diff --git a/FrontendMentor/ping-coming-soon-page-master/css/style.css b/FrontendMentor/ping-coming-soon-page-master/css/style.css index 4b76e6b..740cc2b 100644 --- a/FrontendMentor/ping-coming-soon-page-master/css/style.css +++ b/FrontendMentor/ping-coming-soon-page-master/css/style.css @@ -40,7 +40,7 @@ body { } .titleSection { - margin-top: 2rem; + margin-top: 1.95rem; } .titleSection p { @@ -48,9 +48,9 @@ body { } .titleSection .line1 { + font-size: 1.1rem; font-weight: 300; color: var(--site-gray); - letter-spacing: 1.2px; } .line1 b { @@ -59,7 +59,7 @@ body { } .titleSection .line2 { - margin-top: 0.95rem; + margin-top: 0.9rem; font-size: 12px; color: var(--site-gray); } @@ -75,23 +75,26 @@ body { width: 83%; } -.formSection input[type=email] { +.formSection input[type=text] { font-family: 'Libre Franklin', sans-serif; - width: calc(100% - 46px); + width: calc(100% - 44px); color: black; font-size: 12px; font-weight: 300; - border: 2px solid var(--site-paleBlue); + border: 1px solid var(--site-paleBlue); padding: 0.55rem 0; padding-left: 20px; padding-right: 20px; text-align: justify; text-decoration: none; - /* cursor: ; */ border-radius: 32px; } +input[type="text"].errorBorder { + border-color: var(--site-lightRed); +} + .formSection input::placeholder{ padding-left: 8px; color: var(--site-paleBlue);; @@ -108,12 +111,30 @@ body { padding: 0.625rem 0; text-align: center; text-decoration: none; - /* display: inline-block; */ - /* margin: 4px 2px; */ cursor: pointer; 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 { @@ -156,18 +177,18 @@ footer { .attribution { font-size: 11px; text-align: center; } .attribution a i { color: hsl(228, 45%, 44%); } -@media screen and (max-width: 600px) { +@media screen and (max-width: 800px) { .flexContainer { width: 90vw; height: 100vh; } .formSection button { - margin-top: 0.45rem; + margin-top: 0.55rem; } } -@media screen and (min-width: 600px) { +@media screen and (min-width: 800px) { .flexContainer { width: 50vw; height: 100vh; @@ -182,17 +203,17 @@ footer { .titleSection { margin-top: 2.5rem; } - + .titleSection .line1 { font-weight: 300; letter-spacing: 1.3px; font-size: 45px; } - + .line1 b { font-weight: 700; } - + .titleSection .line2 { margin-top: 0.95rem; font-size: 20px; @@ -209,7 +230,7 @@ footer { width: 88%; } - .formSection input[type=email] { + .formSection input[type=text] { flex-basis: 66%; width: calc(100% - 46px); @@ -219,6 +240,7 @@ footer { padding-left: 20px; padding-right: 20px; } + .formSection button { margin-left: 1rem; flex-basis: 34%; @@ -227,17 +249,16 @@ footer { font-weight: 300; 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 { margin-top: 4.3rem; width: 89%; } - + .copyright { font-size: 12px; margin-bottom: 1.75rem; } - } \ No newline at end of file diff --git a/FrontendMentor/ping-coming-soon-page-master/index.html b/FrontendMentor/ping-coming-soon-page-master/index.html index 959cd40..e36d96f 100644 --- a/FrontendMentor/ping-coming-soon-page-master/index.html +++ b/FrontendMentor/ping-coming-soon-page-master/index.html @@ -24,9 +24,13 @@

Subscribe and get notified

-
- - + + + +
+

Placeholder Text

+
+
@@ -57,5 +61,6 @@ Coded by Robert McGovern.

+ \ No newline at end of file diff --git a/FrontendMentor/ping-coming-soon-page-master/js/script.js b/FrontendMentor/ping-coming-soon-page-master/js/script.js index 23e72fd..61bdd37 100644 --- a/FrontendMentor/ping-coming-soon-page-master/js/script.js +++ b/FrontendMentor/ping-coming-soon-page-master/js/script.js @@ -1,2 +1,105 @@ "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(); \ No newline at end of file diff --git a/FrontendMentor/ping-coming-soon-page-master/work-through/mobile-error-diff.png b/FrontendMentor/ping-coming-soon-page-master/work-through/mobile-error-diff.png new file mode 100644 index 0000000..f5e52c8 Binary files /dev/null and b/FrontendMentor/ping-coming-soon-page-master/work-through/mobile-error-diff.png differ diff --git a/FrontendMentor/ping-coming-soon-page-master/work-through/myProcess.md b/FrontendMentor/ping-coming-soon-page-master/work-through/myProcess.md index bb89bf0..5afe5a2 100644 --- a/FrontendMentor/ping-coming-soon-page-master/work-through/myProcess.md +++ b/FrontendMentor/ping-coming-soon-page-master/work-through/myProcess.md @@ -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) 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: * 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 diff --git a/notes.md b/notes.md index ed97cbb..e1ddb78 100644 --- a/notes.md +++ b/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 +* 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 \ No newline at end of file