src/views/admin/post_editor.html
<title>edit post</title>
<article class="post edit">
<header>
<h2>edit post</h2>
<h3>{{&title}}</h3>
</header>
<form id="edit" {{&form}}>
<input type="hidden" id="post_id" name="post_id" value="{{&post_id}}" />
<section class="flex-row">
<label for="date">date</label>
<input type="date" id="date" name="date" value="{{&date}}" required onkeydown="return event.key != 'Enter';" />
</section>
<section class="flex-row">
<label for="url">url</label>
<input type="text" name="url" id="url" value="{{&url}}" required pattern="[0-9a-z_]+"
onkeydown="return event.key != 'Enter';" readonly />
<fieldset hx-on:click="customize()">
<input type="checkbox" id="custom" />
<legend>custom?</legend>
<callout id="url_warn"><i class="nf nf-fa-warning"></i> urls must alphanumeric, lowercase, and underscored.
</callout>
</fieldset>
</section>
<section class="flex-row">
<label for="title">title</label>
<input type="text" name="title" id="title" value="{{&title}}" hx-on:keyup="sanitize()" required
onkeydown="return event.key != 'Enter';" hx-target="#url_warn" />
</section>
<section class="flex-row">
<label for="subtitle">subtitle</label>
<input type="text" name="subtitle" id="subtitle" value="{{&subtitle}}" required
onkeydown="return event.key != 'Enter';" />
</section>
<section class="flex-row">
<label for="excerpt">excerpt</label>
<textarea id="excerpt" name="excerpt" required>{{&excerpt}}</textarea>
</section>
<section class="flex-row">
<label for="content">content</label>
<textarea id="content" name="content" required>{{&content}}</textarea>
</section>
<section class="flex-row">
<label for="postTags">tags</label>
<section id="tagCloud">
<input type="hidden" name="tags" value="" />
{{&tagcloud}}
</section>
<input type="text" list="tags" id="postTags" name="postTags" hx-on:change="tagChange()"
placeholder="add tags..." onkeydown="return event.key != 'Enter';" />
<datalist id="tags">
{{&tags}}
</datalist>
</section>
<section class="flex-row">
<label for="postCats">categories</label>
<section id="pounce">
<input type="hidden" name="cats" value="" />
{{&pounce}}
</section>
<input type="text" list="cats" id="postCats" name="postCats" hx-on:change="meow()"
placeholder="add categories..." onkeydown="return event.key != 'Enter';" />
<datalist id="cats">
{{&cats}}
</datalist>
</section>
<section class="flex-row">
<fieldset>
<label for="live">published</label><br />
<input type="checkbox" id="live" name="live" {{&live}} />
<legend>live?</legend>
</fieldset>
</section>
<header>
<button type="submit" id="submitCaptain">save</button>
<button id="preview" onclick="previewPost(event)">preview</button>
</header>
</form>
</article>
<article class="post" id="previewDOM"></article>
<script>
function sanitize() {
if (!htmx.find("#custom").checked) {
htmx.find("#url").value = htmx.find("#title").value.toString().trim().toLowerCase().replace(/ /g, "_").replace(/[^0-9a-z_]/g, "");
}
}
function customize() {
htmx.find("#custom").toggleAttribute("checked");
htmx.find("#url").toggleAttribute("readonly");
htmx.toggleClass(htmx.find("#url_warn"), "revealed");
sanitize();
}
function meow() {
let val = htmx.values(htmx.find("#edit"));
let cat = val["postCats"].toString();
if (!Object.values(val["cats"]).includes(cat)) {
htmx.find("#pounce").innerHTML += `<button onclick="remove(event, 'btn${cat}')" id="btn${cat}" class="cat">${cat}<input type="hidden" name="cats" value="${cat}"/></button>`;
}
htmx.find("#postCats").value = "";
}
function tagChange() {
let val = htmx.values(htmx.find("#edit"));
let tag = val["postTags"].toString();
if (!Object.values(val["tags"]).includes(tag)) {
htmx.find("#tagCloud").innerHTML += `<button onclick="remove(event, 'btn${tag}')" id="btn${tag}" class="tag">${tag}<input type="hidden" name="tags" value="${tag}"/></button>`;
}
htmx.find("#postTags").value = "";
}
function remove(e, id) {
e.preventDefault();
htmx.find("#" + id).outerHTML = '';
}
function previewPost(e) {
e.preventDefault();
let dom = htmx.find('#previewDOM');
let val = htmx.values(htmx.find("#edit"));
dom.innerHTML = "<header><h2>" + val.title + "</h2><h3>" + val.subtitle + '</h3></header>' + val.content;
}
</script>