smarkform
Version:
[](https://www.npmjs.com/package/smarkform)
192 lines (178 loc) โข 8.81 kB
HTML
<html style='--background-image-url: url("https://picsum.photos/id/972/800.jpg");'>
<head>
<title>TODO-List Example</title>
<meta name='viewport' content='width=device-width, initial-scale=1.0'>
<meta http-equiv='Content-Type' content='text/html; charset=utf-8'>
<link rel='stylesheet' href='/resources/dist/examples/smarkform_layout_sample.css?foo=0.7776419866765434'>
<link rel='stylesheet' href='/resources/dist/examples/smarkform_styles_sample.css?foo=0.727267112615217'>
<script>
const bgImg = `https://picsum.photos/id/${1+Math.floor(Math.random()*1084)}/800.jpg`;
document.documentElement.style.setProperty('--background-image-url', `url("${bgImg}")`);
document.addEventListener("DOMContentLoaded", function() {
const backgroundAnchor = document.getElementById("background-anchor");
if (backgroundAnchor) backgroundAnchor.href = bgImg;
});
</script>
<script defer src='/resources/dist/SmarkForm.umd.js?foo=0.563786617206983'></script>
<script>
document.addEventListener('DOMContentLoaded', function() {
// <!-- BEGIN controller sample-->
// Essential:
// ==========
// SmarkForm instantiation:
const myForm = new SmarkForm(document.querySelector("#main-form"));
// Import / Export data handling:
// ==============================
// Do Something on export action:
myForm.on("AfterAction_export"
, ({data})=>alert (JSON.stringify(data, null, 4))
);
// Fetching data on import action (example):
myForm.on("BeforeAction_import", (options) => {
let data = prompt('Provide JSON data');
try {
options.data = JSON.parse(data);
} catch (err) {
if (data.length) {
alert ('โ ๏ธ Invalid JSON!!');
data = null; // Emulate prompt cancel.
} else {
data = {}; // Drop form contents
};
};
if (data === null) options.preventDefault();
});
// Aesthetic enhancements:
// =======================
// Ask for confirm on clear action
myForm.on("BeforeAction_clear", async ({context, preventDefault}) => {
// Ask for confirmation:
if (
context.getPath() == "/" // Only for the whole form
&& ! await context.isEmpty() // Don't even ask if already empty
&& ! confirm("Are you sure?")
) preventDefault(); // Abort if user cancelled
});
// Allow for list items addition/removal CSS animation:
// (Propperly and/remove "animated_item" and "ongoing" CSS classes)
const delay = ms=>new Promise(resolve=>setTimeout(resolve, ms));
myForm.on("afterRender", async function(ev) {
if (ev.context.parent?.options.type !== "list") return; /* Only for list items */
const item = ev.context.targetNode;
item.classList.add("animated_item");
await delay(1); /* Important: Allow DOM to update */
item.classList.add("ongoing");
});
myForm.on("beforeUnrender", async function(ev) {
if (ev.context.parent?.options.type !== "list") return; /* Only for list items */
const item = ev.context.targetNode;
item.classList.remove("ongoing");
/* Await for transition to be finished before item removal: */
await delay(150);
});
// <!-- END controller sample-->
});
</script>
</head>
<body>
<div class='main-container'>
<div class='smarkForm' id='main-form'>
<header>
<h1>TODO-List Example</h1>
<style>
.credits {
background: rgba(255, 255, 255, .7);
padding: 1em 1.5em;
margin: .3em;
font-size: small;
}
.credits, .credits a {
color: darkblue;
}
.credits .subtitle, .credits .subtitle a {
color: darkgrey;
font-weight: bold;
}
.credits .description {
color: black;
}
.credits ul {
margin-left: .2em;
list-style-type: none;
}
.credits li::before {
content: "๐";
margin-right: 5px;
}
</style>
<div class='credits'>
<p class='subtitle'>This is an <a href='https://smarkform.bitifet.net'>SmarkForm</a> demonstration page.</p>
<p class='description'>
This example shows how to create a complete TO-DO list interface
with just a few HTML lines.
</p>
<ul>
<li>
Complete documentation at
<a href='https://smarkform.bitifet.net'>https://smarkform.bitifet.net</a>.
</li>
<li>
Latest version and more examples at
<a href='https://smarkform.bitifet.net/resources/examples'>https://smarkform.bitifet.net/resources/examples</a>
</li>
<li>
GitHub:
<a href='https://github.com/bitifet/SmarkForm'>https://github.com/bitifet/SmarkForm</a>.
</li>
<li>
NPM:
<a href='https://www.npmjs.com/package/smarkform'>https://www.npmjs.com/package/smarkform</a>.
</li>
<li> <a id='background-anchor' href='#'>Background image</a>
courtesy of
<a href='https://picsum.photos/'>Lorem Picsum</a>
</li>
</ul>
</div>
</header>
<!-- BEGIN SmarkForm sample-->
<section>
<div class='form-group h1 nowrap'>
<div class='spacer'></div>
<button data-smark='{"action":"import","context":"tasklist"}'><span role='img' aria-label=''>๐</span> Import (JSON)</button>
<button data-smark='{"action":"export","context":"tasklist"}'><span role='img' aria-label=''>๐พ</span> Export (JSON)</button>
</div>
<div data-smark='{"type":"list","name":"tasklist","sortable":true,"exportEmpties":true,"min_items":0}'>
<fieldset class='form-group aside reverse' data-smark='{"exportEmpties":false}'>
<button class='inline' data-smark='{"action":"removeItem"}' title='Remove task'><span role='img' aria-label='Remove task'>โ</span></button>
<div class='form-group spacer'>
<div class='form-group'><span data-smark='{"action":"position"}'>/</span><span> </span>
<input data-smark name='title' type='text' placeholder='Task title'>
</div>
<div class='form-group'>
<div class='input-group'><strong data-smark='label'>Goals</strong>
<div data-smark='{"name":"goals","type":"list","of":"input","sortable":true,"max_items":100}'>
<div class='singleton'>
<button data-smark='{"action":"removeItem","failback":"clear","hotkey":"-"}' title='Remove this item'><span role='img' aria-label='Remove this item'>โ</span></button>
<input data-smark='data-smark' type='text' placeholder='New goal...'/>
<button data-smark='{"action":"addItem","hotkey":"+"}' title='Add new item below'><span role='img' aria-label='Add new item'>โ</span></button>
</div>
</div>
</div>
</div>
</div>
</fieldset>
</div>
<div class='form-group f1 nowrap' style='text-align: right'>
<div class='spacer'></div>
<button data-smark='{"action":"clear","context":"tasklist","autoscroll":"elegant"}' title='Clear form data'><span role='img' aria-label=''>โ</span> Clear all</button>
<button data-smark='{"action":"removeItem","context":"tasklist","target":"*","autoscroll":"elegant","preserve_non_empty":true}' title='Clear all empty tasks'><span role='img' aria-label=''>๐งน</span> Clear empty</button>
<button data-smark='{"action":"addItem","context":"tasklist"}'><span role='img' aria-label=''>โ</span> Add new task</button>
</div>
</section>
<!-- END SmarkForm sample-->
</div>
</div>
</body>
</html>