# Form Validation

{% tabs %}
{% tab title="📙 參考" %}

* freeCodeCamp ⟩ [Learn JavaScript Form Validation](https://www.freecodecamp.org/news/learn-javascript-form-validation-by-making-a-form/)
* GitHub ⟩ [Project images](https://github.com/JoyShaheb/Project-image-repo/tree/main/Form-Validation)
  {% endtab %}

{% tab title="📘 手冊" %}

* MDN ⟩ CSS ⟩&#x20;
  * [outline](https://developer.mozilla.org/en-US/docs/Web/CSS/outline)
  * [background-image](https://developer.mozilla.org/en-US/docs/Web/CSS/background-image)
    {% endtab %}
    {% endtabs %}

💾 [replit](https://replit.com/@pegasusroe/form-validation#script.js)

## Live Demo

{% tabs %}
{% tab title="1. HTML" %}
{% embed url="<https://codepen.io/lochiwei/pen/dyRjqXK>" %}

{% endtab %}

{% tab title="2. CSS" %}
{% embed url="<https://codepen.io/lochiwei/pen/abwjaBV>" %}

{% endtab %}

{% tab title="3. Icons" %}
{% embed url="<https://codepen.io/lochiwei/pen/RwgBYvX>" %}

{% endtab %}

{% tab title="4. JS" %}
{% embed url="<https://codepen.io/lochiwei/pen/KKqBGyo>" %}

{% endtab %}

{% tab title="5. Social" %}
{% embed url="<https://codepen.io/lochiwei/pen/MWoBPNL>" %}

{% endtab %}

{% tab title="6. Images" %}
{% embed url="<https://codepen.io/lochiwei/pen/dyRjQOv>" %}

{% endtab %}
{% endtabs %}

## Code

{% tabs %}
{% tab title="1. HTML" %}

```markup
<div class="container">

  <form id="form">

    <div class="title">Get Started</div>

    <!-- ⭐️ User Name -->
    <div>
      <label for="username">User Name</label>
      <i class="fas fa-user"></i>

      <input type="text" name="username" id="username" placeholder="Joy Shaheb" />

      <i class="fas fa-exclamation-circle failure-icon"></i>
      <i class="far fa-check-circle success-icon"></i>

      <div class="error"></div>
    </div>

    <!-- ⭐️ Email -->
    <div>
      <label for="email">Email</label>
      <i class="far fa-envelope"></i>

      <input type="email" name="email" id="email" placeholder="abc@gmail.com" />

      <i class="fas fa-exclamation-circle failure-icon"></i>
      <i class="far fa-check-circle success-icon"></i>

      <div class="error"></div>
    </div>

    <!-- ⭐️ Password -->
    <div>
      <label for="password">Password</label>
      <i class="fas fa-lock"></i>

      <input type="password" name="password" id="password" placeholder="Password here" />

      <i class="fas fa-exclamation-circle failure-icon"></i>
      <i class="far fa-check-circle success-icon"></i>

      <div class="error"></div>
    </div>

    <button id="btn" type="submit">Submit</button>

  </form>

</div>
```

{% endtab %}

{% tab title="2. CSS" %}

```css
/* import Font Awesome */
@import url("https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free@5.15.4/css/all.min.css");

/*
 * css reset
 */

* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

body {
  font-family: sans-serif;
}

/*
 * form section
 */

form {
  display: flex;
  flex-direction: column;
  justify-content: center;
  max-width: 400px;
  box-shadow: 2px 2px 4px rgba(0, 0, 0, 0.1);
  padding: 50px;
}

.title {
  font-size: 25px;
  font-weight: bold;
  margin-bottom: 20px;
}

label {
  display: block;
  margin-bottom: 5px;
}

form input {
  
  width: 100%;
  height: 40px;
  padding: 0 30px;
  border-radius: 8px;
  border: 1px solid #c4c4c4;
  
  /* ⭐️ browser gives default styling to <input> */
  outline: none;
  
  box-shadow: 2px 2px 4px rgba(0,0,0,0.1) inset;
}

form div {
  position: relative;
  margin-bottom: 15px;
}

input:focus {
  border: 2px solid #f2796e;      /* ⭐️ red border on focus */
}
```

{% endtab %}

{% tab title="3. Icons" %}

```css
/*
 * form icons
 */

form div i {
  position: absolute;
  padding: 12px 10px;             /* ⭐️ 調整圖示的位置 */
}

/*
 * error class, success and failure icons
 */

.failure-icon,
.error {
  color: tomato;
}

.success-icon {
  color: green;
}

.error {
  font-size: 14.5px;
  margin-top: 5px;
}

/*
 * submit button
 */

button {
  margin-top: 15px;
  width: 100%;
  height: 45px;
  
  background: tomato;
  color: white;
  
  border: 2px solid tomato;
  border-radius: 8px;
  box-shadow: 2px 2px 4px rgba(0,0,0,0.2);
  
  font-size: 20px;
  cursor: pointer;
}

button:hover {
  box-shadow: 2px 2px 4px rgba(0,0,0,0.1);
  border-color: red;
  opacity: 0.9;             /* ⭐️ 顏色會變淡一些 */
}
```

{% endtab %}

{% tab title="4. JS" %}

```javascript
/* ---------- helpers ---------- */

// ⭐️ $(): select first
function $(selector, parent = document){
  return parent.querySelector(selector);
}

// ⭐️ $all(): select all
function $all(selector, parent = document){
  return parent.querySelectorAll(selector);
}

/* ---------- elements ---------- */

const username = $('#username');
const email = $('#email');
const password = $('#password');
const form = $('#form');

const errors = $all('.error');
const successIcons = $all('.success-icon');
const failureIcons = $all('.failure-icon');

/* ---------- check input value ---------- */

function check(input, idx, msg){
  // input value empty ?
  const isEmpty = input.value.trim() === '';
  // set border style
  input.style.border = `2px solid ${isEmpty ? 'red' : 'green'}`;
  // set error message
  errors[idx].innerHTML = isEmpty ? msg : '';
  // set icon styles
  failureIcons[idx].style.opacity = isEmpty ? '1' : '0';
  successIcons[idx].style.opacity = isEmpty ? '0' : '1';
}

/* ---------- on submit ---------- */

form.addEventListener('submit', e => {
  e.preventDefault();
  check(username, 0, 'user name can not be blank');
  check(email, 1, 'email can not be blank');
  check(password, 2, 'password can not be blank');
})
```

{% endtab %}

{% tab title="5. Social" %}

* css

```css
/* social buttons */

.btn {
  display: flex;
  justify-content: space-between;
  gap: 15px;
}

.btn-1, .btn-2 {
  
  width: 100%;
  padding: 10px 15px;
  
  border: 2px solid #c4c4c4;
  border-radius: 8px;
  box-shadow: 2px 2px 4px rgba(0,0,0, 0.1);
  
  display: flex;
  justify-content: center;
  align-items: center;
  gap: 15px;
  
  cursor: pointer;
}

/* facebook style */
.btn-2 {
  background-color: #4f70b5;
  color: white;
}

/* text styles */

.or {
  text-align: center;
}

.question {
  font-size: 15px;
}

span {
  color: #f2796e;
  cursor: pointer;
}
```

* html

```markup
<div class="social">

      <div class="title">Get Started</div>

      <div class="question">
        Already Have an Account? <br />
        <span>Sign In</span>
      </div>

      <div class="btn">
        <div class="btn-1">
          <img src="https://img.icons8.com/color/30/000000/google-logo.png" />
          Sign Up
        </div>

        <div class="btn-2">
          <img src="https://img.icons8.com/ios-filled/30/ffffff/facebook-new.png" />
          Sign Up
        </div>
      </div>

      <div class="or">Or</div>
</div>
```

{% endtab %}

{% tab title="6. Images" %}

```css
/* image */
.image {
  background-image: url("https://3fb9978f-da79-476a-a592-ceb9885444d6.id.repl.co/img/image.svg");
  background-repeat: no-repeat;
  background-size: contain;
  background-position: center;

  height: 65%;
}

/* text */
.text {
    text-align: center;
    color: white;
}
```

{% endtab %}

{% tab title="注意❗️" %}
{% hint style="info" %}
The [**outline**](https://developer.mozilla.org/en-US/docs/Web/CSS/outline) of most elements defaults to **none**. A notable exception is <**input**> elements, which are given **default styling** by **browsers**.
{% endhint %}
{% endtab %}
{% endtabs %}
