Hello,
I'm trying to integrate the SHIFT+Enter (<br>) functionality as explained in this support ticket: T959240
I converted the script into a Typescript / react based component but when i try Shift+Enter my cursor only moves one position to the right.
This is the code i wrote:
TypeScriptimport * as React from 'react';
import HtmlEditor from 'devextreme-react/html-editor';
import { Toolbar, Item } from 'devextreme-react/html-editor';
import { Button, Popup, TextArea } from 'devextreme-react';
import * as Quill from 'devextreme-quill';
import { useCallback, useRef, useState, useEffect } from 'react';
const Parchment = Quill.import("parchment");
const Break = Quill.import("blots/break");
const Embed = Quill.import("blots/embed"); //not in use?
const Delta = Quill.import("delta");
const ENTER = 'enter';
Break.prototype.optimize = function () { };
//Break.prototype.insertInto = function (parent : any, ref : any) {
// Embed.prototype.insertInto.call(this, parent, ref);
//};
Break.prototype.length = function () {
return 1;
};
Break.prototype.value = function () {
return "\n";
};
export default () => {
const htmlRef = useRef<HtmlEditor>(null);
const [text, setText] = useState("<p>test text</p><p>test<br>text</p>");
const [showHtmlPopup, setShowHtmlPopup] = useState(false);
//register bindings for SHIFT + ENTER
useEffect(() => {
const quill = htmlRef.current?.instance.getQuillInstance();
if (!quill)
return;
console.log("quill instance", quill);
quill.clipboard.addMatcher("BR", function () {
const newDelta = new Delta();
newDelta.insert({ break: "" });
return newDelta;
});
quill.keyboard.addBinding({
key: ENTER,
handler: function (range: any, context: any) {
if (range.length > 0) {
quill.scroll.deleteAt(range.index, range.length); // So we do not trigger text-change
}
let lineFormats: any = Object.keys(context.format).reduce(function (
lineFormats: any,
format: any
) {
if (
Parchment.query(format, Parchment.Scope.BLOCK) &&
!Array.isArray(context.format[format])
) {
lineFormats[format] = context.format[format];
}
return lineFormats;
},
{});
const previousChar: any = quill.getText(range.index - 1, 1);
// Earlier scroll.deleteAt might have messed up our selection,
// so insertText's built in selection preservation is not reliable
quill.insertText(range.index, "\n", lineFormats, Quill.sources.USER);
if (previousChar === "" || previousChar === "\n") {
quill.setSelection(range.index + 2, Quill.sources.SILENT);
} else {
quill.setSelection(range.index + 1, Quill.sources.SILENT);
}
quill.selection.scrollIntoView();
Object.keys(context.format).forEach((name) => {
if (lineFormats[name] != null) return;
if (Array.isArray(context.format[name])) return;
if (name === "link") return;
quill.format(name, context.format[name], Quill.sources.USER);
});
}
});
quill.keyboard.addBinding({
key: ENTER,
shiftKey: true,
handler: function (range: any, context: any) {
const nextChar: string = quill.getText(range.index + 1, 1);
quill.insertEmbed(range.index, "break", true, "user");
if (nextChar.length === 0) {
// second line break inserts only at the end of parent element
quill.insertEmbed(range.index, "break", true, "user");
}
quill.setSelection(range.index + 1, Quill.sources.SILENT);
}
});
var enterHandlers: any = quill.keyboard.bindings[ENTER];
var customHandlers: any = enterHandlers.splice(enterHandlers.length - 2);
enterHandlers.unshift(...customHandlers);
}, []);
const showEditHtmlPopUp = useCallback(() => {
setShowHtmlPopup(true);
}, [])
const hidePopup = useCallback(() => setShowHtmlPopup(false), []);
const valueChanged = useCallback((e: any) => setText(e.value), [])
return <>
<HtmlEditor
height="100%"
ref={htmlRef}
value={text}
onValueChanged={valueChanged}
>
<Toolbar >
<Item formatName="undo" />
<Item formatName="redo" />
<Item formatName="separator" />
<Item
formatName="size"
/>
<Item formatName="separator" />
<Item formatName="bold" />
<Item formatName="italic" />
<Item formatName="strike" />
<Item formatName="underline" />
<Item formatName="separator" />
<Item formatName="alignLeft" />
<Item formatName="alignCenter" />
<Item formatName="alignRight" />
<Item formatName="alignJustify" />
<Item formatName="separator" />
<Item
formatName="header"
/>
<Item formatName="separator" />
<Item formatName="orderedList" />
<Item formatName="bulletList" />
<Item formatName="separator" />
<Item formatName="color" />
<Item formatName="background" />
<Item formatName="separator" />
<Item formatName="link" />
<Item formatName="image" />
<Item formatName="separator" />
<Item formatName="clear" />
<Item formatName="blockquote" />
<Item formatName="separator" />
<Item formatName="insertTable" />
<Item formatName="insertRowAbove" />
<Item formatName="insertRowBelow" />
<Item formatName="insertColumnLeft" />
<Item formatName="insertColumnRight" />
<Item formatName="deleteRow" />
<Item formatName="deleteColumn" />
<Item formatName="deleteTable" />
<Item formatName="separator" />
<Item>
<Button
icon="variable"
type="normal"
stylingMode="text"
hint="Edit html"
onClick={showEditHtmlPopUp}
/>
</Item>
</Toolbar>
</HtmlEditor>
<Popup
title="Edit html"
visible={showHtmlPopup}
onHiding={hidePopup}
deferRendering
>
<TextArea
value={text}
onValueChanged={valueChanged}
height="100%"
/>
</Popup>
</>;
}
using packages:
"devextreme": "^20.2.5",
"devextreme-quill": "^0.10.2",
"devextreme-react": "^20.2.5",
Did something change in the last release of devextreme? How can i get the Shift + Enter to work in the Html Editor with React / Typescript?
Kind regards,
Vincent