Search code examples
javascripthtmlcssbarcode

How to fix non-working buttons in a website?


I need to fix this webpage, because the buttons don’t work. The source code is as follows:

<!DOCTYPE html>
<html lang="en">
<head>
<link rel="icon" href="logos/logo.PNG" type="image/png">
<link rel="shortcut icon" href="logos/logo.PNG" type="image/png">
<title>ElijahSpirit FDM</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jsbarcode/3.11.5/JsBarcode.all.min.js" integrity="sha512-QEAheCz+x/VkKtxeGoDq6nsGyzTx/0LMINTgQjqZ0h3+NjP+bCsPYz3hn0HnBkGmkIFSr7QcEZT+KyEM7lbLPQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>
  body {
    font-family: Arial, sans-serif;
    display: flex;
    justify-content: center;
    align-items: center;
    min-height: 100vh;
    margin: 0;
    background-color: #f5f5f5;
  }
    select {
      border-radius: 10px;
      background-color: white;
      color: black;
      padding: 8px 16px;
      border: 2px solid black;
      font-size: 14px;
      margin: 10px;
      width: 200px;
}
  #container {
    background-color: #ffffff;
    padding: 20px;
    border-radius: 10px;
    box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.2);
  }
  .question {
    text-align: center;
    margin-bottom: 20px;
  }
  .hidden {
    display: none;
  }
button {
  margin: 10px;
  border-radius: 10px; /* Increases the border radius for rounder corners */
  background-color: #00008B; /* Sets the background color to dark blue */
  color: white;
  padding: 10px 20px; /* Adjusts padding for a slightly larger button */
  border: none;
  cursor: pointer;
  font-size: 14px;
}
    input[type="range"] {
    width: 100%; /* Make the range input fill its container */
    margin: 10px 0;
}
    input[type="email"],
    input[type="number"] {
      border-radius: 10px;
      background-color: white;
      color: black;
      padding: 8px 16px;
      border: 2px solid black; /* Adds a black border */
      font-size: 14px;
      margin: 10px;
      width: 150px; /* Adjust the width as needed */
    }
    footer {
      position: fixed; /* Keep the footer fixed at the bottom */
      left: 10px; /* Position it on the left side */
      bottom: 10px; /* Position it at the bottom */
      display: flex;
      align-items: center; /* Vertically center content */
    }

    footer img {
      width: 30px; /* Adjust the image size as needed */
      margin-right: 10px; /* Add spacing between text and image */
    }
</style>
<script>
let currentPrice = 4;
let minimumPrice = 10;
let startPrice = 12;
let currentDiscount = 1;

