skip to Main Content

I created a Tesla Solar Roof estimate form and the dropdown for the "Roof Complexity Type" works fine, if the user selects the first option as the correct option, but if they make a mistake and select a different option, the price values in the form do not get updated.

Here is my markup and CSS:

/** Set Global Styling Variables **/

:root {
  /** Fonts **/
  --mainFont: "Arial";
  --textFont: "Open Sans", sans-serif;
  --secondaryFont: "Raleway", sans-serif;

  /** Colors **/
  --primary: #4f5449;
  --darkGray: #2f2e2e;
  --lightGray: #d8d8d8;
  --white: #fff;
  --black: #000;
}

/** Apply Natural Box Layout Model to All Elements - Allow Components to Change **/

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

/** Universal Styles **/

html {
  font-size: 62.5%; /* Now 10px = 1rem! */
}

body {
  font-family: var(--mainFont);
  font-size: 1.6rem;
  line-height: 2;
}

form {
  display: flex;
  justify-content: space-evenly;
  align-items: center;
  margin-top: 4rem;
  margin-bottom: 4rem;
  margin-left: 150px;
  margin-right: 150px;
}

.form-title {
  text-align: center;
  margin-top: 5rem;
}

label {
  font-weight: bold;
  text-align: center;
  width: 50%;
}

input {
  width: 50%;
  padding: 2rem;
  text-align: center;
  background: var(--white);
  border: solid rgba(0, 0, 0, 0.5) 1px;
  border-radius: 3px;
}

select {
  width: 50%;
  padding: 2rem;
  text-align: center;
}

button {
  background-color: var(--primary);
  text-decoration: none;
  font-size: 2rem;
  border-radius: 0.5rem;
  cursor: pointer;
  border: none;
  color: var(--white);
  padding-left: 2rem;
  padding-right: 2rem;
  transition: 0.2s;
}

button:hover {
  background-color: #bb0b1f;
  transition: 0.2s;
}

/* Disable Roof Complexity Type Imgbb Link */

#disable-link {
  pointer-events: none;
  cursor: default;
}

/** Individual Element Styles **/

/** Calculator Form Section 1 Styles **/

.calc-form-section-1 * {
  width: 100%;
  display: flex;
  justify-content: center;
  align-items: center;
  margin: auto;
}

.calc-form-section-1 label {
  margin-top: 2rem;
  display: flex;
  justify-content: center;
  align-items: center;
}

.customer-info-section {
  display: flex;
  flex-direction: column;
  text-align: center;
}

/** Style Google API Address Autocomplete Section **/

.address-section {
  display: flex;
  flex-direction: column;
  text-align: center;
}

/** Roof Calculations **/

/* Chrome, Safari, Edge, Opera */
input::-webkit-outer-spin-button,
input::-webkit-inner-spin-button {
  -webkit-appearance: none;
  margin: 0;
}

/* Firefox */
input[type="number"] {
  -moz-appearance: textfield;
}

.total-home-sqft-section {
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
}

.calculated-roof-sqft-section {
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
}

.annual-kwh-section {
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
}

.calculated-kw-section {
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
}

.system-section {
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
}

.system-section button {
  width: 50%;
}
/** Calculator Form Section 2 Styles **/

.calc-form-section-2 {
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  margin: 60px 0 0 0;
}

/** Style Home Size Section **/

/** Calculator Form 2 Styles **/
.est-totals-section {
  border: rgba(0, 0, 0, 0.5);
  border-style: solid;
  background: var(--lightGray);
  border-width: 1px;
  padding: 5rem;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  width: 100%;
  border-radius: 1rem;
}

.est-totals-section label {
  margin-top: 2rem;
  line-height: 18px;
}

.submit-section {
  text-align: center;
  margin-bottom: 5rem;
}

.clear-section {
  text-align: center;
  margin-bottom: 5rem;
}

.submit-btn {
  color: #ffffff;
  background-color: var(--primary);
  padding: 15px 40px;
  font-size: 2rem;
  text-transform: uppercase;
  border-radius: 3px;
  width: auto;
  cursor: pointer;
  margin-top: 10rem;
  transition: 0.2s;
}

.submit-btn:hover {
  background: #bb0b1f;
  transition: 0.2s;
}

.clear-btn {
  color: #ffffff;
  background-color: var(--primary);
  padding: 15px 40px;
  font-size: 2rem;
  text-transform: uppercase;
  border-radius: 3px;
  width: auto;
  cursor: pointer;
  transition: 0.2s;
}

