Skip to content

Instantly share code, notes, and snippets.

@5ally
Last active August 26, 2021 17:12
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save 5ally/7e6006c990ddbade5b6742933c0ff34b to your computer and use it in GitHub Desktop.
Save 5ally/7e6006c990ddbade5b6742933c0ff34b to your computer and use it in GitHub Desktop.
image-block.js (cw-blocks/responsive-image) - see https://wordpress.stackexchange.com/q/393769 for details, but check the revision to see what I changed/added
// MY VERSION OF YOUR CODE
//import React from 'react'; // Why do you need this?
if (wp.element && wp.editor) { // *I don't think this is necessary
const { __ } = wp.i18n; // Import __() from wp.i18n
const {
registerBlockType,
getBlockDefaultClassName
} = wp.blocks;
const {
useBlockProps,
MediaUploadCheck,
InspectorControls,
MediaUpload,
} = wp.blockEditor;
const {
Button,
PanelBody,
PanelRow,
SelectControl,
TextControl,
ToggleControl,
} = wp.components;
// 1. See lines 15 & 16 above.
/*
const {
InspectorControls,
MediaUpload
} = wp.editor;
*/
const { serverSideRender: ServerSideRender } = wp;
const el = wp.element.createElement;
// 2. Import useSelect from the @wordpress/data package. We'll use it in the
// edit function to retrieve the image object from the REST API, using
// getEntityRecord().
const { useSelect } = wp.data;
const icon = el('svg',{
xmlns: 'http://www.w3.org/2000/svg',
viewBox: '0 0 93 93',
},
el('title', 'icon' ),
el('g',{
id: 'Layer_2',
'data-name': 'Layer 2'
},
el('g',{
id: 'Layer_1-2',
'data-name': 'Layer 1'
},
el('path',{
d: 'M30,30V93H93V30ZM80.47,61l-19,19L50.66,69.11,36,83.77V36H87V67.52Z'
}),
el('circle',{
cx: '46.21',
cy: '46.53',
r: '5.76',
}),
el('polygon', {
points: '6 87 6 6 87 6 87 13 93 13 93 0 0 0 0 93 13 93 13 87 6 87'
}),
el('polygon', {
points: '21 87 21 21 87 21 87 28 93 28 93 15 15 15 15 93 28 93 28 87 21 87'
}),
)
)
);
registerBlockType('cw-blocks/responsive-image', {
title: 'Responsive Image',
icon: icon,
category: 'embed',
attributes: {
imgW: {
type: 'number',
default: 1600,
},
imgH: {
type: 'number',
default: 1200,
},
imgWMed: {
type: 'number',
default: 800,
},
imgHMed: {
type: 'number',
default: 600,
},
imgWSmall: {
type: 'number',
default: 400,
},
imgHSmall: {
type: 'number',
default: 300,
},
crop: {
type: 'boolean',
default: false,
},
linkURL: {
type: 'string',
default: ''
},
targetBlank: {
type: 'boolean',
default: false
},
pos: {
type: 'string', // 3. Changed it from 'text' to 'string'
default: ''
},
// 4. Remove this attribute.
/*
imgDataObj: {
type: 'array', // *This should actually be object.
default: {}
},
*/
imgID: {
type: 'number', // 5. Media/post IDs are numbers, so I used 'number'.
default: 0
}
},
edit: (props) => {
//const blockProps = useBlockProps(); // *See note #12 below
const { className, setAttributes, attributes } = props;
//const { attributes } = props; // *See above
// 6. Add imgDataObj as a constant in this function.
// *Note that imgDataObj might be undefined when getEntityRecord() is first called.
const imgDataObj = useSelect( select => {
const { getEntityRecord } = select( 'core' );
return attributes.imgID && getEntityRecord( 'root', 'media', attributes.imgID );
}, [ attributes.imgID ] );
//console.log( imgDataObj );
const setImgData = function (media){ // *I renamed imgDataObj to 'media'.
//setAttributes({ imgDataObj: imgDataObj }); // 7. Remove this
setAttributes({ imgID: media.id }); // 8. You should use .id and not ['id']
//console.log( media ); // *The items are different than those in imgDataObj
}
const resetImgData = function (){
//setAttributes({ imgDataObj: {} }); // 9. Remove this
setAttributes({ imgID: 0 });
}
// 10. In the following, I replaced props.attributes.imgDataObj with just imgDataObj
// 11. I also replaced attributes.imgDataObj.url with imgDataObj.source_url and
// attributes.imgDataObj.width with imgDataObj.media_details.width
// 12. When returning an array of elements, each top-level element should have
// a unique key.
return [
<InspectorControls key="key-1">
<PanelBody title="Image" initialOpen={true}>
<MediaUploadCheck>
<MediaUpload
className="cw-resp-image wp-admin-cw-resp-image"
allowedTypes={['image']}
multiple={false}
value={imgDataObj ? imgDataObj.id : ''}
onSelect={setImgData}
render={({ open }) => (
imgDataObj ?
<div>
<p>
<img src={imgDataObj.source_url} width={imgDataObj.media_details.width / 2} />
</p>
<p>
<Button onClick={resetImgData} className="button is-small">Remove</Button>
</p>
</div> :
<Button onClick={open} className="button">Select/Upload Image</Button>
)}
/>
</MediaUploadCheck>
<SelectControl
label="Position"
value={props.attributes.pos}
onChange={(pos) => setAttributes({ pos: pos })}
options={[
{ label: 'Left', value: 'left' },
{ label: 'Center', value: 'center' },
{ label: 'Right', value: 'right' },
]}
/>
</PanelBody>
<PanelBody title="URL" initialOpen={false}>
<TextControl
label="URL"
value={props.attributes.linkURL}
onChange={(linkURL) => setAttributes({ linkURL: linkURL })}
type="text"
/>
<ToggleControl
label="Open link in new tab"
checked={props.attributes.targetBlank}
onChange={(targetBlank) => setAttributes({ targetBlank: targetBlank })}
/>
</PanelBody>
<PanelBody title="Sizes" initialOpen={true}>
<PanelRow>
<p>Both width and height are required to create a cropped image.</p>
</PanelRow>
<TextControl
label="Small Width (phones)"
value={props.attributes.imgWSmall}
onChange={(imgWSmall) => setAttributes({ imgWSmall: parseInt(imgWSmall) })}
type="number"
/>
<TextControl
label="Small Height (phones)"
value={props.attributes.imgHSmall}
onChange={(imgHSmall) => setAttributes({ imgHSmall: parseInt(imgHSmall) })}
type="number"
/>
<TextControl
label="Medium Width (tablets)"
value={props.attributes.imgWMed}
onChange={(imgWMed) => setAttributes({ imgWMed: parseInt(imgWMed) })}
type="number"
/>
<TextControl
label="Medium Height (tablets)"
value={props.attributes.imgHMed}
onChange={(imgHMed) => setAttributes({ imgHMed: parseInt(imgHMed) })}
type="number"
/>
<TextControl
label="Large Width (desktop)"
value={props.attributes.imgW}
onChange={(imgW) => setAttributes({ imgW: parseInt(imgW) })}
type="number"
/>
<TextControl
label="Large Height (desktop)"
value={props.attributes.imgH}
onChange={(imgH) => setAttributes({ imgH: parseInt(imgH) })}
type="number"
/>
</PanelBody>
<PanelBody title="Options" initialOpen={false}>
<ToggleControl
label="Crop"
checked={props.attributes.crop}
onChange={(crop) => setAttributes({ crop: crop })}
/>
</PanelBody>
</InspectorControls>,
<div {...useBlockProps( { key: 'key-2' } )}>
<ServerSideRender
block="cw-blocks/responsive-image"
attributes={{
// no image object sent here
imgW: attributes.imgW,
imgH: attributes.imgH,
imgWMed: attributes.imgWMed,
imgHMed: attributes.imgHMed,
imgWSmall: attributes.imgWSmall,
imgHSmall: attributes.imgHSmall,
crop: attributes.crop,
loading: attributes.loading,
linkURL: attributes.linkURL,
targetBlank: attributes.targetBlank,
pos: attributes.pos,
imgID: attributes.imgID,
}}
/>
</div>
];
},
save: () => {
return null;
},
});
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment