Last active
July 31, 2019 11:38
-
-
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.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//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