Fix controlling contenteditable div innerText

This commit is contained in:
josdejong 2020-05-06 10:47:48 +02:00
parent 2b73c6e6bf
commit e9116cc36c
2 changed files with 73 additions and 36 deletions

View File

@ -31,6 +31,7 @@
}
}
},
'': '',
'string': 'Hello World',
'url': 'https://jsoneditoronline.org',
'Lorem Ipsum': 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.'
@ -117,7 +118,7 @@
<div class="editor">
<JSONEditor
json={json}
bind:json={json}
onChange={handleChange}
/>
</div>

View File

@ -21,6 +21,9 @@
let limit = DEFAULT_LIMIT
let domKey
let domValue
$: type = valueType (value)
let prevValue = undefined
@ -49,13 +52,37 @@
: false
})
$: valueClass = classnames('value', type, {
url: valueIsUrl,
empty: escapedValue.length === 0,
search: searchResult
? !!searchResult[SEARCH_VALUE]
: false
})
$: valueClass = getValueClass(value)
$: if (domKey) {
if (document.activeElement !== domKey || escapedKey === '') {
// synchronize the innerText of the editable div with the escaped value,
// but only when the domValue does not have focus else we will ruin
// the cursor position.
domKey.innerText = escapedKey
}
}
$: if (domValue) {
if (document.activeElement !== domValue || escapedValue === '') {
// synchronize the innerText of the editable div with the escaped value,
// but only when the domValue does not have focus else we will ruin
// the cursor position.
domValue.innerText = escapedValue
}
}
function getValueClass (value) {
const type = valueType (value)
return classnames('value', type, {
url: isUrl(value),
empty: escapedValue.length === 0,
search: searchResult
? !!searchResult[SEARCH_VALUE]
: false
})
}
function toggle () {
expanded = !expanded
@ -66,12 +93,22 @@
onChangeKey(newKey, key)
}
function handleKeyBlur () {
// make sure differences in escaped text like with new lines is updated
domKey.innerText = escapedValue
}
function handleValueInput (event) {
const valueText = unescapeHTML(getInnerText(event.target))
const newValue = stringConvert(valueText) // TODO: implement support for type "string"
onChangeValue(newValue, key)
}
function handleValueBlur () {
// make sure differences in escaped text like with new lines is updated
domValue.innerText = escapedValue
}
function handleValueClick (event) {
if (valueIsUrl && event.ctrlKey) {
event.preventDefault()
@ -152,9 +189,9 @@
contenteditable="true"
spellcheck="false"
on:input={handleKeyInput}
>
{escapedKey}
</div>
on:blur={handleKeyBlur}
bind:this={domKey}
/>
<div class="separator">:</div>
{/if}
{#if expanded}
@ -201,9 +238,9 @@
contenteditable="true"
spellcheck="false"
on:input={handleKeyInput}
>
{escapedKey}
</div>
on:blur={handleKeyBlur}
bind:this={domKey}
/>
<span class="separator">:</span>
{/if}
{#if expanded}
@ -238,9 +275,9 @@
contenteditable="true"
spellcheck="false"
on:input={handleKeyInput}
>
{escapedKey}
</div>
on:blur={handleKeyBlur}
bind:this={domKey}
/>
<span class="separator">:</span>
{/if}
<div
@ -248,12 +285,12 @@
contenteditable="true"
spellcheck="false"
on:input={handleValueInput}
on:blur={handleValueBlur}
on:click={handleValueClick}
on:keydown={handleValueKeyDown}
bind:this={domValue}
title={valueIsUrl ? 'Ctrl+Click or Ctrl+Enter to open url in new window' : null}
>
{escapedValue}
</div>
/>
</div>
{/if}
</div>
@ -386,24 +423,23 @@
}
div.empty {
border: 1px dotted lightgray;
border-radius: 2px;
padding: 0 $input-padding;
line-height: 17px;
}
&:not(:focus) {
outline: 1px dotted lightgray;
-moz-outline-radius: 2px;
}
div.empty::after,
div.empty::after {
pointer-events: none;
color: lightgray;
}
&::after {
pointer-events: none;
color: lightgray;
}
div.key.empty::after {
content: 'key';
}
&.key::after {
content: 'key';
}
div.value.empty::after {
content: 'value';
&.value::after {
content: 'value';
}
}
.key.search,