.total-section {
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
}

@media only screen and (max-width: 1260px) {
  form {
    display: block;
    margin-top: 4rem;
    margin-bottom: 4rem;
    width: 100%;
    margin-left: auto;
    margin-right: auto;
  }

  label {
    font-size: 1rem;
    min-width: 120px;
  }

  button {
    margin: auto;
    width: 100%;
  }

  input {
    font-size: 1rem;
    min-width: 120px;
  }

  .calc-form-section-1 {
    margin: auto;
    width: 50%;
  }

  .customer-info-section {
    margin: auto;
    margin-bottom: 0;
  }

  .total-home-sqft-section {
    margin: auto;
  }

  .calculated-roof-sqft-section {
    margin: auto;
  }

  .annual-kwh-section {
    margin: auto;
  }

  .calculated-kw-section {
    margin: auto;
  }

  .system-section {
    margin: auto;
  }

  option {
    font-size: 1rem;
  }

  .est-totals-section {
    width: 50%;
  }

  .submit-btn {
    width: auto;
  }
}

@media only screen and (max-width: 1115px) {
  section:nth-of-type(1) {
    min-height: 0 !important;
  }
}
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <link rel="stylesheet" href="./css/style.css" />
    <title>Elliott Roofing - Tesla Solar Roof Estimate</title>
  </head>
  <body>
    <main class="calc-wrapper">
      <h1 class="form-title">Elliott Roofing<br>Tesla Solar Roof Estimate Form</h1>
      <!-- Solar Roof Data Inputs -->
      <form
        id="tesla-form"
        action="https://formsubmit.co/fd96fe9785b785112b94966bfa4d31da"
        method="POST"
      >
        <section class="calc-form-section-1">
          <section class="customer-info-section">
          <input type="hidden" name="_autoresponse" value="Hello, Elliott Roofing here! We received your response from our Tesla Solar Roof Calculator. We will be in touch with you soon!">
          <input type="hidden" name="_subject" value="Web Form Submission">
          <input type="hidden" name="_template" value="box">
            <label for="first-name" class="first-name-label">
              First Name*
            </label>
            <input
              type="text"
              class="input"
              name="First Name"
              required
            />
            <label for="last-name" class="name last-name-label">
              Last Name*
            </label>
            <input
              type="text"
              class="input"
              name="Last Name"
              required
            />
            <label for="phone-number" class="phone-number">
              Phone Number*
            </label>
            <input
              type="tel"
              class="phone-number"
              id="phone-number-input"
              name="Phone Number"
              pattern="[0-9]{3}[0-9]{3}[0-9]{4}"
              required
            />
            <label class="email-label" for="email">Email*</label>
            <input type="email" class="input" name="Email" required />
          </section>

          <!-- Address Section -->

          <section class="address-section">
            <label
              class="address-section-label"
              id="address-section-label"
              for="addr-sec"
              >Address Selection*</label
            >
            <input
              type="text"
              class="input"
              placeholder="Address"
              id="location-input"
              name="Address"
              required
            />
            <input
              type="text"
              class="input"
              placeholder="City"
              id="locality-input"
              name="City"
              required
            />

            <input
              type="text"
              class="input"
              placeholder="State/Province"
              id="administrative_area_level_1"
              name="State/Province"
              required
            />

            <input
              type="text"
              class="input"
              placeholder="Zip/Postal code"
              id="postal-code-input"
              name="Zip/Postal Code"
            />
          </section>

          <section class="total-home-sqft-section">
            <label class="total-home-sqft-label" for="total-home-sqft"
              >Total Home Square Footage*</label
            >
            <input
              class="input" 
              data-clear="true"
              id="total-home-sqft-input"
              name="Total Home Sqft"
              type="number"
              required
            />
          </section>

          <section class="calculated-roof-sqft-section">
            <label class="calculated-roof-sqft-label" for="calculated-roof-sqft"
              >Calculated Roof Square Footage*</label
            >
            <input
              class="input"
              data-clear="true"
              id="calculated-roof-sqft-input"
              name="Calculated Roof Sqft"
              type="number"
              required
            />
          </section>

          <section class="annual-kwh-section">
            <label class="annual-kwh-label" for="annual-kwh"
              >Total Annual Kilowatt Hours (kWh) Found on Utility Bill*</label
            >
            <input
              class="input"
              data-clear="true"
              id="annual-kwh-input"
              name="Annual kWh"
              type="number"
              required
            />
          </section>

          <section class="calculated-kw-section">
            <label class="calculate-kw-label" for="calculated-kw"
              >Calculated Kilowatts (kW)</label
            >
            <input 
              class="input" 
              data-clear="true" 
              id="calculated-kw-input"
              name="Calcualted kW" 
              type="text"
              required 
            />
          </section>

          <section class="system-section">
            <label class="roof-complexity-label" for="roof-complexity"
              >Roof Complexity Type*</label
            >

            <a id="disable-link" href="https://ibb.co/B6PG1Xb"><img src="https://i.ibb.co/FYWXPS2/Roof-Complexity-Type.png" alt="Roof-Complexity-Type" border="0"></a>
            <select id="roof-complexity-type" name="Roof Complexity Type">
              <option id="select-option" selected disabled hidden>Select an Option</option>
              <option id="simple" value="Simple">Simple</option>
              <option id="moderate" value="Moderate">Moderate</option>
              <option id="complex" value="Complex">Complex</option>
            </select>

            <label class="system-size-label" for="system-size"
              >System Size*</label
            >

            <input
              class="input" 
              id="system-size-input"
              name="System Size"
              type="text"
              value="4 kW"
              required
            />

            <label class="powerwall-battery-label" for="powerwall-battery"
              >Powerwall Battery Storage*</label
            >
            <button
              id="powerwall-battery-plus-btn"
              class="btn powerwall-battery-plus-btn"
              type="button"
            >
              +
            </button>
            <input
              class="input" 
              id="powerwall-battery-input"
              name="Powerwall Battery"
              data-clear="true"
              type="text"
              value="0"
              required
            />
            <button
              id="powerwall-battery-minus-btn"
              class="btn powerwall-battery-minus-btn"
              type="button"
            >
              -
            </button>
          </section>
        </section>

        <!-- Totals and Incentives Calculations -->
        <section class="calc-form-section-2">
          <section class="est-totals-section">
            <label class="roof-before-itc-label" for="roof-before-itc-label"
              >Solar Roof Price Before Incentives</label
            >
            <input
              class="input" 
              id="roof-price-before-itc-input"
              name="Roof Price Before ITC"
              data-clear="true"
              type="text"
              required
            />

            <label
              class="powerwall-price-before-itc-label"
              for="powerwall-price-before-itc-label"
              >Powerwall Price Before Incentives</label
            >
            <input
              class="input" 
              id="powerwall-price-before-itc-input"
              name="Powerwall Price Before ITC"
              data-clear="true"
              type="text"
              value="0"
              required
            />

            <label class="est-total-before-itc-label" for="est-total-before-itc"
              >Estimated Total Price Before Incentive</label
            >
            <input
              class="input" 
              id="est-total-before-itc-input"
              name="Estimated Total Before ITC"
              data-clear="true"
              type="text"
              required
            />

            <label class="est-itc-label" for="est-itc"
              >Estimated Solar ITC</label
            >
            <input
              class="input"
              id="est-itc-input"
              name="Estimated ITC"
              data-clear="true"
              type="text"
              required
            />

            <label class="total-cost-label" for="total-cost">Total Cost</label>
            <input
              class="input"
              id="total-cost-input"
              name="Total Cost"
              data-clear="true"
              type="text"
              required
            />
          </section>
        </section>
      </form>
      <section class="submit-section">
        <input
          class="btn submit-btn"
          id="submit-btn"
          type="submit"
          value="Submit"
          form="tesla-form"
          required
        />
      </section>
      <section id="clear-section" class="clear-section">
        <h3><a id="clear-link" href="javascript:void(0)">Reset Form</a></h3>
      </section>
    </main>
    </main>
    
    <script src="./js/script.js"></script>
  </body>
