summaryrefslogtreecommitdiff
path: root/static
diff options
context:
space:
mode:
Diffstat (limited to 'static')
-rw-r--r--static/css/standard.css26
-rw-r--r--static/index.html23
-rw-r--r--static/js/ajax.js47
-rw-r--r--static/js/slug.js10
4 files changed, 102 insertions, 4 deletions
diff --git a/static/css/standard.css b/static/css/standard.css
index c5fa6b9..d7acfdc 100644
--- a/static/css/standard.css
+++ b/static/css/standard.css
@@ -70,6 +70,9 @@ body {
font-family: var(--cflems-ff-text-primary);
font-size: 14pt;
}
+#content #rhs p {
+ margin-bottom: 0.5rem;
+}
.form-element {
margin: 1rem 0;
}
@@ -101,6 +104,15 @@ body {
#shortenButton:active {
background-color: #5f80be;
}
+#shortenButton.error {
+ background-color: #b2022f;
+}
+#shortenButton.error:hover {
+ background-color: #a0012a;
+}
+#shortenButton.error:active {
+ background-color: #900025;
+}
.form-element p .fullsize {
flex-grow: 1;
}
@@ -128,9 +140,9 @@ body {
@media (prefers-color-scheme: dark) {
body {
- color: #fdfbf9;
+ color: #e0e0e0;
background-image:
- linear-gradient(to top, #000000f0 20%, #00000090 50%, #00000050),
+ linear-gradient(to top, #000000f0 20%, #00000090 50%, #00000070),
url('https://cdn.cflems.net/fle.ms/earth.webp');
}
#content a {
@@ -160,8 +172,16 @@ body {
#shortenButton:active {
background-color: #68369b;
}
+ #shortenButton.error {
+ background-color: #74001d;
+ }
+ #shortenButton.error:hover {
+ background-color: #68001a;
+ }
+ #shortenButton.error:active {
+ background-color: #5d0017;
+ }
.form-element input[type=text], .form-element button {
border-color: none;
- /*box-shadow: 0rem 0rem 0.5rem #fdfbf9b0;*/
}
}
diff --git a/static/index.html b/static/index.html
index 25d0fd9..ccd7f42 100644
--- a/static/index.html
+++ b/static/index.html
@@ -9,6 +9,8 @@
<link rel="stylesheet" type="text/css" href="css/standard.css" />
<link rel="stylesheet" type="text/css" href="css/mobile.css" />
<title>fle.ms</title>
+ <script type="text/javascript" src="js/slug.js" async></script>
+ <script type="text/javascript" src="js/ajax.js" defer></script>
</head>
<body>
<div id="header">
@@ -32,7 +34,26 @@
</div>
</div>
<div id="rhs">
- <p>A URL shortener is a thing that does blah blah blah.</p>
+ <h3>What is this?</h3>
+ <p>fle.ms is an REST API driven URL shortener&mdash;a service which stores
+ long and complicated URLs such as Google Drive documents, GitHub commit
+ references, Spotify playlists, and social media permalinks. Our service
+ replaces these long links that are hard to remember and share,
+ with short alphanumeric slugs and keywords that you can say or type out
+ in one go.
+ </p>
+ <h3>Why this service over another?</h3>
+ <p>Popular URL shorteners, like most other real estate on the internet,
+ have become saturated over their long tenure. Relevant keywords, names,
+ and even short random slugs are all taken, leading to longer and less
+ meaningful links. This is a fresh start.
+ </p>
+ <p>fle.ms places an emphasis on readability and communicability, so our
+ service ignores capitalization entirely. An &apos;a&apos; is an
+ &apos;A&apos; and a &apos;z&apos; is a &apos;Z&apos;. No need to sweat
+ over what kind. Our technology is optimized for usability without
+ sacrificing speed.
+ </p>
</div>
</div>
</body>
diff --git a/static/js/ajax.js b/static/js/ajax.js
new file mode 100644
index 0000000..e31a009
--- /dev/null
+++ b/static/js/ajax.js
@@ -0,0 +1,47 @@
+(function () {
+ const btn = document.querySelector('#shortenButton');
+ const inpUrl = document.querySelector('#url');
+ const inpSlug = document.querySelector('#slug');
+
+ function shorten (e) {
+ if (!inpUrl.value) return;
+
+ const req = new XMLHttpRequest();
+ req.addEventListener('load', () => {
+ const reply = JSON.parse(req.responseText);
+ if (req.status != 201) {
+ btn.innerText = reply.uiString || 'API Error';
+ btn.classList.add('error');
+ console.error(req.status, reply.errorMessage);
+ return;
+ }
+
+ inpUrl.value = reply.data.shortUrl;
+ inpSlug.value = '';
+ btn.removeEventListener('click', shorten);
+ btn.classList.remove('error');
+ btn.innerText = 'Copy';
+ btn.addEventListener('click', copyUrl);
+ inpUrl.focus();
+ inpUrl.select();
+ });
+ req.addEventListener('error', () => {
+ btn.innerText = 'Connection Error';
+ btn.classList.add('error');
+ })
+
+ if (inpSlug.value)
+ req.open('PUT', '/'+encodeURIComponent(inpSlug.value));
+ else
+ req.open('POST', '/');
+ req.setRequestHeader('Content-Type', 'application/json');
+ req.send(JSON.stringify({url: encodeURI(inpUrl.value)}));
+ }
+
+ async function copyUrl(e) {
+ await navigator.clipboard.writeText(encodeURI(inpUrl.value));
+ btn.innerText = 'Copied!';
+ }
+
+ btn.addEventListener('click', shorten);
+})(); \ No newline at end of file
diff --git a/static/js/slug.js b/static/js/slug.js
new file mode 100644
index 0000000..f82635c
--- /dev/null
+++ b/static/js/slug.js
@@ -0,0 +1,10 @@
+function generateSlug (len = 5) {
+ const ALPHA_SIZE = 36;
+ const MIN = 36**(len-1);
+ const MAX = 36**len;
+ const slugNumeric = Math.floor(Math.random() * (MAX-MIN))+MIN;
+ return slugNumeric.toString(ALPHA_SIZE);
+}
+
+if (typeof module !== 'undefined')
+ module.exports = {generateSlug};