Use urlencoded data for sending to server.

Improve outlook for progressive enhancement.

Add Cancel-link
This commit is contained in:
Magnus Hoff 2017-09-05 11:41:37 +02:00
parent 0bc4c69579
commit 7946a6f321
2 changed files with 60 additions and 19 deletions

View file

@ -8,10 +8,11 @@
</div> </div>
<div class="editor"> <div class="editor">
<form action="" method="POST"> <form action="" method="POST">
<input type=hidden name=revision value="{{revision}}"> <input type=hidden name=baseRevision value="{{revision}}">
<textarea autocomplete=off name=body>{{raw}}</textarea> <textarea autocomplete=off name=body>{{raw}}</textarea>
<textarea autocomplete=off class="shadow-control"></textarea> <textarea autocomplete=off class="shadow-control"></textarea>
<div class="editor-controls"> <div class="editor-controls">
<a href="{{article_id}}">Cancel</a>
<button type=submit>Save</button> <button type=submit>Save</button>
</div> </div>
</form> </form>
@ -19,7 +20,7 @@
</article> </article>
<footer> <footer>
<p><a id="openEditor" href="?editor=true">Edit</a></p> <p><a id="openEditor" href="?editor">Edit</a></p>
<dl> <dl>
<dt>Article ID</dt> <dt>Article ID</dt>
<dd>{{article_id}}</dd> <dd>{{article_id}}</dd>
@ -34,38 +35,64 @@
<script> <script>
function autosizeTextarea(textarea, shadow) { function autosizeTextarea(textarea, shadow) {
shadow.value = textarea.value;
shadow.style.width = textarea.clientWidth + "px"; shadow.style.width = textarea.clientWidth + "px";
shadow.style.height = "auto"; shadow.value = textarea.value;
textarea.style.height = shadow.scrollHeight + "px"; textarea.style.height = shadow.scrollHeight + "px";
} }
function queryArgsFromForm(form) {
const items = [];
for (const {name, value} of form.elements) {
if (!name) continue;
items.push(encodeURIComponent(name) + '=' + encodeURIComponent(value));
}
return items.join('&');
}
function openEditor() { function openEditor() {
const article = document.querySelector("article");
const rendered = document.querySelector(".rendered"); const rendered = document.querySelector(".rendered");
const editor = document.querySelector(".editor"); const editor = document.querySelector(".editor");
const textarea = editor.querySelector('textarea[name="body"]'); const textarea = editor.querySelector('textarea[name="body"]');
const shadow = editor.querySelector('textarea.shadow-control'); const shadow = editor.querySelector('textarea.shadow-control');
editor.style.display = "block"; textarea.style.height = rendered.clientHeight + "px";
article.classList.add('edit');
autosizeTextarea(textarea, shadow); autosizeTextarea(textarea, shadow);
textarea.addEventListener('input', () => autosizeTextarea(textarea, shadow)); textarea.addEventListener('input', () => autosizeTextarea(textarea, shadow));
window.addEventListener('resize', () => autosizeTextarea(textarea, shadow)); window.addEventListener('resize', () => autosizeTextarea(textarea, shadow));
rendered.style.display = "none";
const form = editor.querySelector("form"); const form = editor.querySelector("form");
form.addEventListener("submit", async function (ev) { form.addEventListener("submit", function (ev) {
(async function () {
ev.preventDefault(); ev.preventDefault();
ev.stopPropagation(); ev.stopPropagation();
const body = queryArgsFromForm(form);
textarea.disabled = true;
const response = await fetch( const response = await fetch(
form.getAttribute("action"), form.getAttribute("action"),
{ {
method: 'PUT', method: 'PUT',
body: new FormData(form), headers: {
"Content-Type": "application/x-www-form-urlencoded"
},
body: body,
} }
); );
if (!response.ok) throw new Error("Unexpected status code (" + response.status + ")");
textarea.disabled = false;
}()
.catch(err => {
textarea.disabled = false;
console.error(err);
alert(err);
}));
}); });
textarea.focus(); textarea.focus();

View file

@ -142,12 +142,26 @@ textarea {
.shadow-control { .shadow-control {
visibility: hidden; visibility: hidden;
position: fixed; position: fixed;
height: auto;
min-height: 100px;
} }
.editor { .editor {
display: none; display: none;
} }
.editor textarea {
height: 600px;
}
.edit .editor {
display: block;
}
.edit .rendered {
display: none;
}
.editor-controls { .editor-controls {
position: fixed; position: fixed;
right: 0; right: 0;
@ -165,7 +179,7 @@ textarea {
right: 20px; right: 20px;
bottom: 20px; bottom: 20px;
box-shadow: 5px 5px 8px rgba(0,0,0, 0.3); box-shadow: 2px 2px 8px rgba(0,0,0, 0.25);
} }
} }
</style> </style>