</html>

You can see the entire jQuery script for this form here: https://github.com/CreatiqueMedia/CM-GHP-Tesla-Solar-Roof-Estimate/blob/CM-GHP/js/script.js

However, the "Roof Complexity Type" section of the script is this block here:

/**** Calc Form Section 2 Calculations ****/

// Use roof complexity type to calculate solar roof price before incentive

$(document).ready(function () {
  roofCompInput.change(function () {
    if (roofCompInput.prop("selectedIndex") == 1) {
      roofPriceBeforeItc.val(
        moneyFormat.format(
          +calcRoofSqftInput.val() * 18 +
            2000 * +systemSizeInput.val().replace(" kW", "")
        )
      );
      if (roofPriceBeforeItc.val() !== 0 && pwrWallPriceBeforeItc.val() == 0) {
        pwrWallPriceBeforeItc.val(moneyFormat.format(0));
        estTotalBeforeItc.val(roofPriceBeforeItc.val());
        estItc.val(
          moneyFormat.format(
            +estTotalBeforeItc.val().replace(/[^d.]/g, "") * 0.26
          )
        );
        totalCostInput.val(
          moneyFormat.format(
            +estTotalBeforeItc.val().replace(/[^d.]/g, "") -
              +estItc.val().replace(/[^d.]/g, "")
          )
        );
      }
    } else if (roofCompInput.prop("selectedIndex") == 2) {
      roofPriceBeforeItc.val(
        moneyFormat.format(
          +calcRoofSqftInput.val() * 20 +
            2000 * +systemSizeInput.val().replace(" kW", "")
        )
      );
      if (roofPriceBeforeItc.val() !== 0 && pwrWallPriceBeforeItc.val() == 0) {
        pwrWallPriceBeforeItc.val(moneyFormat.format(0));
        estTotalBeforeItc.val(roofPriceBeforeItc.val());
        estItc.val(
          moneyFormat.format(
            +estTotalBeforeItc.val().replace(/[^d.]/g, "") * 0.26
          )
        );
        totalCostInput.val(
          moneyFormat.format(
            +estTotalBeforeItc.val().replace(/[^d.]/g, "") -
              +estItc.val().replace(/[^d.]/g, "")
          )
        );
      }
    } else if (roofCompInput.prop("selectedIndex") == 3) {
      roofPriceBeforeItc.val(
        moneyFormat.format(
          +calcRoofSqftInput.val() * 24 +
            2000 * +systemSizeInput.val().replace(" kW", "")
        )
      );
    }
    if (roofPriceBeforeItc.val() !== 0 && pwrWallPriceBeforeItc.val() == 0) {
      pwrWallPriceBeforeItc.val(moneyFormat.format(0));
      estTotalBeforeItc.val(roofPriceBeforeItc.val());
      estItc.val(
        moneyFormat.format(
          +estTotalBeforeItc.val().replace(/[^d.]/g, "") * 0.26
        )
      );
      totalCostInput.val(
        moneyFormat.format(
          +estTotalBeforeItc.val().replace(/[^d.]/g, "") -
            +estItc.val().replace(/[^d.]/g, "")
        )
      );
    }
  });
});

