Skip to content

Instantly share code, notes, and snippets.

@varunajmera0
Last active July 31, 2019 11:38
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 varunajmera0/0ffa6c899e4de4b8729996103042405e to your computer and use it in GitHub Desktop.
Save varunajmera0/0ffa6c899e4de4b8729996103042405e to your computer and use it in GitHub Desktop.
I was trying to create entity when # appears but when you remove/delete multiple selected text it is not working properly.
//https://stackoverflow.com/a/49214278
//https://github.com/facebook/draft-js/issues/506#issuecomment-230123013 #for word find
import decorateComponentWithProps from 'decorate-component-with-props';
import Hashtag from './Hashtag/index';
import hashtagStrategy from './hashtagStrategy';
import styles from './styles.css';
import {
EditorState, SelectionState, Modifier, getDefaultKeyBinding, KeyBindingUtil, genKey, ContentBlock, ContentState,
} from 'draft-js';
import {extractHashtagsWithIndices} from "./utils";
const defaultTheme = {
hashtag: styles.hashtag,
};
let reset = 0;
const specialChars = ['!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '+', '-', '=', '[', ']', '{', '}', '\\', '|', ':', ';', '\'', '"', ',', '<', '>', '?', '/', '~', '`', '.', ','];
let eddd = ''
export default (config = {}) => {
// Styles are overwritten instead of merged as merging causes a lot of confusion.
//
// Why? Because when merging a developer needs to know all of the underlying
// styles which needs a deep dive into the code. Merging also makes it prone to
// errors when upgrading as basically every styling change would become a major
// breaking change. 1px of an increased padding can break a whole layout.
const theme = config.theme ? config.theme : defaultTheme;
return {
decorators: [
{
strategy: hashtagStrategy,
component: decorateComponentWithProps(Hashtag, {theme}),
},
],
keyBindingFn: e => {
const {hasCommandModifier} = KeyBindingUtil;
//e.keyCode = 32 (space)
//e.keyCode = 13 (enter)
//e.keyCode = 190 (period/.)
if (e.keyCode === 32 && !hasCommandModifier(e)) {
return "createHashTagEntityWithSpace";
}else if(e.keyCode === 13 && !hasCommandModifier(e)){
return "createHashTagEntityWithEnter";
}else if (specialChars.includes(e.key)){
if (e.key === '#') {
reset = 1;
}
return e.key;
}else if(e.key === '#' && !hasCommandModifier(e)){
reset = 1;
return e.key;
} else if (reset === 1) {
if (e.which >= 65 && e.which <= 90){
return e.key
}
else if (e.which === 8) {
reset = 1
return e.key
}
reset = 0;
return getDefaultKeyBinding(e);
}else if (e.which === 8) {
const {currentBlock, blockText, start, end} = getInsertRange(eddd);
const selectionState = eddd.getSelection();
const endWord = selectionState.getEndOffset();
let slicedText = currentBlock.getText().slice(0, endWord);
const pp = extractHashtagsWithIndices(slicedText)
if (pp.length > 0 && endWord <= pp.slice(-1)[0].indices[0] && endWord >=pp.slice(-1)[0].indices[1]) {
reset = 1
return e.key
}
return getDefaultKeyBinding(e);
}
return getDefaultKeyBinding(e);
},
handleKeyCommand: (command, editorState, {setEditorState}) => {
if (command === "createHashTagEntityWithSpace") {
const hashTagEntity = addHashTag(editorState, 32);
setEditorState(hashTagEntity, hashTagEntity.getSelection(), hashTagEntity.getCurrentContent().getLastCreatedEntityKey());
return "handled";
} else if(command === "createHashTagEntityWithEnter") {
const hashTagEntity = addHashTag(editorState, 13);
setEditorState(hashTagEntity, hashTagEntity.getSelection(), hashTagEntity.getCurrentContent().getLastCreatedEntityKey());
return "handled";
} else if (specialChars.includes(command)) {
const hashTagEntity = addHashTag(editorState, command);
setEditorState(hashTagEntity, hashTagEntity.getSelection(), hashTagEntity.getCurrentContent().getLastCreatedEntityKey());
return "handled";
} else if (reset === 1) {
if (command === 'Backspace'){
const h = updateEntity(eddd)
setEditorState(h, h.getSelection(), h.getCurrentContent().getLastCreatedEntityKey());
}else {
const hashTagEntity = addHashTag(editorState, command);
setEditorState(hashTagEntity, hashTagEntity.getSelection(), hashTagEntity.getCurrentContent().getLastCreatedEntityKey());
}
return "handled";
} else if (command === 'Backspace') {
const h = updateEntity(editorState)
setEditorState(h, h.getSelection(), h.getCurrentContent().getLastCreatedEntityKey());
return "handled";
}
return "not-handled";
},
};
};
let entityKey = [];
const getInsertRange = (editorState) => {
const currentSelectionState = editorState.getSelection();
const end = currentSelectionState.getAnchorOffset();
const anchorKey = currentSelectionState.getAnchorKey();
const currentContent = editorState.getCurrentContent();
const currentBlock = currentContent.getBlockForKey(anchorKey);
const blockText = currentBlock.getText();
const start = blockText.substring(0, end).lastIndexOf('#');
return {
currentBlock,
blockText,
start,
end,
};
};
const addEmptyBlock = (editorState) => {
const blockKey = genKey();
const newBlock = new ContentBlock({
key: blockKey,
type: 'unstyled',
text: ''
});
const contentState = editorState.getCurrentContent();
const newBlockMap = contentState.getBlockMap().set(newBlock.key, newBlock);
const selection = new SelectionState({
anchorKey: blockKey,
anchorOffset: 0,
focusKey: blockKey,
focusOffset: 0,
});
return EditorState.forceSelection(
EditorState.push(editorState, ContentState.createFromBlockArray(newBlockMap.toArray())),
selection
);
};
function updateEntity(editorState) {
const contentState = editorState.getCurrentContent();
const {currentBlock, blockText, start, end} = getInsertRange(editorState);
const selectionState = editorState.getSelection();
const endWord = selectionState.getEndOffset();
let slicedText = currentBlock.getText().slice(0, endWord);
let startWord = slicedText.lastIndexOf(" ");
if (startWord === -1) {
startWord = 0;
}
const word = slicedText.slice(startWord).trim();
console.log("word updateEntity====>", word)
//(word.match(/#/g) || []).length === 1
// not more than 2 hashtags in one string
if (word.includes('#') && (word.match(/#/g) || []).length === 1) {
console.log("hahah", word)
let newContentState;
const selectionWord = new SelectionState({ anchorKey: currentBlock.getKey(),
anchorOffset: start,
focusKey: currentBlock.getKey(),
focusOffset: endWord,
hasFocus: true
});
if (word.length === 2){
newContentState = Modifier.applyEntity(
contentState,
selectionWord,
null
);
const newContentStateWithSpace = EditorState.push(editorState,
newContentState,
`insert-characters`,
);
const wor = '';
console.log("word.length", word.length, start)
newContentState = Modifier.replaceText(
newContentStateWithSpace.getCurrentContent(),
selectionWord,
wor,
null,
entityKey.slice(-1)[0]
);
reset = 0
}else if (word.length ===1) {
newContentState = Modifier.replaceText(
contentState,
selectionWord,
'',
null,
entityKey.slice(-1)[0].toString()
);
entityKey.pop()
reset=0
} else{
console.log("laste entity key getLastCreatedEntityKey=>", entityKey)
// console.log("conentState", start.toString(), editorState.getEntityAt(contentState.getLastCreatedEntityKey()))
contentState.replaceEntityData(entityKey.slice(-1)[0].toString(), {word: word.substring(0, word.length - endWord.length)});
newContentState = Modifier.replaceText(
contentState,
selectionWord,
`${word.substring(0, word.length - endWord)}`,
null,
entityKey.slice(-1)[0].toString()
);
entityKey.pop()
}
return EditorState.push(editorState,
newContentState,
`insert-characters`,
);
}
}
const addHashTag = (editorState, key) => {
const contentState = editorState.getCurrentContent();
let newContentState = contentState;
const {currentBlock, blockText, start, end} = getInsertRange(editorState);
// console.log("endWord", start, end)
const selectionState = editorState.getSelection();
const endWord = selectionState.getEndOffset();
let slicedText = currentBlock.getText().slice(0, endWord);
const pp = extractHashtagsWithIndices(slicedText)
let startWord = slicedText.lastIndexOf(" ");
if (startWord === -1) {
startWord = 0;
}
const word = slicedText.slice(startWord).trim();
if (word.includes('#') && (word.match(/#/g) || []).length === 1) {
const selectionWord = new SelectionState({ anchorKey: currentBlock.getKey(),
anchorOffset: start,
focusKey: currentBlock.getKey(),
focusOffset: end,
hasFocus: true
});
const contentStateWithEntity = contentState.createEntity('HASHTAG',
'MUTABLE',
{
word,
}
);
entityKey.push(contentStateWithEntity.getLastCreatedEntityKey())
if (key === 32) {
newContentState = Modifier.replaceText(
contentStateWithEntity,
selectionWord,
`${word}`,
null,
entityKey.slice(-1)[0]
);
const newContentStateWithSpace = EditorState.push(editorState,
newContentState,
`insert-characters`,
);
newContentState = Modifier.insertText(
newContentStateWithSpace.getCurrentContent(),
selectionState,
" "
);
reset = 0;
} else if (key === 13) {
newContentState = Modifier.replaceText(
contentStateWithEntity,
selectionWord,
`${word}`,
null,
entityKey.slice(-1)[0]
);
const newContentStateWithEnter = EditorState.push(editorState,
newContentState,
`insert-characters`,
);
reset = 0;
return addEmptyBlock(newContentStateWithEnter)
} else if (specialChars.includes(key)){
newContentState = Modifier.replaceText(
contentStateWithEntity,
selectionWord,
`${word}`,
null,
entityKey.slice(-1)[0]
);
const newContentStateWithSpecialChar = EditorState.push(editorState,
newContentState,
`insert-characters`,
);
newContentState = Modifier.insertText(
newContentStateWithSpecialChar.getCurrentContent(),
selectionState,
(key === '#' || key === '@') ? (pp.length > 1 ? ` ${key}` : `${key}`) : `${key}`
);
if (key === '#') {
reset = 1;
} else {
reset = 0;
}
} else if (reset === 1) {
newContentState = Modifier.replaceText(
contentStateWithEntity,
selectionWord,
`${word}`,
null,
entityKey.slice(-1)[0]
);
const newContentStateWithSpecialChar = EditorState.push(editorState,
newContentState,
`insert-characters`,
);
newContentState = Modifier.insertText(
newContentStateWithSpecialChar.getCurrentContent(),
selectionState,
key
);
}else if (key === '') {
newContentState = Modifier.replaceText(
contentStateWithEntity,
selectionWord,
`${word}`,
null,
entityKey.slice(-1)[0]
);
}
} else {
if (key === 32){
newContentState = Modifier.insertText(
contentState,
selectionState,
" "
);
} else if (key === 13){
return addEmptyBlock(editorState)
} else if (specialChars.includes(key)) {
newContentState = Modifier.insertText(
contentState,
selectionState,
key === '#' ? (pp.length > 1 ? ` ${key}` : `${key}`) : `${key}`
);
}
}
if (!newContentState.equals(contentState)) {
return EditorState.push( editorState,
newContentState,
`insert-characters`,
);
}
return editorState;
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment