' +
+ '
' +
escapeHtml(entry.title || '') +
'
' +
- '
' +
+ '
' +
escapeHtml(entry.artist || '') +
'
' +
'
' +
@@ -112,18 +114,43 @@
}
// ── 인라인 편집 (제목/가수) ─────────────────────────
+ // 기본 상태에서는 contenteditable 이 꺼져 있어서 row 어디를 클릭해도 드래그가 시작된다.
+ // 더블클릭 시점에 해당 칸만 contenteditable 로 켜고, 드래그는 일시 비활성화.
+ // blur 또는 Enter 키로 편집 종료 + 상태 저장 + 드래그 복원.
function attachInlineEdit(li, idx) {
- li.querySelectorAll('[contenteditable="true"]').forEach(function (el) {
- el.addEventListener('focus', function () { li.draggable = false })
- el.addEventListener('blur', function () { li.draggable = true })
- el.addEventListener('input', function () {
+ li.querySelectorAll('[data-field]').forEach(function (el) {
+ el.addEventListener('mousedown', function (e) {
+ // 편집 모드일 때만 드래그를 막아서 텍스트 선택을 허용.
+ if (el.getAttribute('contenteditable') === 'true') e.stopPropagation()
+ })
+ el.addEventListener('dblclick', function (e) {
+ e.stopPropagation()
+ if (el.getAttribute('contenteditable') === 'true') return
+ el.setAttribute('contenteditable', 'true')
+ li.draggable = false
+ el.focus()
+ try {
+ var range = document.createRange()
+ range.selectNodeContents(el)
+ var sel = window.getSelection()
+ sel.removeAllRanges()
+ sel.addRange(range)
+ } catch (_) {}
+ })
+ el.addEventListener('blur', function () {
+ if (el.getAttribute('contenteditable') !== 'true') return
+ el.removeAttribute('contenteditable')
+ li.draggable = true
var field = el.getAttribute('data-field')
var value = (el.textContent || '').replace(/\r?\n/g, ' ').trim()
+ if (!state.music[idx]) return
if (field === 'title') state.music[idx].title = value
else if (field === 'artist') state.music[idx].artist = value
})
el.addEventListener('keydown', function (e) {
+ if (el.getAttribute('contenteditable') !== 'true') return
if (e.key === 'Enter') { e.preventDefault(); el.blur() }
+ else if (e.key === 'Escape') { e.preventDefault(); el.blur() }
})
})
}