Fix slug input: free typing with live space→hyphen and lowercasing
Live-filtering through slugify ate hyphens and spaces (trailing hyphens are stripped) and jumped the cursor to the end on mid-text edits. Now only spaces→hyphens and lowercasing happen oninput (length-preserving, cursor stays put); the full slugify runs at commit before the server call, which keeps its own validation.
This commit is contained in:
@@ -106,7 +106,8 @@ function discardPending() {
|
||||
async function commitPending() {
|
||||
const node = pending.value
|
||||
if (!node) return
|
||||
// Empty slug: derive one from the title (transliterated to ASCII).
|
||||
// The typed slug is slugified at commit; empty derives one from the
|
||||
// title (transliterated to ASCII).
|
||||
const slug = slugify(node.slug.trim()) || slugify(node.title)
|
||||
if (!slug) {
|
||||
return
|
||||
@@ -216,10 +217,13 @@ function onTitleInput(node, ev) {
|
||||
})
|
||||
}
|
||||
|
||||
// The slug inputs are filtered as you type (StructureTree onSlugInput,
|
||||
// see slugify.js); the server re-validates and its reason is shown.
|
||||
// Slug inputs are typed freely (spaces become hyphens live, see
|
||||
// StructureTree onSlugInput); the value is slugified here at commit
|
||||
// (blur/Enter) before talking to the server, which re-validates (e.g.
|
||||
// reserved names) and its reason is shown.
|
||||
async function commitSlug(node, ev) {
|
||||
const slug = ev.target.value.trim()
|
||||
const slug = slugify(ev.target.value.trim())
|
||||
ev.target.value = slug
|
||||
if (slug === node.slug) return
|
||||
const parent = node.path.split('/').slice(0, -1).join('/')
|
||||
// Empty slug at top level = the front page (path "").
|
||||
|
||||
@@ -34,16 +34,17 @@ const props = defineProps({
|
||||
|
||||
const handlers = inject('structureHandlers')
|
||||
|
||||
// Live-filter the slug inputs as they are typed (oninput): invalid
|
||||
// characters are simply not accepted, spaces become hyphens and unicode
|
||||
// folds to ASCII (see slugify.js). Existing rows commit on change, the
|
||||
// pending row is v-modeled.
|
||||
function onSlugInput(ev) {
|
||||
ev.target.value = slugify(ev.target.value)
|
||||
}
|
||||
|
||||
function onPendingSlugInput(element, ev) {
|
||||
element.slug = slugify(ev.target.value)
|
||||
// Slug inputs accept free typing; the only live rewrites are turning
|
||||
// spaces into hyphens and lowercasing (both keep the length for ASCII,
|
||||
// so the cursor stays put). Anything else (unicode folding, stripping,
|
||||
// collapsing) is left for commit time, where the value is run through
|
||||
// slugify before talking to the server (StructureEditor). `element` is
|
||||
// the pending row (v-modeled), null for existing rows (plain :value
|
||||
// binding, read back on commit).
|
||||
function onSlugInput(element, ev) {
|
||||
const v = ev.target.value.replace(/\s/g, '-').toLowerCase()
|
||||
ev.target.value = v
|
||||
if (element) element.slug = v
|
||||
}
|
||||
|
||||
// Focus the title input of a fresh pending row.
|
||||
@@ -113,7 +114,7 @@ function onEnd() {
|
||||
class="edit slug-edit"
|
||||
:placeholder="slugify(element.title)"
|
||||
title="Slug (last path segment) — empty: derived from the title"
|
||||
@input="onPendingSlugInput(element, $event)"
|
||||
@input="onSlugInput(element, $event)"
|
||||
@keyup.enter="handlers.commitPending()"
|
||||
@keyup.esc="handlers.discardPending()"
|
||||
/>
|
||||
@@ -135,7 +136,7 @@ function onEnd() {
|
||||
:value="element.slug"
|
||||
placeholder="front page"
|
||||
title="Slug (last path segment) — renames move the whole subtree. Empty at top level = front page"
|
||||
@input="onSlugInput"
|
||||
@input="onSlugInput(null, $event)"
|
||||
@change="handlers.commitSlug(element, $event)"
|
||||
/>
|
||||
<span class="acts">
|
||||
|
||||
Reference in New Issue
Block a user