function updatePrice() {
  const store = parseFloat(document.getElementById('store').value);
  const width = parseInt(document.getElementById('width').value);
  const height = parseInt(document.getElementById('height').value);
  const length = parseInt(document.getElementById('length').value);
  const density = parseInt(document.getElementById('density').value);
  const material = parseFloat(document.getElementById('material').value);
  const color = parseFloat(document.getElementById('color').value);
  const accuracy = parseFloat(document.getElementById('accuracy').value);

  // Calculate the runningPrice with proper order of operations and parentheses
  runningPrice = (
    minimumPrice +
    (startPrice * width * height * length) / 20000000 *
    (1 + density) *
    material *
    color *
    accuracy
  ) * currentDiscount * store;

 currentPrice = Math.round(runningPrice);
document.getElementById('totalPrice').textContent = `Total Price: £${currentPrice}`;

var price = currentPrice;
var formattedPrice = "ES3D" + price.toString().padStart(8, '0');

// Generate the barcode using JsBarcode
JsBarcode("#barcode", formattedPrice, {
  format: "CODE128", // You can choose the barcode format you prefer
  displayValue: true // Display the text (formattedPrice) below the barcode
});

var randomDigits = generateRandomDigits(4); // Generate 4 random digits
var totalPriceValue = currentPrice.toString().padStart(8, '0');
var formattedTotalPrice = "ES3D" + totalPriceValue + randomDigits;

// Append the barcode with the formattedTotalPrice
JsBarcode("#barcode", formattedTotalPrice, {
  format: "CODE128",
  displayValue: true
});

function generateRandomDigits(length) {
  return Math.floor(Math.random() * Math.pow(10, length)).toString().padStart(length, '0');
}

function showNextQuestion(currentQuestion, nextQuestion) {
  document.getElementById(currentQuestion).classList.add('hidden');
  document.getElementById(nextQuestion).classList.remove('hidden');
}

function showEmailAndSummary() {
  const email = document.getElementById('email').value;
  const size = `${document.getElementById('width').value}mm x ${document.getElementById('height').value}mm x ${document.getElementById('length').value}mm`;
  const density = document.getElementById('density').value;
  const material = document.getElementById('material').options[document.getElementById('material').selectedIndex].text;
  const color = document.getElementById('color').options[document.getElementById('color').selectedIndex].text;
  const accuracy = document.getElementById('accuracy').options[document.getElementById('accuracy').selectedIndex].text;

  const orderDetails = `Email: ${email}\nSize: ${size}\nDensity: ${density}\nMaterial: ${material}\nColor: ${color}\nAccuracy: ${accuracy}\nTotal Price: £${currentPrice}`;

  const mailtoLink = `mailto:[email protected]?subject=3D Print Order&body=${encodeURIComponent(orderDetails)}`;
  window.location.href = mailtoLink;
}

function showPreviousQuestion(currentQuestion, previousQuestion) {
  document.getElementById(currentQuestion).classList.add('hidden');
  document.getElementById(previousQuestion).classList.remove('hidden');
}
</script>

</head>
<body>
<div id="container">
  <div id="question0" class="question">
    <p>Press continue to begin</p>
  <p>What location are you at?</p>
    <select id="store" onchange="updatePrice()">
      <option value="1">ElijahSpirit FDM Centre</option>
      <option value="1.25">DIY Store (Sandhurst)</option>
      <option value="1.5">DIY Store (Crowthorne)</option>
    </select>
    <div>
      <button onclick="showNextQuestion('question0', 'question1')">Continue</button>
    </div>
  </div>
  <div id="question1" class="hidden question">
    <p>Question 1: Please enter your email</p>
    <input type="email" id="email">
    <div>
      <button onclick="showNextQuestion('question1', 'question2')">Continue</button>
      <button onclick="showPreviousQuestion('question1', 'question0')">Back</button>
    </div>
  </div>

  <div id="question2" class="hidden question">
    <p>Question 2: Model size</p>
    Width (mm): <input type="number" id="width"><br>
    Height (mm): <input type="number" id="height"><br>
    Length (mm): <input type="number" id="length"><br>
    <div>
      <button onclick="updatePrice(); showNextQuestion('question2', 'question3')">Continue</button>
      <button onclick="showPreviousQuestion('question2', 'question1')">Back</button>
    </div>
  </div>

  <div id="question3" class="hidden question">
    <p>Question 3: Density</p>
    <input type="range" id="density" min="0" max="100" step="1" oninput="updatePrice()">
    <div>
      <button onclick="showNextQuestion('question3', 'question4')">Continue</button>
      <button onclick="showPreviousQuestion('question3', 'question2')">Back</button>
    </div>
  </div>

  <div id="question4" class="hidden question">
    <p>Question 4: Material</p>
    <select id="material" onchange="updatePrice()">
      <option value="1">PLA</option>
      <option value="1.5">PETG</option>
      <option value="4">TPU</option>
    </select>
    <div>
      <button onclick="showNextQuestion('question4', 'question5')">Continue</button>
      <button onclick="showPreviousQuestion('question4', 'question3')">Back</button>
    </div>
  </div>

  <div id="question5" class="hidden question">
    <p>Question 5: Color</p>
    <select id="color" onchange="updatePrice()">
      <optgroup label="Glossy Colors">
        <option value="1">Black</option>
        <option value="1">White</option>
        <option value="1">Grey</option>
        <option value="1">Blue</option>
        <option value="1">Red</option>
        <option value="1">Rainbow</option>
      </optgroup>
      <optgroup label="Matte Colors">
        <option value="1">Navy</option>
        <option value="1">Black</option>
        <option value="1">Cyan</option>
        <option value="1">Grey</option>
        <option value="1">Dark Green</option>
      </optgroup>
    </select>
    <div>
      <button onclick="showNextQuestion('question5', 'question6')">Continue</button>
      <button onclick="showPreviousQuestion('question5', 'question4')">Back</button>
    </div>
  </div>

  <div id="question6" class="hidden question">
    <p>Question 6: Accuracy</p>
    <select id="accuracy" onchange="updatePrice()">
      <option value="1">Draft</option>
      <option value="1.25">Excellent</option>
      <option value="1.5">Water Tight</option>
    </select>
    <div>
      <button onclick="showNextQuestion('question6', 'summary')">Continue</button>
      <button onclick="showPreviousQuestion('question6', 'question5')">Back</button>
    </div>
  </div>

  <div id="summary" class="hidden question">
    <p>Price:</p>
    <p id="totalPrice">Total Price: £4</p>
<canvas id="barcode"></canvas>

    <div>
      <button onclick="showEmailAndSummary()">Place Order</button>
      <button onclick="showPreviousQuestion('summary', 'question6')">Back</button>
    </div>
  </div>
</div>

<script>
  const continueButtons = document.querySelectorAll('button[onclick^="showNextQuestion"]');
  continueButtons.forEach(button => {
    button.insertAdjacentHTML('afterend', '<button onclick="showPreviousQuestion(\'' + button.parentNode.parentNode.id + '\', \'' + button.parentNode.parentNode.previousElementSibling.id + '\')">Back</button>');
  });
</script>
    <footer>
    <img src="logos/logo.PNG" alt="Logo">
    Designed by ElijahSpirit <br> Version 1.2.5 BETA
  </footer>
</body>
</html>

I was expecting the buttons to work, but they don’t! Nothing seems to happen, which is worrying. I’ve reached out to people on Fiverr, but they don’t know the answer. The issue is around the script for Barcode generation or random number generation.


Solution

  • Everything seems to be in order, except you forgot to close your updatePrice function. If you place a curly brace before the generateRandomDigits, the form will work.

      // Append the barcode with the formattedTotalPrice
      JsBarcode("#barcode", formattedTotalPrice, {
        format: "CODE128",
        displayValue: true
      });
    } // <--- HERE
    
    function generateRandomDigits(length) {
      return Math.floor(Math.random() * Math.pow(10, length)).toString().padStart(length, '0');
    }
    

    Make sure you are formatting your code properly. Keeping consistent indention will make it easier to spot issues like this.

    Note: If you check the logs, you will see that you have another issue:

    Uncaught TypeError: Cannot read properties of null (reading 'id')

    Make sure you are applying proper null-checks or use optional chaining i.e. button.parentNode.parentNode?.id

    Snippet

    let currentPrice = 4;
    let minimumPrice = 10;
    let startPrice = 12;
    let currentDiscount = 1;
    
    function updatePrice() {
      const store = parseFloat(document.getElementById('store').value);
      const width = parseInt(document.getElementById('width').value);
      const height = parseInt(document.getElementById('height').value);
      const length = parseInt(document.getElementById('length').value);
      const density = parseInt(document.getElementById('density').value);
      const material = parseFloat(document.getElementById('material').value);
      const color = parseFloat(document.getElementById('color').value);
      const accuracy = parseFloat(document.getElementById('accuracy').value);
    
      // Calculate the runningPrice with proper order of operations and parentheses
      runningPrice = (
        minimumPrice +
        (startPrice * width * height * length) / 20000000 *
        (1 + density) *
        material *
        color *
        accuracy
      ) * currentDiscount * store;
    
      currentPrice = Math.round(runningPrice);
      document.getElementById('totalPrice').textContent = `Total Price: £${currentPrice}`;
    
      var price = currentPrice;
      var formattedPrice = "ES3D" + price.toString().padStart(8, '0');
    
      // Generate the barcode using JsBarcode
      JsBarcode("#barcode", formattedPrice, {
        format: "CODE128", // You can choose the barcode format you prefer
        displayValue: true // Display the text (formattedPrice) below the barcode
      });
    
      var randomDigits = generateRandomDigits(4); // Generate 4 random digits
      var totalPriceValue = currentPrice.toString().padStart(8, '0');
      var formattedTotalPrice = "ES3D" + totalPriceValue + randomDigits;
    
      // Append the barcode with the formattedTotalPrice
      JsBarcode("#barcode", formattedTotalPrice, {
        format: "CODE128",
        displayValue: true
      });
    }
    
    function generateRandomDigits(length) {
      return Math.floor(Math.random() * Math.pow(10, length)).toString().padStart(length, '0');
    }
    
    function showNextQuestion(currentQuestion, nextQuestion) {
      document.getElementById(currentQuestion).classList.add('hidden');
      document.getElementById(nextQuestion).classList.remove('hidden');
    }
    
    function showEmailAndSummary() {
      const email = document.getElementById('email').value;
      const size = `${document.getElementById('width').value}mm x ${document.getElementById('height').value}mm x ${document.getElementById('length').value}mm`;
      const density = document.getElementById('density').value;
      const material = document.getElementById('material').options[document.getElementById('material').selectedIndex].text;
      const color = document.getElementById('color').options[document.getElementById('color').selectedIndex].text;
      const accuracy = document.getElementById('accuracy').options[document.getElementById('accuracy').selectedIndex].text;
    
      const orderDetails = `Email: ${email}\nSize: ${size}\nDensity: ${density}\nMaterial: ${material}\nColor: ${color}\nAccuracy: ${accuracy}\nTotal Price: £${currentPrice}`;
    
      const mailtoLink = `mailto:[email protected]?subject=3D Print Order&body=${encodeURIComponent(orderDetails)}`;
      window.location.href = mailtoLink;
    }
    
    function showPreviousQuestion(currentQuestion, previousQuestion) {
      document.getElementById(currentQuestion).classList.add('hidden');
      document.getElementById(previousQuestion).classList.remove('hidden');
    }
    
    const continueButtons = document.querySelectorAll('button[onclick^="showNextQuestion"]');
    continueButtons.forEach(button => {
      button.insertAdjacentHTML('afterend', '<button onclick="showPreviousQuestion(\'' + button.parentNode.parentNode.id + '\', \'' + button.parentNode.parentNode.previousElementSibling.id + '\')">Back</button>');
    });
    body {
      font-family: Arial, sans-serif;
      display: flex;
      justify-content: center;
      align-items: center;
      min-height: 100vh;
      margin: 0;
      background-color: #f5f5f5;
    }
    
    select {
      border-radius: 10px;
      background-color: white;
      color: black;
      padding: 8px 16px;
      border: 2px solid black;
      font-size: 14px;
      margin: 10px;
      width: 200px;
    }
    
    #container {
      background-color: #ffffff;
      padding: 20px;
      border-radius: 10px;
      box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.2);
    }
    
    .question {
      text-align: center;
      margin-bottom: 20px;
    }
    
    .hidden {
      display: none;
    }
    
    button {
      margin: 10px;
      border-radius: 10px;
      /* Increases the border radius for rounder corners */
      background-color: #00008B;
      /* Sets the background color to dark blue */
      color: white;
      padding: 10px 20px;
      /* Adjusts padding for a slightly larger button */
      border: none;
      cursor: pointer;
      font-size: 14px;
    }
    
    input[type="range"] {
      width: 100%;
      /* Make the range input fill its container */
      margin: 10px 0;
    }
    
    input[type="email"],
    input[type="number"] {
      border-radius: 10px;
      background-color: white;
      color: black;
      padding: 8px 16px;
      border: 2px solid black;
      /* Adds a black border */
      font-size: 14px;
      margin: 10px;
      width: 150px;
      /* Adjust the width as needed */
    }
    
    footer {
      position: fixed;
      /* Keep the footer fixed at the bottom */
      left: 10px;
      /* Position it on the left side */
      bottom: 10px;
      /* Position it at the bottom */
      display: flex;
      align-items: center;
      /* Vertically center content */
    }
    
    footer img {
      width: 30px;
      /* Adjust the image size as needed */
      margin-right: 10px;
      /* Add spacing between text and image */
    }
    <!DOCTYPE html>
    <html lang="en">
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jsbarcode/3.11.5/JsBarcode.all.min.js" integrity="sha512-QEAheCz+x/VkKtxeGoDq6nsGyzTx/0LMINTgQjqZ0h3+NjP+bCsPYz3hn0HnBkGmkIFSr7QcEZT+KyEM7lbLPQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
    
    <div id="container">
      <div id="question0" class="question">
        <p>Press continue to begin</p>
        <p>What location are you at?</p>
        <select id="store" onchange="updatePrice()">
          <option value="1">ElijahSpirit FDM Centre</option>
          <option value="1.25">DIY Store (Sandhurst)</option>
          <option value="1.5">DIY Store (Crowthorne)</option>
        </select>
        <div>
          <button onclick="showNextQuestion('question0', 'question1')">Continue</button>
        </div>
      </div>
      <div id="question1" class="hidden question">
        <p>Question 1: Please enter your email</p>
        <input type="email" id="email">
        <div>
          <button onclick="showNextQuestion('question1', 'question2')">Continue</button>
          <button onclick="showPreviousQuestion('question1', 'question0')">Back</button>
        </div>
      </div>
    
      <div id="question2" class="hidden question">
        <p>Question 2: Model size</p>
        Width (mm): <input type="number" id="width"><br> Height (mm): <input type="number" id="height"><br> Length (mm): <input type="number" id="length"><br>
        <div>
          <button onclick="updatePrice(); showNextQuestion('question2', 'question3')">Continue</button>
          <button onclick="showPreviousQuestion('question2', 'question1')">Back</button>
        </div>
      </div>
    
      <div id="question3" class="hidden question">
        <p>Question 3: Density</p>
        <input type="range" id="density" min="0" max="100" step="1" oninput="updatePrice()">
        <div>
          <button onclick="showNextQuestion('question3', 'question4')">Continue</button>
          <button onclick="showPreviousQuestion('question3', 'question2')">Back</button>
        </div>
      </div>
    
      <div id="question4" class="hidden question">
        <p>Question 4: Material</p>
        <select id="material" onchange="updatePrice()">
          <option value="1">PLA</option>
          <option value="1.5">PETG</option>
          <option value="4">TPU</option>
        </select>
        <div>
          <button onclick="showNextQuestion('question4', 'question5')">Continue</button>
          <button onclick="showPreviousQuestion('question4', 'question3')">Back</button>
        </div>
      </div>
    
      <div id="question5" class="hidden question">
        <p>Question 5: Color</p>
        <select id="color" onchange="updatePrice()">
          <optgroup label="Glossy Colors">
            <option value="1">Black</option>
            <option value="1">White</option>
            <option value="1">Grey</option>
            <option value="1">Blue</option>
            <option value="1">Red</option>
            <option value="1">Rainbow</option>
          </optgroup>
          <optgroup label="Matte Colors">
            <option value="1">Navy</option>
            <option value="1">Black</option>
            <option value="1">Cyan</option>
            <option value="1">Grey</option>
            <option value="1">Dark Green</option>
          </optgroup>
        </select>
        <div>
          <button onclick="showNextQuestion('question5', 'question6')">Continue</button>
          <button onclick="showPreviousQuestion('question5', 'question4')">Back</button>
        </div>
      </div>
    
      <div id="question6" class="hidden question">
        <p>Question 6: Accuracy</p>
        <select id="accuracy" onchange="updatePrice()">
          <option value="1">Draft</option>
          <option value="1.25">Excellent</option>
          <option value="1.5">Water Tight</option>
        </select>
        <div>
          <button onclick="showNextQuestion('question6', 'summary')">Continue</button>
          <button onclick="showPreviousQuestion('question6', 'question5')">Back</button>
        </div>
      </div>
    
      <div id="summary" class="hidden question">
        <p>Price:</p>
        <p id="totalPrice">Total Price: £4</p>
        <canvas id="barcode"></canvas>
    
        <div>
          <button onclick="showEmailAndSummary()">Place Order</button>
          <button onclick="showPreviousQuestion('summary', 'question6')">Back</button>
        </div>
      </div>
    </div>
    
    <footer>
      <img src="logos/logo.PNG" alt="Logo"> Designed by ElijahSpirit <br> Version 1.2.5 BETA
    </footer>