aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorlonkaars <loek@pipeframe.xyz>2023-05-27 14:21:25 +0200
committerlonkaars <loek@pipeframe.xyz>2023-05-27 14:21:25 +0200
commit8af23ff155904ba78de61a3cdab33a048a0f5664 (patch)
tree16a7c1c426f68e3e0289177b1406222f55b6fb0e
parent05d4f801fa8a519e257993cfa5bf1d72cdb7646f (diff)
validate register info client-side
-rw-r--r--public/global.css6
-rw-r--r--public/login.php4
-rw-r--r--public/register.css93
-rw-r--r--public/register.js83
-rw-r--r--public/register.php34
5 files changed, 214 insertions, 6 deletions
diff --git a/public/global.css b/public/global.css
index a417d10..1683ef5 100644
--- a/public/global.css
+++ b/public/global.css
@@ -54,6 +54,12 @@ body, html {
border-radius: 8px;
border: none;
background-color: var(--bg-alt);
+ transition: opacity .3s;
+}
+.button[disabled],
+.buttonstyle[disabled] {
+ opacity: 0.4;
+ cursor: not-allowed !important;
}
.button {
diff --git a/public/login.php b/public/login.php
index 19d9d17..7b1a254 100644
--- a/public/login.php
+++ b/public/login.php
@@ -23,9 +23,9 @@ do {
<div class="modal">
<form action="/login.php" method="post">
<label for="username">Gebruikersnaam</label>
- <input id="username" name="username" type="text" placeholder="gebruikersnaam" class="buttonstyle">
+ <input id="username" name="username" type="text" placeholder="gebruikersnaam" class="buttonstyle" autocomplete="username" autofocus>
<label for="password">Wachtwoord</label>
- <input id="password" name="password" type="password" placeholder="wachtwoord" class="buttonstyle">
+ <input id="password" name="password" type="password" placeholder="wachtwoord" class="buttonstyle" autocomplete="current-password">
<input type="submit" value="Inloggen" class="button filled">
</form>
<span class="register">Of <a href="/register.php">een nieuw account maken</a></span>
diff --git a/public/register.css b/public/register.css
new file mode 100644
index 0000000..eef7490
--- /dev/null
+++ b/public/register.css
@@ -0,0 +1,93 @@
+.check-popup {
+ transition-property: margin, box-shadow;
+ transition-duration: .3s;
+ background-color: var(--bg-alt);
+ position: relative;
+ margin-bottom: 16px;
+ border-radius: 8px;
+ box-shadow: 0px 8px 32px -16px #0004;
+}
+
+.check-popup::before {
+ transition: opacity .3s;
+ content: "";
+ position: absolute;
+ top: 0;
+ left: 50%;
+ background-color: var(--bg-alt);
+ width: 16px;
+ height: 16px;
+ transform: translate(-50%, -50%) rotate(-45deg);
+}
+
+.requirements {
+ display: grid;
+ list-style: none;
+}
+
+.requirements .requirement {
+ transition-property: opacity;
+ transition-duration: .3s;
+ opacity: calc(100% - 50% * var(--done));
+ --done: 0;
+}
+
+.requirements .requirement .inner {
+ position: relative;
+}
+
+.requirements .requirement .inner::before {
+ content: "- ";
+ position: absolute;
+ left: -0.5em;
+ transform: translateX(-100%);
+}
+
+.requirements .requirement .inner::after {
+ transition-property: width;
+ transition-duration: .3s;
+ content: "";
+ position: absolute;
+ top: 50%;
+ left: 0;
+ width: calc(100% * var(--done));
+ background-color: currentColor;
+ height: 2px;
+}
+
+.requirements.len-3 .requirement.len-3,
+.requirements.nosymbol .requirement.nosymbol,
+.requirements.nospace .requirement.nospace,
+.requirements.valid .requirement.valid,
+.requirements.len-8 .requirement.len-8,
+.requirements.digit-2 .requirement.digit-2,
+.requirements.symbol-2 .requirement.symbol-2,
+.requirements.has-uppercase .requirement.has-uppercase,
+.requirements.has-lowercase .requirement.has-lowercase
+{ --done: 1; }
+
+#username-requirements { --requirement-count: 3; }
+#email-requirements { --requirement-count: 1; }
+#password-requirements { --requirement-count: 5; }
+.check-popup .requirements {
+ --requirement-count: 0; /* TODO: this should dynamically change */
+ transition-property: margin, opacity, grid-template-rows;
+ transition-duration: .3s;
+ grid-template-rows: repeat(var(--requirement-count), 1fr);
+ overflow: hidden;
+}
+
+.check-popup .requirements .requirement {
+ min-height: 0;
+}
+
+.check-popup.all .requirements {
+ margin: 0;
+ opacity: 0;
+ grid-template-rows: repeat(var(--requirement-count), 0fr);
+}
+.check-popup.all {
+ margin: 0;
+ box-shadow: none;
+}
+.check-popup.all::before { opacity: 0; }
diff --git a/public/register.js b/public/register.js
new file mode 100644
index 0000000..d3b66e1
--- /dev/null
+++ b/public/register.js
@@ -0,0 +1,83 @@
+function checkUsername() {
+ var username = document.getElementById("username").value;
+ var requirements = document.getElementById("username-requirements");
+
+ var len3 = username.length >= 3;
+ var nosymbol = username.match(/["'<>/&:;\\|{}[\]()]/) == null;
+ var nospace = username.match(/[ ]/) == null;
+
+ requirements.classList[len3 ? "add" : "remove"]("len-3");
+ requirements.classList[nosymbol ? "add" : "remove"]("nosymbol");
+ requirements.classList[nospace ? "add" : "remove"]("nospace");
+
+ requirements.parentElement.classList.remove("all");
+ if (!len3) return false;
+ if (!nosymbol) return false;
+ if (!nospace) return false;
+ requirements.parentElement.classList.add("all");
+ return true;
+}
+
+function checkEmail() {
+ var email = document.getElementById("email").value;
+ var requirements = document.getElementById("email-requirements");
+
+ // e-mail addresses can really only be verified by attempting to send a mail
+ // to them, so this is pretty much useless for client-side anyways
+ var valid = email.match(/.+?@.+/) != null;
+
+ requirements.classList[valid ? "add" : "remove"]("valid");
+
+ requirements.parentElement.classList.remove("all");
+ if (!valid) return false;
+ requirements.parentElement.classList.add("all");
+ return true;
+}
+
+function checkPassword() {
+ var password = document.getElementById("password").value;
+ var requirements = document.getElementById("password-requirements");
+
+ var len8 = password.length >= 8;
+ var minnum2 = password.match(/[0-9]/g)?.length >= 2;
+ var minsym2 = password.match(/[!@#$%^&*()\-=_+[\]{}\\|;:'",<.>/?`~]/g)?.length >= 2;
+ var uppercase = password.match(/[A-Z]/) != null;
+ var lowercase = password.match(/[a-z]/) != null;
+
+ requirements.classList[len8 ? "add" : "remove"]("len-8");
+ requirements.classList[minnum2 ? "add" : "remove"]("digit-2");
+ requirements.classList[minsym2 ? "add" : "remove"]("symbol-2");
+ requirements.classList[uppercase ? "add" : "remove"]("has-uppercase");
+ requirements.classList[lowercase ? "add" : "remove"]("has-lowercase");
+
+ requirements.parentElement.classList.remove("all");
+ if (!len8) return false;
+ if (!minnum2) return false;
+ if (!minsym2) return false;
+ if (!uppercase) return false;
+ if (!lowercase) return false;
+ requirements.parentElement.classList.add("all");
+ return true;
+}
+
+function checkAllFields() {
+ var username = checkUsername();
+ var email = checkEmail();
+ var password = checkPassword();
+
+ if (!username) return false;
+ if (!email) return false;
+ if (!password) return false;
+ return true;
+}
+
+function updateRegisterButton() {
+ document.getElementById("register-submit").disabled = !checkAllFields();
+}
+
+// update when fields are changed
+document.getElementById("username").addEventListener("input", updateRegisterButton);
+document.getElementById("email").addEventListener("input", updateRegisterButton);
+document.getElementById("password").addEventListener("input", updateRegisterButton);
+
+updateRegisterButton();
diff --git a/public/register.php b/public/register.php
index f0f6596..0ef7e18 100644
--- a/public/register.php
+++ b/public/register.php
@@ -1,5 +1,6 @@
+<!DOCTYPE html>
<?php include "../lib/login.php" ?>
-<?php // if_logged_in(true, "/") ?>
+<?php if_logged_in(true, "/") ?>
<?php
do {
if ($_SERVER['REQUEST_METHOD'] !== 'POST') break;
@@ -17,6 +18,8 @@ do {
<?php include 'head.php' ?>
<title>registeren</title>
<link rel='stylesheet' type='text/css' media='screen' href='login.css'>
+ <link rel='stylesheet' type='text/css' media='screen' href='register.css'>
+ <script defer src="register.js"></script>
</head>
<body>
<?php include 'navbar.php' ?>
@@ -25,10 +28,33 @@ do {
<div class="modal">
<form action="/register.php" method="post">
<label for="username">Gebruikersnaam</label>
- <input id="username" name="username" type="text" placeholder="gebruikersnaam" class="buttonstyle">
+ <input id="username" name="username" type="text" placeholder="gebruikersnaam" class="buttonstyle" autocomplete="username" autofocus>
+ <div class="check-popup check-username">
+ <ul id="username-requirements" class="requirements">
+ <li class="requirement len-3"><span class="inner">Minimaal 3 letters lang</span></li>
+ <li class="requirement nosymbol"><span class="inner">Geen symbolen</span></li>
+ <li class="requirement nospace"><span class="inner">Geen spaties</span></li>
+ </ul>
+ </div>
+ <label for="username">E-mail adres</label>
+ <input id="email" name="email" type="text" placeholder="e-mail" class="buttonstyle" autocomplete="email">
+ <div class="check-popup check-email">
+ <ul id="email-requirements" class="requirements">
+ <li class="requirement valid"><span class="inner">Geldig e-mail adres</span></li>
+ </ul>
+ </div>
<label for="password">Wachtwoord</label>
- <input id="password" name="password" type="password" placeholder="wachtwoord" class="buttonstyle">
- <input type="submit" value="Registreren" class="button filled">
+ <input id="password" name="password" type="password" placeholder="wachtwoord" class="buttonstyle" autocomplete="new-password">
+ <div class="check-popup check-password">
+ <ul id="password-requirements" class="requirements">
+ <li class="requirement len-8"><span class="inner">Minimaal 8 tekens lang</span></li>
+ <li class="requirement digit-2"><span class="inner">Minimaal 2 cijfers</span></li>
+ <li class="requirement symbol-2"><span class="inner">Minimaal 2 symbolen</span></li>
+ <li class="requirement has-uppercase"><span class="inner">Bevat hoofdletter(s)</span></li>
+ <li class="requirement has-lowercase"><span class="inner">Bevat kleine letter(s)</span></li>
+ </ul>
+ </div>
+ <input id="register-submit" type="submit" value="Registreren" class="button filled">
</form>
<span class="register">Of <a href="/login.php">inloggen</a></span>
</div>