diff --git a/src/Editor.ts b/src/Editor.ts index 549aca9..5bf720f 100644 --- a/src/Editor.ts +++ b/src/Editor.ts @@ -214,9 +214,9 @@ export class Editor { setStyleFromObj(newStyle: CSSObj): void { const rootNode = document.getElementById(this.editorDivId) as Node; const selAdj = getAdjSelection(true, rootNode); + if (!selAdj || !newStyle || !selAdj.startNode) {return;} - newStyle = this.setAlignment(selAdj, newStyle); - if (!newStyle || Object.keys(newStyle).length === 0) {return;} + if (!newStyle || Object.keys(newStyle).length === 0) {return;} if (selAdj && selAdj.startNode && !selAdj.isEmpty) { this.updateStyleAndOptimize(rootNode, selAdj, newStyle); } else { @@ -264,6 +264,7 @@ export class Editor { * @param newStyle - New style which should be applied on selection area. */ updateStyleAndOptimize(rootNode: Node, sel: SelectionAdj, newStyle: CSSObj): void { + newStyle = this.setAlignment(sel, newStyle); setStyle(sel, newStyle); if (!rootNode.textContent) {return;} // Optimize DOM structure after style update @@ -290,6 +291,7 @@ export class Editor { * @param newStyle - New style which should be applied on selection area. */ setCursorStyle(selAdj: SelectionAdj, newStyle: CSSObj): void { + newStyle = this.setAlignment(selAdj, newStyle); let cursorNd = selAdj.startNode; if (cursorNd.textContent !== "\u200b") { cursorNd = this.insertEmptySpan(selAdj.startNode, selAdj.startOffset); diff --git a/src/SelectionAdj.ts b/src/SelectionAdj.ts index b7ce18d..50b51fe 100644 --- a/src/SelectionAdj.ts +++ b/src/SelectionAdj.ts @@ -50,14 +50,17 @@ export function getAdjSelection(splitNodes: boolean, rootNode: Node): SelectionA const sel = window.getSelection(); if (!sel || !sel.anchorNode || !sel.anchorNode.parentNode || !sel.focusNode || !rootNode) {return;} + const anchorHierarchy = getNodeHierarchy(sel.anchorNode, rootNode); + const focusHierarchy = getNodeHierarchy(sel.focusNode, rootNode); + if (!anchorHierarchy.includes(rootNode) || !focusHierarchy.includes(rootNode)) {return;} + const selIsOneNode = sel.anchorNode.isSameNode(sel.focusNode); let commonNode: Node = sel.anchorNode.parentNode; let reverseSelection = sel.anchorOffset < sel.focusOffset || !selIsOneNode ? false : true; if (!selIsOneNode) { - const anchorHierarchy = getNodeHierarchy(sel.anchorNode, rootNode); - const focusHierarchy = getNodeHierarchy(sel.focusNode, rootNode); + commonNode = getCommonNode(anchorHierarchy, focusHierarchy); reverseSelection = isReverseSelection(anchorHierarchy, focusHierarchy, commonNode); } diff --git a/src/ToolsPanel/Inputs/DropDownButton.ts b/src/ToolsPanel/Inputs/DropDownButton.ts index 74fbde4..a4ec7a1 100644 --- a/src/ToolsPanel/Inputs/DropDownButton.ts +++ b/src/ToolsPanel/Inputs/DropDownButton.ts @@ -14,6 +14,18 @@ const buttonStyle: CSSObj = { 'background': 'transparent', } +/** + * Styles for button when pressed(active). + */ +const unselectableStyle: CSSObj = { + selector: ".unselectable > *", + "-moz-user-select": "-moz-none", + "-khtml-user-select": "none", + "-webkit-user-select": "none", + "-ms-user-select": "none", + "user-select": "none", +} + /** * Styles for button when pressed(active). */ @@ -26,7 +38,7 @@ const buttonStyleActive: CSSObj = { * Node with button styles. * Yes I know ,I can use css. It's just more fun to work with DOM directly. */ -const buttonStyleNode = buildStyleNode(buttonStyle, buttonStyleActive); +const buttonStyleNode = buildStyleNode(buttonStyle, buttonStyleActive, unselectableStyle); /** * Implementation of base class for dropdown button @@ -44,8 +56,10 @@ export class DropDownButton { this.button = this.buildButton(); this.dropDownArrow = new DropDownArrow(() => {}); + this.Element.appendChild(buttonStyleNode); this.Element.appendChild(this.button); this.Element.appendChild(this.dropDownArrow.Element); + this.Element.classList.add("unselectable"); this.connectEventHandlers(); } @@ -87,7 +101,6 @@ export class DropDownButton { button.style.flexDirection = "column"; button.style.justifyContent = "center"; button.style.alignItems = "center"; - button.appendChild(buttonStyleNode); button.classList.add("buttonStyle"); return button; } diff --git a/tests/Editor.test.ts b/tests/Editor.test.ts index b319bf5..b830fc7 100644 --- a/tests/Editor.test.ts +++ b/tests/Editor.test.ts @@ -525,33 +525,6 @@ describe('Testing setStyleFromObj', () => { expect(updateStyleAndOptimizeMock.mock.calls[0][1]).toEqual(sel); expect(updateStyleAndOptimizeMock.mock.calls[0][2]).toEqual(style); }); - - test('only set alignment', () => { - const {editor, editorDiv, editorP, txtNd} = buildEditor(); - const updateStyleAndOptimizeMock = jest.fn(); - const setCursorStyleMock = jest.fn(); - const setAlignmentMock = jest.fn(); - - const sel: SelectionAdj = { - startNode: txtNd, - startOffset: 1, - endNode: txtNd, - endOffset: 5, - commonNode: editorP, - isEmpty: false - }; - getAdjSelectionMock.mockReturnValue(sel); - setAlignmentMock.mockReturnValue({}); - - editor.updateStyleAndOptimize = updateStyleAndOptimizeMock; - editor.setCursorStyle = setCursorStyleMock; - - const style = {"text-align": "left"} as CSSObj; - editor.setStyleFromObj(style); - - expect(setCursorStyleMock.mock.calls).toHaveLength(0); - expect(updateStyleAndOptimizeMock.mock.calls).toHaveLength(0); - }); }); describe('Testing setAlignment', () => {