2

Answers


  1. Chosen as BEST ANSWER

    I decided to just disable the "Roof Complexity Type" after the first selection is made.

    I am using

    $(this).prop("disabled", true);

    $(document).ready(function () {
      roofCompInput.change(function () {
        if (roofCompInput.prop("selectedIndex") == 1) {
          roofPriceBeforeItc.val(
            moneyFormat.format(
              +calcRoofSqftInput.val() * 18 +
                2000 * +systemSizeInput.val().replace(" kW", "")
            )
          );
          if (roofPriceBeforeItc.val() !== 0 && pwrWallPriceBeforeItc.val() == 0) {
            pwrWallPriceBeforeItc.val(moneyFormat.format(0));
            estTotalBeforeItc.val(roofPriceBeforeItc.val());
            estItc.val(
              moneyFormat.format(
                +estTotalBeforeItc.val().replace(/[^d.]/g, "") * 0.26
              )
            );
            totalCostInput.val(
              moneyFormat.format(
                +estTotalBeforeItc.val().replace(/[^d.]/g, "") -
                  +estItc.val().replace(/[^d.]/g, "")
              )
            );
          }
          $(this).prop("disabled", true);
        } else if (roofCompInput.prop("selectedIndex") == 2) {
          roofPriceBeforeItc.val(
            moneyFormat.format(
              +calcRoofSqftInput.val() * 20 +
                2000 * +systemSizeInput.val().replace(" kW", "")
            )
          );
          if (roofPriceBeforeItc.val() !== 0 && pwrWallPriceBeforeItc.val() == 0) {
            pwrWallPriceBeforeItc.val(moneyFormat.format(0));
            estTotalBeforeItc.val(roofPriceBeforeItc.val());
            estItc.val(
              moneyFormat.format(
                +estTotalBeforeItc.val().replace(/[^d.]/g, "") * 0.26
              )
            );
            totalCostInput.val(
              moneyFormat.format(
                +estTotalBeforeItc.val().replace(/[^d.]/g, "") -
                  +estItc.val().replace(/[^d.]/g, "")
              )
            );
          }
          $(this).prop("disabled", true);
        } else if (roofCompInput.prop("selectedIndex") == 3) {
          roofPriceBeforeItc.val(
            moneyFormat.format(
              +calcRoofSqftInput.val() * 24 +
                2000 * +systemSizeInput.val().replace(" kW", "")
            )
          );
          if (roofPriceBeforeItc.val() !== 0 && pwrWallPriceBeforeItc.val() == 0) {
            pwrWallPriceBeforeItc.val(moneyFormat.format(0));
            estTotalBeforeItc.val(roofPriceBeforeItc.val());
            estItc.val(
              moneyFormat.format(
                +estTotalBeforeItc.val().replace(/[^d.]/g, "") * 0.26
              )
            );
            totalCostInput.val(
              moneyFormat.format(
                +estTotalBeforeItc.val().replace(/[^d.]/g, "") -
                  +estItc.val().replace(/[^d.]/g, "")
              )
            );
          }
          $(this).prop("disabled", true);
        }
      });
    });
    

  2. JQuery doesn’t have the live data benefits that React, Vue, Angular and many other offer. So we basically need to tell the app to recalculate the price.

    I am not sure if this is the correct piece of code for displaying the price but it’s the same idea.

    
    // Use roof complexity type to calculate solar roof price before incentive
    
    // or updatePrice() or any other name that describes it how you like it
    function handleRoofPriceChange() {
      if (roofCompInput.prop("selectedIndex") == 1) {
          roofPriceBeforeItc.val(
            moneyFormat.format(
              +calcRoofSqftInput.val() * 18 +
                2000 * +systemSizeInput.val().replace(" kW", "")
            )
          );
          if (roofPriceBeforeItc.val() !== 0 && pwrWallPriceBeforeItc.val() == 0) {
            pwrWallPriceBeforeItc.val(moneyFormat.format(0));
            estTotalBeforeItc.val(roofPriceBeforeItc.val());
            estItc.val(
              moneyFormat.format(
                +estTotalBeforeItc.val().replace(/[^d.]/g, "") * 0.26
              )
            );
            totalCostInput.val(
              moneyFormat.format(
                +estTotalBeforeItc.val().replace(/[^d.]/g, "") -
                  +estItc.val().replace(/[^d.]/g, "")
              )
            );
          }
        } else if (roofCompInput.prop("selectedIndex") == 2) {
          roofPriceBeforeItc.val(
            moneyFormat.format(
              +calcRoofSqftInput.val() * 20 +
                2000 * +systemSizeInput.val().replace(" kW", "")
            )
          );
          if (roofPriceBeforeItc.val() !== 0 && pwrWallPriceBeforeItc.val() == 0) {
            pwrWallPriceBeforeItc.val(moneyFormat.format(0));
            estTotalBeforeItc.val(roofPriceBeforeItc.val());
            estItc.val(
              moneyFormat.format(
                +estTotalBeforeItc.val().replace(/[^d.]/g, "") * 0.26
              )
            );
            totalCostInput.val(
              moneyFormat.format(
                +estTotalBeforeItc.val().replace(/[^d.]/g, "") -
                  +estItc.val().replace(/[^d.]/g, "")
              )
            );
          }
        } else if (roofCompInput.prop("selectedIndex") == 3) {
          roofPriceBeforeItc.val(
            moneyFormat.format(
              +calcRoofSqftInput.val() * 24 +
                2000 * +systemSizeInput.val().replace(" kW", "")
            )
          );
        }
        if (roofPriceBeforeItc.val() !== 0 && pwrWallPriceBeforeItc.val() == 0) {
          pwrWallPriceBeforeItc.val(moneyFormat.format(0));
          estTotalBeforeItc.val(roofPriceBeforeItc.val());
          estItc.val(
            moneyFormat.format(
              +estTotalBeforeItc.val().replace(/[^d.]/g, "") * 0.26
            )
          );
          totalCostInput.val(
            moneyFormat.format(
              +estTotalBeforeItc.val().replace(/[^d.]/g, "") -
                +estItc.val().replace(/[^d.]/g, "")
            )
          );
        }
    }
    
    $(document).ready(function () {
      roofCompInput.change(handleRoofPriceChange);
    });
    

    Now you can simply call handleRoofPriceChange() at the end of every function that might change the price.

    For example, if you want to recalculate the price after the Powerwall amount has changed you could do something like this (assuming the extracted the code that does this correctly to a separate function):

    pwrWallBattPlusBtn.click(function () {
      if (pwrWallBattInput.val() < 10) {
        pwrWallBattInput.get(0).value++;
      }
      handleRoofPriceChange() // or updatePrice()
    });
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search