Skip to content

Commit

Permalink
Merge pull request #11 from dvnrsn/master
Browse files Browse the repository at this point in the history
fix onBlur never firing save()
  • Loading branch information
joeldenning authored Feb 21, 2019
2 parents 2b0f699 + 72c6df6 commit f8591e8
Showing 1 changed file with 22 additions and 17 deletions.
39 changes: 22 additions & 17 deletions src/rich-text-editor.component.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,8 @@ let globalBandicootId = 0
export const RichTextEditor = forwardRef((props, editorRef) => {
const divRef = useRef(null)
const selectionRangeBeforeBlurRef = useRef(null)
const [ focused, setFocused ] = useState(() => false)
const [ focused, setFocused ] = useState(null)
const richTextContext = useContext(RichTextContext)
const unchangedTimeout = useRef(null)
const bandicootId = useRef(globalBandicootId++)
const [lastSavedHTML, setLastSavedHTML] = useState(props.initialHTML)

Expand Down Expand Up @@ -45,20 +44,36 @@ export const RichTextEditor = forwardRef((props, editorRef) => {

useEffect(() => {
if (props.save && props.unchangedInterval && divRef.current && focused) {
setTimeout(save, props.unchangedInterval)
const mutationConfig = {attributes: true, childList: true, subtree: true, characterData: true}
let timeout
const observer = new MutationObserver(() => {
clearTimeout(unchangedTimeout.current)
unchangedTimeout.current = setTimeout(save, props.unchangedInterval)
clearTimeout(timeout)
timeout = setTimeout(save, props.unchangedInterval)
})
observer.observe(divRef.current, mutationConfig)
return () => {
observer.disconnect()
clearTimeout(unchangedTimeout.current)
clearTimeout(timeout)
}
}
}, [props.unchangedInterval, props.save, divRef.current, focused])

useEffect(() => {
// Clicking on bandicoot richtext buttons triggers a blur event that will setFocus to false we want to delay the
// save event that is triggered by blur events. 100ms is arbitrary. Whenever react rerenders the rich-text-editor
// due to focused state changing we need to either clear the blurTimeout to prevent a save action from firing
// (in the case of a quick refocus triggered by the rich text buttons) or fire a save event after waiting 100ms
if (focused === false) {
const timeout = setTimeout(() => {
richTextContext.fireBlur()
save()
}, 100)
return () => {
clearTimeout(timeout)
}
}
}, [focused])

useEffect(() => {
richTextContext.selectRangeFromBeforeBlur = () => {
if (divRef.current && document.activeElement !== divRef.current && !divRef.current.contains(document.activeElement)) {
Expand Down Expand Up @@ -101,24 +116,14 @@ export const RichTextEditor = forwardRef((props, editorRef) => {
return (
<div
contentEditable
onBlur={onBlur}
onBlur={() => setFocused(false)}
onFocus={onFocus}
ref={divRef}
className={props.className + " bandicoot-id-" + bandicootId.current}
data-placeholder={props.placeholder}
/>
)

function onBlur() {
setFocused(false)
setTimeout(() => {
if (!focused) {
richTextContext.fireBlur()
save()
}
}, 100)
}

function onFocus() {
setFocused(true)
const selection = window.getSelection()
Expand Down

0 comments on commit f8591e8

Please sign in to comment.