admin管理员组

文章数量:1123950

  • I have extended core/group block to add different background image when its being viewed on smaller view port.
  • I would like to know what will be best approach to add class name here which I did in my code or something other also doubt is if I choose to change image with CSS then for all groups in single page background image on mobile device will be same and if I choose to do it with JS then on page refresh only it will get triggered.
/**
 * WordPress dependencies
 */
const { addFilter } = wp.hooks;
const { InspectorControls } = wp.blockEditor;
const { PanelBody } = wpponents;
const { createHigherOrderComponent } = wppose;
const { MediaUpload, MediaUploadCheck } = wp.blockEditor;
const { Fragment } = wp.element;
const { __ } = wp.i18n;

/**
 * Adds the mobileBackgroundImage attribute to the group block settings.
 *
 * @param {Object} settings - The block settings.
 * @return {Object} - The updated block settings.
 */
function addMobileBackgroundImageAttribute( settings ) {
    if ( 'core/group' !== settings.name ) {
        return settings; // Return settings even if the block name doesn't match
    }

    settings.attributes = {
        ...settings.attributes,
        mobileBackgroundImage: {
            type: 'string',
            default: '',
        },
    };

    return settings;
}

addFilter( 'blocks.registerBlockType', 'addMobileBackgroundImageAttribute', addMobileBackgroundImageAttribute );

/**
 * Higher Order Component to add class name and inspector controls to core/group block.
 * This HOC adds a mobile background image control to the core/group block.
 *
 * @param {Function} BlockEdit - Original component.
 * @return {Function} - New component.
 */
const withClassNameAndInspectorControls = createHigherOrderComponent( ( BlockEdit ) => {
    return ( props ) => {
        const { name, attributes, setAttributes } = props;

        if ( 'core/group' !== name ) {
            return <BlockEdit { ...props } />;
        }

        const oldClassList = attributes.className ? attributes.className : '';
        const removeClass = oldClassList?.replace( 'has-mobile-background-image', '' );

        return (
            <>
                <BlockEdit { ...props } />
                <InspectorControls group="styles">
                    <PanelBody title={ __( 'Mobile Background Image', 'features' ) }>
                        <MediaUploadCheck>
                            <MediaUpload
                                onSelect={ ( media ) => {
                                    setAttributes( { mobileBackgroundImage: media.url, className: oldClassList + ' has-mobile-background-image' } );
                                } }
                                type="image"
                                value={ attributes.mobileBackgroundImage }
                                render={ ( { open } ) => (
                                    <>
                                        <button className="button button-large" onClick={ open }>
                                            { attributes.mobileBackgroundImage ? __( 'Change Image', 'features' ) : __( 'Select Image', 'features' ) }
                                        </button>
                                        { attributes.mobileBackgroundImage && (
                                            <>
                                                <img src={ attributes.mobileBackgroundImage } alt={ __( 'Mobile Background', 'features' ) } className="mobile-background-image" style={ { marginTop: '10px', maxWidth: '100%' } } />
                                                <button
                                                    className="button button-large"
                                                    onClick={ () => {
                                                        setAttributes( { mobileBackgroundImage: '', className: removeClass } );
                                                    } }
                                                >
                                                    { __( 'Remove Image', 'features' ) }
                                                </button>
                                            </>
                                        ) }
                                    </>
                                ) }
                            />
                        </MediaUploadCheck>
                    </PanelBody>
                </InspectorControls>
            </>
        );
    };
}, 'withClassNameAndInspectorControls' );

addFilter( 'editor.BlockEdit', 'addMobileBackgroundImageControl', withClassNameAndInspectorControls );

/**
 * Higher Order Component to add class name to core/group block in the editor.
 *
 * @param {Function} BlockListBlock - Original component.
 * @return {Function} - New component.
 */
const addEditorClass = createHigherOrderComponent( ( BlockListBlock ) => {
    return ( props ) => {
        const { wrapperProps, name, attributes } = props;

        if ( ! [ 'core/group' ].includes( name ) ) {
            return <BlockListBlock { ...props } wrapperProps={ wrapperProps } />;
        }

        const newWrapperProps = {
            ...wrapperProps,
            ...( attributes.mobileBackgroundImage &&
            {
                'data-mobile-background-image': attributes.mobileBackgroundImage,
            } ),
        };

        return <BlockListBlock { ...props } wrapperProps={ newWrapperProps } />;
    };
}, 'withTooltip' );

wp.hooks.addFilter( 'editor.BlockListBlock', 'features', addEditorClass );

/**
 * Adds the mobileBackgroundImage attribute to the group block settings.
 *
 * @param {Object} settings - The block settings.
 * @return {Object} - The updated block settings.
 */
addFilter( 'blocks.getSaveContent.extraProps', 'addClassNameToGroupBlockFrontend', ( extraProps, blockType, attributes ) => {
    if ( attributes?.mobileBackgroundImage ) {
        return {
            ...extraProps,
            'data-mobile-background-image': attributes.mobileBackgroundImage,
        };
    }
    return extraProps;
} );
add_filter( 'render_block_core/group', array( $this, 'extend_core_group_block' ), 10, 3 );

public function extend_core_group_block( $block_content, $block, $instance ) {
        // Add JavaScript to dynamically set background images.


        $image_path = '';
        if(isset($instance->parsed_block['attrs']['mobileBackgroundImage'])){
            $image_path = esc_url( $instance->parsed_block['attrs']['mobileBackgroundImage'] );
        }

        if(isset($image_path) && $image_path !== ''){
        ?>
        
        <style>
            @media screen and (max-width: 768px){
                .wp-block-group.has-mobile-background-image {
                    background-image: url(<?php echo $image_path; ?>) !important;
                    background-size: cover;
                }
            }
        </style>
        <?php
        }

        wp_add_inline_script(
            'jquery',
            '
            jQuery(document).ready(function($) {
                if ($(window).width() < 768) {
                    $(".wp-block-group.has-mobile-background-image").each(function() {
                        var backgroundImageURL = $(this).data("mobile-background-image");
                        $(this).css("background-image", "url(" + backgroundImageURL + ")");
                        $(this).css("background-size", "cover");
                    });
                }
            });
        '
        );

        return $block_content;
    }
  • latest update on code
public function extend_core_group_block( $block_content, $block, $instance ) {

        $image_path = '';
        if(isset($instance->parsed_block['attrs']['mobileBackgroundImage'])){
            $image_path = ( $instance->parsed_block['attrs']['mobileBackgroundImage'] );
            var_dump($image_path);
            wp_add_inline_style(
                'up1512001-2024-styles',
                '@media (max-width: 768px){
                    .wp-block-group.has-mobile-background-image[data-mobile-background-image="' . $image_path . '"] {
                        background-image: url(' . esc_url($image_path) . ') !important;
                    }
                }'
            );
        }

        return $block_content;
    }
  • I have extended core/group block to add different background image when its being viewed on smaller view port.
  • I would like to know what will be best approach to add class name here which I did in my code or something other also doubt is if I choose to change image with CSS then for all groups in single page background image on mobile device will be same and if I choose to do it with JS then on page refresh only it will get triggered.
/**
 * WordPress dependencies
 */
const { addFilter } = wp.hooks;
const { InspectorControls } = wp.blockEditor;
const { PanelBody } = wp.components;
const { createHigherOrderComponent } = wp.compose;
const { MediaUpload, MediaUploadCheck } = wp.blockEditor;
const { Fragment } = wp.element;
const { __ } = wp.i18n;

/**
 * Adds the mobileBackgroundImage attribute to the group block settings.
 *
 * @param {Object} settings - The block settings.
 * @return {Object} - The updated block settings.
 */
function addMobileBackgroundImageAttribute( settings ) {
    if ( 'core/group' !== settings.name ) {
        return settings; // Return settings even if the block name doesn't match
    }

    settings.attributes = {
        ...settings.attributes,
        mobileBackgroundImage: {
            type: 'string',
            default: '',
        },
    };

    return settings;
}

addFilter( 'blocks.registerBlockType', 'addMobileBackgroundImageAttribute', addMobileBackgroundImageAttribute );

/**
 * Higher Order Component to add class name and inspector controls to core/group block.
 * This HOC adds a mobile background image control to the core/group block.
 *
 * @param {Function} BlockEdit - Original component.
 * @return {Function} - New component.
 */
