Error state for mobile done ... well there are things to do. Placeholder text could be nudged. The email text positioning could be moved too.
There is JavaScript functions to clear error state, show error, and validate email address.
This commit is contained in:
parent
317f2bdbb8
commit
22f6907743
|
@ -40,7 +40,7 @@ body {
|
||||||
}
|
}
|
||||||
|
|
||||||
.titleSection {
|
.titleSection {
|
||||||
margin-top: 2rem;
|
margin-top: 1.95rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.titleSection p {
|
.titleSection p {
|
||||||
|
@ -48,9 +48,9 @@ body {
|
||||||
}
|
}
|
||||||
|
|
||||||
.titleSection .line1 {
|
.titleSection .line1 {
|
||||||
|
font-size: 1.1rem;
|
||||||
font-weight: 300;
|
font-weight: 300;
|
||||||
color: var(--site-gray);
|
color: var(--site-gray);
|
||||||
letter-spacing: 1.2px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.line1 b {
|
.line1 b {
|
||||||
|
@ -59,7 +59,7 @@ body {
|
||||||
}
|
}
|
||||||
|
|
||||||
.titleSection .line2 {
|
.titleSection .line2 {
|
||||||
margin-top: 0.95rem;
|
margin-top: 0.9rem;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
color: var(--site-gray);
|
color: var(--site-gray);
|
||||||
}
|
}
|
||||||
|
@ -75,23 +75,26 @@ body {
|
||||||
width: 83%;
|
width: 83%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.formSection input[type=email] {
|
.formSection input[type=text] {
|
||||||
font-family: 'Libre Franklin', sans-serif;
|
font-family: 'Libre Franklin', sans-serif;
|
||||||
width: calc(100% - 46px);
|
width: calc(100% - 44px);
|
||||||
|
|
||||||
color: black;
|
color: black;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
font-weight: 300;
|
font-weight: 300;
|
||||||
border: 2px solid var(--site-paleBlue);
|
border: 1px solid var(--site-paleBlue);
|
||||||
padding: 0.55rem 0;
|
padding: 0.55rem 0;
|
||||||
padding-left: 20px;
|
padding-left: 20px;
|
||||||
padding-right: 20px;
|
padding-right: 20px;
|
||||||
text-align: justify;
|
text-align: justify;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
/* cursor: ; */
|
|
||||||
border-radius: 32px;
|
border-radius: 32px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
input[type="text"].errorBorder {
|
||||||
|
border-color: var(--site-lightRed);
|
||||||
|
}
|
||||||
|
|
||||||
.formSection input::placeholder{
|
.formSection input::placeholder{
|
||||||
padding-left: 8px;
|
padding-left: 8px;
|
||||||
color: var(--site-paleBlue);;
|
color: var(--site-paleBlue);;
|
||||||
|
@ -108,12 +111,30 @@ body {
|
||||||
padding: 0.625rem 0;
|
padding: 0.625rem 0;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
/* display: inline-block; */
|
|
||||||
/* margin: 4px 2px; */
|
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
border-radius: 32px;
|
border-radius: 32px;
|
||||||
box-shadow: 0px 3px 10px 1px var(--site-paleBlue); /* 10px 5px 10px*/
|
box-shadow: 0px 3px 10px 1px var(--site-paleBlue);
|
||||||
|
}
|
||||||
|
|
||||||
|
.notifyButton.notifyError {
|
||||||
|
transform: translate(0, 1.6rem);
|
||||||
|
}
|
||||||
|
|
||||||
|
.errorSection {
|
||||||
|
height: 0;
|
||||||
|
padding: 0;
|
||||||
|
transform: translate(0, 0.35rem);
|
||||||
|
}
|
||||||
|
|
||||||
|
.errorMessage {
|
||||||
|
font-style: italic;
|
||||||
|
font-size: 10px;
|
||||||
|
opacity: 0;
|
||||||
|
color: var(--site-lightRed);
|
||||||
|
}
|
||||||
|
|
||||||
|
.errorMessage.visible {
|
||||||
|
opacity: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
.imageSection {
|
.imageSection {
|
||||||
|
@ -156,18 +177,18 @@ footer {
|
||||||
.attribution { font-size: 11px; text-align: center; }
|
.attribution { font-size: 11px; text-align: center; }
|
||||||
.attribution a i { color: hsl(228, 45%, 44%); }
|
.attribution a i { color: hsl(228, 45%, 44%); }
|
||||||
|
|
||||||
@media screen and (max-width: 600px) {
|
@media screen and (max-width: 800px) {
|
||||||
.flexContainer {
|
.flexContainer {
|
||||||
width: 90vw;
|
width: 90vw;
|
||||||
height: 100vh;
|
height: 100vh;
|
||||||
}
|
}
|
||||||
|
|
||||||
.formSection button {
|
.formSection button {
|
||||||
margin-top: 0.45rem;
|
margin-top: 0.55rem;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media screen and (min-width: 600px) {
|
@media screen and (min-width: 800px) {
|
||||||
.flexContainer {
|
.flexContainer {
|
||||||
width: 50vw;
|
width: 50vw;
|
||||||
height: 100vh;
|
height: 100vh;
|
||||||
|
@ -182,17 +203,17 @@ footer {
|
||||||
.titleSection {
|
.titleSection {
|
||||||
margin-top: 2.5rem;
|
margin-top: 2.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.titleSection .line1 {
|
.titleSection .line1 {
|
||||||
font-weight: 300;
|
font-weight: 300;
|
||||||
letter-spacing: 1.3px;
|
letter-spacing: 1.3px;
|
||||||
font-size: 45px;
|
font-size: 45px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.line1 b {
|
.line1 b {
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
}
|
}
|
||||||
|
|
||||||
.titleSection .line2 {
|
.titleSection .line2 {
|
||||||
margin-top: 0.95rem;
|
margin-top: 0.95rem;
|
||||||
font-size: 20px;
|
font-size: 20px;
|
||||||
|
@ -209,7 +230,7 @@ footer {
|
||||||
width: 88%;
|
width: 88%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.formSection input[type=email] {
|
.formSection input[type=text] {
|
||||||
flex-basis: 66%;
|
flex-basis: 66%;
|
||||||
|
|
||||||
width: calc(100% - 46px);
|
width: calc(100% - 46px);
|
||||||
|
@ -219,6 +240,7 @@ footer {
|
||||||
padding-left: 20px;
|
padding-left: 20px;
|
||||||
padding-right: 20px;
|
padding-right: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.formSection button {
|
.formSection button {
|
||||||
margin-left: 1rem;
|
margin-left: 1rem;
|
||||||
flex-basis: 34%;
|
flex-basis: 34%;
|
||||||
|
@ -227,17 +249,16 @@ footer {
|
||||||
font-weight: 300;
|
font-weight: 300;
|
||||||
|
|
||||||
padding: 0.8rem 0;
|
padding: 0.8rem 0;
|
||||||
box-shadow: 0px 3px 10px 1px var(--site-paleBlue); /* 10px 5px 10px*/
|
box-shadow: 0px 3px 10px 1px var(--site-paleBlue);
|
||||||
}
|
}
|
||||||
|
|
||||||
.imageSection {
|
.imageSection {
|
||||||
margin-top: 4.3rem;
|
margin-top: 4.3rem;
|
||||||
width: 89%;
|
width: 89%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.copyright {
|
.copyright {
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
margin-bottom: 1.75rem;
|
margin-bottom: 1.75rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -24,9 +24,13 @@
|
||||||
<p class="line2">Subscribe and get notified</p>
|
<p class="line2">Subscribe and get notified</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="formSection">
|
<div class="formSection">
|
||||||
<form action="submit">
|
<form name="emailForm" action="submit" onsubmit="return validateEmailAddress()">
|
||||||
<input type="email" name="emailInput" id="emailInput" placeholder="Your email address...">
|
<!-- challenge requires us to do validation of this field, therefore NOT using type="email" -->
|
||||||
<button class="notifyButton">Notify Me</button>
|
<input type="text" name="emailInput" id="emailInput" placeholder="Your email address..." onfocus="clearError()">
|
||||||
|
<div class="errorSection" id="errorSection" > <!-- hidden -->
|
||||||
|
<p class="errorMessage" id="errorMessage">Placeholder Text</p>
|
||||||
|
</div>
|
||||||
|
<button class="notifyButton" id="notifyButton">Notify Me</button>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
<div class="imageSection">
|
<div class="imageSection">
|
||||||
|
@ -57,5 +61,6 @@
|
||||||
Coded by <a href="mailto:work@tarasis.net">Robert McGovern</a>.
|
Coded by <a href="mailto:work@tarasis.net">Robert McGovern</a>.
|
||||||
</p>
|
</p>
|
||||||
</footer>
|
</footer>
|
||||||
|
<script src="./js/script.js"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
|
@ -1,2 +1,105 @@
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
|
const console = window.console;
|
||||||
|
const emailInput = document.getElementById("emailInput");
|
||||||
|
const errorMessage = document.getElementById("errorMessage");
|
||||||
|
const errorSection = document.getElementById("errorSection");
|
||||||
|
const notifyButton = document.getElementById("notifyButton");
|
||||||
|
|
||||||
|
const errorMessageForgotAddress = "Whoops! It looks like you forgot to add your email";
|
||||||
|
const errorMessageInvalidAddress = "Please provide a valid email address";
|
||||||
|
|
||||||
|
/*
|
||||||
|
* this is my "simple" regex for email addresses. It does not cover all the possibilities that are allowed
|
||||||
|
* for the local and domain parts. For a more "correct" / comprehensive regex, there is one at
|
||||||
|
* https://stackoverflow.com/questions/3844431/are-email-addresses-allowed-to-contain-non-alphanumeric-characters
|
||||||
|
*
|
||||||
|
* For local part you can use ASCII:
|
||||||
|
* Latin letters A - Z a - z
|
||||||
|
* digits 0 - 9
|
||||||
|
* special characters !#$%&'*+-/=?^_`{|}~
|
||||||
|
* dot ., that it is not first or last, and not in sequence
|
||||||
|
* space and "(),:;<>@[] characters are allowed with restrictions (they are only allowed inside a quoted string, a backslash or double-quote must be preceded by a backslash)
|
||||||
|
* Plus since 2012 you can use international characters above U+007F, encoded as UTF-8.
|
||||||
|
*
|
||||||
|
* Domain part is more restricted:
|
||||||
|
* Latin letters A - Z a - z
|
||||||
|
* digits 0 - 9
|
||||||
|
* hyphen -, that is not first or last, multiple hyphens in sequence are allowed.
|
||||||
|
*
|
||||||
|
* Recommended regex is: ^(([^<>()\[\]\.,;:\s@\"]+(\.[^<>()\[\]\.,;:\s@\"]+)*)|(\".+\"))@(([^<>()[\]\.,;:\s@\"]+\.)+[^<>()[\]\.,;:\s@\"]{2,})
|
||||||
|
*/
|
||||||
|
const validEmailFormat = /^[A-Za-z0-9][\w\+]*@[A-Za-z0-9]{3,}\.[A-Za-z]{2,}$/i;
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Don't quite see the point in this, setting "type=email" does some validation
|
||||||
|
* Setting the input to "required" prevents submitting an empty field
|
||||||
|
*
|
||||||
|
* Only benefit I see is the being able to set an error message
|
||||||
|
* Maybe one form of solution is doing exactly that. Use onclick event on the button
|
||||||
|
* if the field is empty, unhide the error field
|
||||||
|
*/
|
||||||
|
function validateEmailAddress() {
|
||||||
|
const submittedEmailAddress = document.forms.emailForm.emailInput.value;
|
||||||
|
// test email is valid via regex
|
||||||
|
const isValidEmailAddress = validEmailFormat.test(submittedEmailAddress);
|
||||||
|
|
||||||
|
if (submittedEmailAddress.length === 0) {
|
||||||
|
showError(errorMessageForgotAddress);
|
||||||
|
return false;
|
||||||
|
} else if (!isValidEmailAddress) {
|
||||||
|
showError(errorMessageInvalidAddress);
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function showError(message) {
|
||||||
|
errorMessage.innerText = message;
|
||||||
|
errorMessage.classList.add("visible");
|
||||||
|
emailInput.classList.add("errorBorder");
|
||||||
|
notifyButton.classList.add("notifyError");
|
||||||
|
// errorSection.hidden = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (Possibly) To be called as user types in the email field. If an error message has been shown,
|
||||||
|
* then hide the message and return the fields to normal
|
||||||
|
*/
|
||||||
|
function clearError() {
|
||||||
|
errorMessage.classList.remove("visible");
|
||||||
|
emailInput.classList.remove("errorBorder");
|
||||||
|
notifyButton.classList.remove("notifyError");
|
||||||
|
// errorSection.hidden = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function testRegex() {
|
||||||
|
console.log("Should all be false");
|
||||||
|
console.log(validEmailFormat.test("submittedEmailAddress"));
|
||||||
|
console.log(validEmailFormat.test("s@.NET"));
|
||||||
|
console.log(validEmailFormat.test("@"));
|
||||||
|
console.log(validEmailFormat.test("@."));
|
||||||
|
console.log(validEmailFormat.test("@.net"));
|
||||||
|
console.log(validEmailFormat.test("@tarasis.net"));
|
||||||
|
console.log(validEmailFormat.test("adsadasds@"));
|
||||||
|
console.log(validEmailFormat.test("__submittedEmailAddress"));
|
||||||
|
console.log(validEmailFormat.test("spam@tarasis.99"));
|
||||||
|
console.log(validEmailFormat.test("rob@.net"));
|
||||||
|
console.log(validEmailFormat.test("spam@tarasis"));
|
||||||
|
console.log(validEmailFormat.test("spam@tarasis.a"));
|
||||||
|
console.log(validEmailFormat.test("s@ta.net"));
|
||||||
|
console.log(validEmailFormat.test("_@tarasis.net"));
|
||||||
|
console.log(validEmailFormat.test("_3@tarasis.net"));
|
||||||
|
|
||||||
|
console.log("\n Should all be true");
|
||||||
|
console.log(validEmailFormat.test("spam@tarasis.net"));
|
||||||
|
console.log(validEmailFormat.test("rob@tad.io"));
|
||||||
|
console.log(validEmailFormat.test("s@tarasis.net"));
|
||||||
|
console.log(validEmailFormat.test("s@tarasis.net"));
|
||||||
|
console.log(validEmailFormat.test("s_@tarasis.net"));
|
||||||
|
console.log(validEmailFormat.test("s+blah@tarasis.net")); // this can be true, some servers use this for filtering
|
||||||
|
}
|
||||||
|
|
||||||
|
// testRegex();
|
Binary file not shown.
After Width: | Height: | Size: 55 KiB |
|
@ -55,6 +55,29 @@ Hover States for Social Buttons (flip colors)
|
||||||
Attempted to use hover state to change the background of the fa-stack but it wasn't triggering. Could only change the color of the item at the top of the stack (i.e the social icon)
|
Attempted to use hover state to change the background of the fa-stack but it wasn't triggering. Could only change the color of the item at the top of the stack (i.e the social icon)
|
||||||
Learnt you can change css of other elemnts when hovering over a different one ... sorta. Has to be a child you are changing, https://stackoverflow.com/questions/19121223/css-change-an-element-content-on-hover-from-different-element
|
Learnt you can change css of other elemnts when hovering over a different one ... sorta. Has to be a child you are changing, https://stackoverflow.com/questions/19121223/css-change-an-element-content-on-hover-from-different-element
|
||||||
|
|
||||||
|
Next Day:
|
||||||
|
|
||||||
|
Realised I had to change a few things. Change the input field from `type="email"` to `type="text"` so that I can do the field validation.
|
||||||
|
|
||||||
|
Added a div that starts as hidden and has no text
|
||||||
|
|
||||||
|
Added some css styling for the text color, and added an error class for changing the input fields border
|
||||||
|
|
||||||
|
In JavaScript created a couple of functions, the first that has to return true/false when the user presses "Notify Me" (basically onsubmit event), does some validation of address length, and address structure.
|
||||||
|
|
||||||
|
The other method reveals the hidden div and sets the input fields border to red.
|
||||||
|
|
||||||
|
There is a third method that I couldn't decide about using. It will clear the error message. The idea being that as soon as the user starts typing again in the field that the error is cleared. (or better yet, when the field gets focus again. I can check for that? )
|
||||||
|
|
||||||
|
Created a simplistic regex for email address validation, with some test cases to check my logic. I'm still learning regex, and I don't want to spend the time learning all the combinations for email addresses.
|
||||||
|
|
||||||
|
I did research and find a more "correct" regex that I could use, but I will stick with my for this sample.
|
||||||
|
|
||||||
|
Played with alignment so mobile & mobile error are close.
|
||||||
|
|
||||||
|
![mobile difference](mobile-error-diff.png)
|
||||||
|
|
||||||
|
|
||||||
BUGS:
|
BUGS:
|
||||||
* when screen not tall enough social buttons and copyright pushed up the page because I clamped them to the bottom of the browser window, rather than the page.
|
* when screen not tall enough social buttons and copyright pushed up the page because I clamped them to the bottom of the browser window, rather than the page.
|
||||||
* because I used attacked circles I can't just change the background to blue for hover. Need to either sub in a filled circle on hover OR swap to manually creating the circle
|
* because I used attacked circles I can't just change the background to blue for hover. Need to either sub in a filled circle on hover OR swap to manually creating the circle
|
||||||
|
|
6
notes.md
6
notes.md
|
@ -33,4 +33,10 @@ Think of it as a combination of learning, and tips and tricks. They will start u
|
||||||
```
|
```
|
||||||
|
|
||||||
* Random aside: can't carry on a list after putting a codeblock inside a list
|
* Random aside: can't carry on a list after putting a codeblock inside a list
|
||||||
|
* Found useful site for Regex writing / testing https://regex101.com
|
||||||
|
* this specific address has regex for email validation https://regex101.com/r/uP2oL7/1
|
||||||
|
|
||||||
|
* CSS - The "!important" rule should only be used as a last resort - nuclear option
|
||||||
|
* better to do elementName.className when wanting to temp add a class to override some css (like say a border color)
|
||||||
|
|
||||||
* Blah
|
* Blah
|
Loading…
Reference in New Issue