Hi All,
So i have been working on a custom button to insert product content into a draft editor but it is currently breaking the pointer location. I am assume this is because of the text characters I am inserting or the tag.
How can I make the text inside none selectable and treat this element like an image?
Do you think this is what is breaking my selection?

for example if you tried to make a link in the blue block it would make a new line at max
Hey @stagfoo did you have any luck with this feature? Im current working on a component build on top of CKEditor so I can drag and drop 'isolated islands' all over the text. However integrating Ckeditor on my React UI is kinda hassle so I would love to use something like Draft.js to implement that. I think what you're doing is kind of similar even though you're not using drag'n drop for your custom-buttom. Maybe we can share some thoughts on it :)
This is how my component looks so far:

I did but I'm out of the office, next time I'm back I will post my solution.
so i did this as a decorator like so
function findImageEntities(contentBlock, callback) {
//get all text
const text = contentBlock.getText();
//find just []()
const IMG = /(\[.*?\]\()(.+?)(\))/g;
let match;
while ((match = IMG.exec(text)) !== null) {
const start = match.index;
const end = start + match[0].length;
callback(start, end);
}
}
const Image = (props) => {
let height = 'auto';
let width = 'auto';
let src;
//get the text found by the above function [image](imageUrl =100x100)
let split = props.decoratedText.split('(')[1].split(')')[0];
src = split.split('=')[0].trim();
split = split.split('=')[1].split('x');
height = split[1];
width = split[0];
// return fully customisable tag
return (
<span>
<img alt="" src={src} height={height} width={width} />
</span>
);
};
this is a simple example but you can do all your custom calls to product data inside the const Image function
const decorator = new CompositeDecorator([
{
strategy: findProductCode,
component: productComp,
},
{
strategy: findLinkEntities,
component: Link,
},
{
strategy: findImageEntities,
component: Image,
},
]);
Check the documentation on decorators in draft
https://facebook.github.io/draft-js/docs/advanced-topics-decorators.html#content
Drag and drop is also on draft-js-plugins.com
To insert the content into draft I use this function
function insertHtmlBlock(currentEditorState, html, state) {
console.log(convertFromHTML(html));
const rawObject = convertToRaw(currentEditorState.getCurrentContent());
const enterObject = {};
const processedHTML = DraftPasteProcessor.processHTML(html);
enterObject.depth = processedHTML[0].depth;
enterObject.key = processedHTML[0].key;
enterObject.text = processedHTML[0].text;
enterObject.type = processedHTML[0].type;
enterObject.depth = processedHTML[0].depth;
enterObject.data = processedHTML[0].data;
enterObject.entityRanges = [];
enterObject.inlineStyleRanges = [];
rawObject.blocks.push(enterObject);
const newContentState = convertFromRaw(rawObject);
state.setState({ editorState: EditorState.push(currentEditorState, newContentState, 'insert-fragment') });
}
Example button
this.confirmImage = () => {
const { editorState } = this.state;
insertHtmlBlock(editorState, `<p></p>`, this);
};
and this is be changed to the Image component.
Awesome answer @stagfoo! I will take a look on the documentation of it. Thank you so much!
@stagfoo could you please tell me how to get DraftPasteProcessor ? thank u
@neove Its in the draft-js package but not exported
import DraftPasteProcessor from 'draft-js/lib/DraftPasteProcessor';
for Images its actually better to use an Atomic Blocks.
Atomic blocks don't have selection issues and only take up one char and you pass in a custom component, which allows you to add a delete button.
https://github.com/facebook/draft-js/blob/master/examples/draft-0-9-1/media/media.html
I would say if you want to edit the text inside use decorators
If you don't want text inside use Atomic Block.
Most helpful comment
@neove Its in the draft-js package but not exported
import DraftPasteProcessor from 'draft-js/lib/DraftPasteProcessor';