const withClassNameAndInspectorControls = createHigherOrderComponent( ( BlockEdit ) => {
    return ( props ) => {
        const { name, attributes, setAttributes } = props;

        if ( 'core/group' !== name ) {
            return <BlockEdit { ...props } />;
        }

        const oldClassList = attributes.className ? attributes.className : '';
        const removeClass = oldClassList?.replace( 'has-mobile-background-image', '' );

        return (
            <>
                <BlockEdit { ...props } />
                <InspectorControls group="styles">
                    <PanelBody title={ __( 'Mobile Background Image', 'features' ) }>
                        <MediaUploadCheck>
                            <MediaUpload
                                onSelect={ ( media ) => {
                                    setAttributes( { mobileBackgroundImage: media.url, className: oldClassList + ' has-mobile-background-image' } );
                                } }
                                type="image"
                                value={ attributes.mobileBackgroundImage }
                                render={ ( { open } ) => (
                                    <>
                                        <button className="button button-large" onClick={ open }>
                                            { attributes.mobileBackgroundImage ? __( 'Change Image', 'features' ) : __( 'Select Image', 'features' ) }
                                        </button>
                                        { attributes.mobileBackgroundImage && (
                                            <>
                                                <img src={ attributes.mobileBackgroundImage } alt={ __( 'Mobile Background', 'features' ) } className="mobile-background-image" style={ { marginTop: '10px', maxWidth: '100%' } } />
                                                <button
                                                    className="button button-large"
                                                    onClick={ () => {
                                                        setAttributes( { mobileBackgroundImage: '', className: removeClass } );
                                                    } }
                                                >
                                                    { __( 'Remove Image', 'features' ) }
                                                </button>
                                            </>
                                        ) }
                                    </>
                                ) }
                            />
                        </MediaUploadCheck>
                    </PanelBody>
                </InspectorControls>
            </>
        );
    };
}, 'withClassNameAndInspectorControls' );

addFilter( 'editor.BlockEdit', 'addMobileBackgroundImageControl', withClassNameAndInspectorControls );

/**
 * Higher Order Component to add class name to core/group block in the editor.
 *
 * @param {Function} BlockListBlock - Original component.
 * @return {Function} - New component.
 */
const addEditorClass = createHigherOrderComponent( ( BlockListBlock ) => {
    return ( props ) => {
        const { wrapperProps, name, attributes } = props;

        if ( ! [ 'core/group' ].includes( name ) ) {
            return <BlockListBlock { ...props } wrapperProps={ wrapperProps } />;
        }

        const newWrapperProps = {
            ...wrapperProps,
            ...( attributes.mobileBackgroundImage &&
            {
                'data-mobile-background-image': attributes.mobileBackgroundImage,
            } ),
        };

        return <BlockListBlock { ...props } wrapperProps={ newWrapperProps } />;
    };
}, 'withTooltip' );

wp.hooks.addFilter( 'editor.BlockListBlock', 'features', addEditorClass );

/**
 * Adds the mobileBackgroundImage attribute to the group block settings.
 *
 * @param {Object} settings - The block settings.
 * @return {Object} - The updated block settings.
 */
addFilter( 'blocks.getSaveContent.extraProps', 'addClassNameToGroupBlockFrontend', ( extraProps, blockType, attributes ) => {
    if ( attributes?.mobileBackgroundImage ) {
        return {
            ...extraProps,
            'data-mobile-background-image': attributes.mobileBackgroundImage,
        };
    }
    return extraProps;
} );
add_filter( 'render_block_core/group', array( $this, 'extend_core_group_block' ), 10, 3 );

public function extend_core_group_block( $block_content, $block, $instance ) {
        // Add JavaScript to dynamically set background images.


        $image_path = '';
        if(isset($instance->parsed_block['attrs']['mobileBackgroundImage'])){
            $image_path = esc_url( $instance->parsed_block['attrs']['mobileBackgroundImage'] );
        }

        if(isset($image_path) && $image_path !== ''){
        ?>
        
        <style>
            @media screen and (max-width: 768px){
                .wp-block-group.has-mobile-background-image {
                    background-image: url(<?php echo $image_path; ?>) !important;
                    background-size: cover;
                }
            }
        </style>
        <?php
        }

        wp_add_inline_script(
            'jquery',
            '
            jQuery(document).ready(function($) {
                if ($(window).width() < 768) {
                    $(".wp-block-group.has-mobile-background-image").each(function() {
                        var backgroundImageURL = $(this).data("mobile-background-image");
                        $(this).css("background-image", "url(" + backgroundImageURL + ")");
                        $(this).css("background-size", "cover");
                    });
                }
            });
        '
        );

        return $block_content;
    }
  • latest update on code
public function extend_core_group_block( $block_content, $block, $instance ) {

        $image_path = '';
        if(isset($instance->parsed_block['attrs']['mobileBackgroundImage'])){
            $image_path = ( $instance->parsed_block['attrs']['mobileBackgroundImage'] );
            var_dump($image_path);
            wp_add_inline_style(
                'up1512001-2024-styles',
                '@media (max-width: 768px){
                    .wp-block-group.has-mobile-background-image[data-mobile-background-image="' . $image_path . '"] {
                        background-image: url(' . esc_url($image_path) . ') !important;
                    }
                }'
            );
        }

        return $block_content;
    }
Share Improve this question edited Mar 20, 2024 at 16:18 up1512001 asked Mar 20, 2024 at 10:02 up1512001up1512001 236 bronze badges 15
  • I'm not sure why you have a call to wp_add_inline_script with JS to remove/show the CSS when there's a CSS media query that does that already. Is this not already handled by the cover block? A cover block with a style variant that hid its background image when the page is wider than 768px would do this without any filters or JS to mess with the frontend – Tom J Nowell Commented Mar 20, 2024 at 11:21
  • I need specific behaviour for core/group block and I have showed two approaches one with media query and another with wp_add_inline_script but doing this with media query will apply same image to all group block present in page and doing with inline script will only trigger on page refresh. So how should I handle this? – up1512001 Commented Mar 20, 2024 at 11:37
  • The current media query outputs the same rule but with different attributes repeatedly, if it used the ID it would be more specific, and wouldn't put background images on all group blocks. Likewise if you inserted the background image with an inline style you could flip the media query and use it to set all group blocks above a certain size to have no background image. It also sounds like this is an X Y problem for an unnamed issue that requires you to have this specific behaviour for the group block. If you can explain why you need that behaviour it can help avoid Q's and give better answers – Tom J Nowell Commented Mar 20, 2024 at 11:42
  • I don't think by default, the core/group block has given any IDs I guess need to set it as an attribute and then update the image accordingly. I am working on a project in which there are two different images are set as background images (one for desktop and one for mobile) the designer doesn't want to change it and the manager doesn't want to use the visibility plugin so this is the whole story of extending core/group block. – up1512001 Commented Mar 20, 2024 at 11:59
  • 1 As per the docs Styles will only be added if the stylesheet is already in the queue., though in this case I don't believe it's an appropriate use to call it inside a block renderer like that – Tom J Nowell Commented Mar 21, 2024 at 10:20
 |  Show 10 more comments

1 Answer 1

Reset to default 1
  • As I am extending core/group block to add option for setting different image for smaller displays I used render_block_core/group filter to add style tag.
  • I am already adding data-mobile-background-image to each group for its mobile view background image so there is no need for updating it through ID as suggested by Tom J Nowell.

Final Code for setting image using only CSS


add_filter( 'render_block_core/group', array( $this, 'extend_core_group_block' ), 10, 3 );

public function extend_core_group_block( $block_content, $block, $instance ) {

        if ( isset( $instance->parsed_block['attrs']['mobileBackgroundImage'] ) ) {
            $image_path     = ( $instance->parsed_block['attrs']['mobileBackgroundImage'] );
            $block_content .= '
                <style>
                    @media (max-width: 768px){
                        .wp-block-group.has-mobile-background-image[data-mobile-background-image="' . esc_attr( $image_path ) . '"] {
                            background-image: url(' . esc_url( $image_path ) . ') !important;
                        }
                    }
                </style>
            ';
        }

        return $block_content;
    }

本文标签: pluginsBest approach to change mobile background image and adding its class