|
83 | 83 | findParentWithNodeName,
|
84 | 84 | getWindow,
|
85 | 85 | isChildOf,
|
86 |
| - isChildOfNodeName |
| 86 | + isChildOfNodeName, |
| 87 | + isEditableDivRef |
87 | 88 | } from '$lib/utils/domUtils.js'
|
88 | 89 | import {
|
89 | 90 | convertValue,
|
|
1334 | 1335 | */
|
1335 | 1336 | export async function scrollTo(path: JSONPath, scrollToWhenVisible = true): Promise<void> {
|
1336 | 1337 | documentState = expandPath(json, documentState, path)
|
1337 |
| - await tick() // await rerender |
| 1338 | + await tick() // await rerender (else the element we want to scroll to does not yet exist) |
1338 | 1339 |
|
1339 | 1340 | const elem = findElement(path)
|
1340 | 1341 |
|
|
1570 | 1571 | }
|
1571 | 1572 |
|
1572 | 1573 | // set focus to the hidden input, so we can capture quick keys like Ctrl+X, Ctrl+C, Ctrl+V
|
1573 |
| - setTimeout(() => { |
1574 |
| - if (!activeElementIsChildOf(refJsonEditor)) { |
1575 |
| - focus() |
1576 |
| - } |
1577 |
| - }) |
| 1574 | + focus() |
1578 | 1575 | }
|
1579 | 1576 |
|
1580 | 1577 | function handleExpandAll() {
|
|
1781 | 1778 |
|
1782 | 1779 | if (combo === 'Ctrl+Z') {
|
1783 | 1780 | event.preventDefault()
|
1784 |
| -
|
1785 |
| - // TODO: find a better way to restore focus |
1786 |
| - // TODO: implement a proper TypeScript solution to check whether this is an element with blur, focus, select |
1787 |
| - const activeElement = document.activeElement as HTMLInputElement |
1788 |
| - if (activeElement && activeElement.blur && activeElement.select) { |
1789 |
| - activeElement.blur() |
1790 |
| - setTimeout(() => { |
1791 |
| - handleUndo() |
1792 |
| - setTimeout(() => activeElement?.select()) |
1793 |
| - }) |
1794 |
| - } else { |
1795 |
| - handleUndo() |
1796 |
| - } |
| 1781 | + handleUndo() |
1797 | 1782 | }
|
1798 | 1783 |
|
1799 | 1784 | if (combo === 'Ctrl+Shift+Z') {
|
1800 | 1785 | event.preventDefault()
|
1801 |
| -
|
1802 |
| - // TODO: find a better way to restore focus |
1803 |
| - // TODO: implement a proper TypeScript solution to check whether this is an element with blur, focus, select |
1804 |
| - const activeElement = document.activeElement as HTMLInputElement |
1805 |
| - if (activeElement && activeElement.blur && activeElement.select) { |
1806 |
| - activeElement.blur() |
1807 |
| - setTimeout(() => { |
1808 |
| - handleRedo() |
1809 |
| - setTimeout(() => activeElement?.select()) |
1810 |
| - }) |
1811 |
| - } else { |
1812 |
| - handleRedo() |
1813 |
| - } |
| 1786 | + handleRedo() |
1814 | 1787 | }
|
1815 | 1788 | }
|
1816 | 1789 |
|
1817 |
| - function handleMouseDown(event) { |
| 1790 | + function handleMouseDown(event: MouseEvent & { target: HTMLDivElement }) { |
1818 | 1791 | debug('handleMouseDown', event)
|
1819 | 1792 |
|
1820 |
| - // TODO: ugly to have two setTimeout here. Without it, hiddenInput will blur |
1821 |
| - setTimeout(() => { |
1822 |
| - setTimeout(() => { |
1823 |
| - if (!hasFocus && !isChildOfNodeName(event.target, 'BUTTON')) { |
1824 |
| - // for example when clicking on the empty area in the main menu |
1825 |
| - focus() |
1826 |
| -
|
1827 |
| - if ( |
1828 |
| - !documentState.selection && |
1829 |
| - json === undefined && |
1830 |
| - (text === '' || text === undefined) |
1831 |
| - ) { |
1832 |
| - createDefaultSelection() |
1833 |
| - } |
1834 |
| - } |
1835 |
| - }) |
1836 |
| - }) |
| 1793 | + if (!isChildOfNodeName(event.target, 'BUTTON') && !event.target.isContentEditable) { |
| 1794 | + // for example when clicking on the empty area in the main menu |
| 1795 | + focus() |
| 1796 | +
|
| 1797 | + if (!documentState.selection && json === undefined && (text === '' || text === undefined)) { |
| 1798 | + createDefaultSelection() |
| 1799 | + } |
| 1800 | + } |
1837 | 1801 | }
|
1838 | 1802 |
|
1839 | 1803 | function openContextMenu({
|
|
1966 | 1930 | }
|
1967 | 1931 |
|
1968 | 1932 | const { path, contents } = pastedJson
|
| 1933 | + pastedJson = undefined |
1969 | 1934 |
|
1970 | 1935 | // exit edit mode
|
1971 |
| - updateSelection(createValueSelection(path, false)) |
1972 |
| -
|
1973 |
| - await tick() |
| 1936 | + const refEditableDiv = refContents?.querySelector('.jse-editable-div') || null |
| 1937 | + if (isEditableDivRef(refEditableDiv)) { |
| 1938 | + refEditableDiv.cancel() |
| 1939 | + } |
1974 | 1940 |
|
1975 | 1941 | // replace the value with the JSON object/array
|
1976 | 1942 | const operations: JSONPatchDocument = [
|
|
1986 | 1952 | state: expandRecursive(patchedJson, patchedState, path)
|
1987 | 1953 | }
|
1988 | 1954 | })
|
| 1955 | +
|
| 1956 | + // TODO: get rid of the setTimeout here |
| 1957 | + setTimeout(focus) |
1989 | 1958 | }
|
1990 | 1959 |
|
1991 | 1960 | function handleClearPastedJson() {
|
1992 | 1961 | debug('clear pasted json')
|
1993 | 1962 | pastedJson = undefined
|
| 1963 | + focus() |
1994 | 1964 | }
|
1995 | 1965 |
|
1996 | 1966 | function handleRequestRepair() {
|
|
2035 | 2005 | refHiddenInput.blur()
|
2036 | 2006 | }
|
2037 | 2007 |
|
2038 |
| - // This is ugly: we need to wait until the EditableDiv has triggered onSelect, |
2039 |
| - // and have onSelect call refHiddenInput.focus(). After that we can call blur() |
2040 |
| - // to remove the focus. |
2041 |
| - // TODO: find a better solution |
2042 |
| - tick().then(() => { |
2043 |
| - setTimeout(() => { |
2044 |
| - if (refHiddenInput) { |
2045 |
| - refHiddenInput.blur() |
2046 |
| - } |
2047 |
| - }) |
2048 |
| - }) |
| 2008 | + debug('blur (outside editor)') |
| 2009 | + if (refHiddenInput) { |
| 2010 | + refHiddenInput.blur() |
| 2011 | + } |
2049 | 2012 | }
|
2050 | 2013 | }
|
2051 | 2014 | }
|
|
2240 | 2203 | onClick: handleClearPastedJson
|
2241 | 2204 | }
|
2242 | 2205 | ]}
|
2243 |
| - onClose={() => { |
2244 |
| - // TODO: the need for setTimeout is ugly |
2245 |
| - setTimeout(focus) |
2246 |
| - }} |
2247 | 2206 | />
|
2248 | 2207 | {/if}
|
2249 | 2208 |
|
|
0 commit comments