javascript - 为什么带有 .substring() 的变量不反射(reflect) css 样式?

标签 javascript

使用纯 JavaScript,我尝试创建一个价格验证函数,该函数在使用时验证输入表单的价格。我的验证有 4 个要求:

  1. 输入必须是数字且不能为空
  2. 如果输入小数,则小数点前后必须至少有 1 个字符
  3. 输入的价格必须是 1 美元到 99.99 美元(含)之间的数字
  4. 输入的价格之间不得有空格

这是我的代码:

function formCheck() {
  var success = true; //default, assumes client enters all fields correctly so "process.html" will load
  var msgBox = document.getElementById('divMessage'); //feedback div

  //Price Variables
  var movPrice = document.getElementById('txtPrice');
  var priceFdBk1 = '<ul><li> Please enter <b>numbers</b> only. </li></ul>';
  var priceFdBk2 =
    '<ul><li> You entered a decimal point. Please enter a <b>number</b> both before and after the decimal place. </li></ul>';
  var priceFdBk3 = '<ul><li> Please enter a movie price between $1.00 to $99.99 (up to 2 decimal places). </li></ul>';
  var priceFdBk4 = '<ul><li> Please do not leave a space when entering the movie price. </li></ul>';

  //Price Validation
  function priceCheck(price, fdBk1, fdBk2, fdBk3, fdBk4) {
    //arguments = price and feedbacks if errors are made
    var price_clean = price.value.trim(); //price entered by client without whitespace
    var price_len = price_clean.length; //number of characters in price entered

    //If there is a $ sign, remove it first
    var dollarSensor = price_clean.charAt(0);
    if (dollarSensor == '$') {
      price_clean = price_clean.substring(1);
    }

    //If there is a decimal point, obtain pre- and post-decimal characters
    if (price_clean.indexOf('.') > -1) {
      var deciSensor = 1; //remember that input has a decimal
      var intValue = price_clean.split('.')[0]; //obtain pre-decimal characters)
      var decimalValue = price_clean.split('.')[1]; //obtain post-decimal characters
      var postCounter = 0;
      for (var j = 0; j < decimalValue.length; j++) {
        //count number of decimal places
        postCounter += 1;
      }
    }

    //Filter 1: Input must be a number and cannot be empty
    if (isNaN(price_clean) || price_clean == '') {
      msgBox.innerHTML = fdBk1;
      price.className = 'yellow';
      success = false;
    }

    //Filter 2: If a decimal is entered, there must at least be 1 pre- and post-decimal character
    else if ((deciSensor == 1 && intValue == '') || (deciSensor == 1 && decimalValue == '')) {
      //if client did not enter a number before and after the decimal point
      msgBox.innerHTML = fdBk2;
      price.className = 'yellow';
      success = false;
    }

    //Filter 3: Price entered must be a number that is between $1 and $99.99 (both inclusive)
    else if (price_clean < 1 || price_clean > 99.99 || postCounter > 2) {
      msgBox.innerHTML = fdBk3; //message in feedback div
      price.className = 'yellow';
      success = false; //prevent loading of "process.html" since selected movie is invalid
    } else {
      price.className = 'transparent';
    }

    //Filter 4: Price entered must not have whitespaces in between
    for (var i = 0; i < price_len; i++) {
      oneDigit = price_clean.charAt(i);
      if (oneDigit == ' ') {
        //if the price float character has a whitespace
        msgBox.innerHTML = fdBk4; //message in feedback div
        price.className = 'yellow'; //highlight error in client's input
        success = false; //prevent loading of "process.html" since selected movie is invalid
      } else if (oneDigit == '') {
        //if the price float character has no whitespace
        price.className = 'transparent'; //remove highlight from client's input
      }
    }
  }
  priceCheck(movPrice, priceFdBk1, priceFdBk2, priceFdBk3, priceFdBk4);

  return success;
}
.yellow {
  background-color: yellow;
}

.transparent {
  background-color: transparent;
}

h1 {
  color: #7157ff;
}

hr {
  display: block;
  border: 0;
  border-top: 3px solid #f90;
  padding: 0;
}

textarea {
  width: 70%;
}

#div_main {
  font-family: Sans-serif;
  margin: auto;
  margin-top: 30px;
  width: 500px;
}

#div_left {
  width: 150px;
  display: inline-block;
  float: left;
}

#div_left p {
  margin-bottom: 19px;
}

#div_right {
  width: 350px;
  display: inline-block;
  float: right;
}

.clear {
  clear: both;
}
<div id="div_main">
  <h1>
    Add Movie
  </h1>
  <hr>
  <form action="process.html" method="POST">
    <div id="div_left">
      <p>Price* ($):</p>
    </div>
    <div id="div_right">
      <p><input type="text" id="txtPrice" name="txtPrice"></p>
    </div>
    <input type="submit" id="btnSubmit" onclick="return formCheck()">
  </form>
  <div id="divMessage">
    *denotes compulsary fields.
  </div>
</div>

该代码工作正常,但有 1 个问题,我怀疑该问题来自这一行:

price_clean = price_clean.substring(1)

具体来说,每当我在表单中输入“$”符号时,我的代码都会删除“$”符号并照常验证输入。但是,当输入无效时,它不再以黄色突出显示输入框。

我可以知道发生了什么事吗?如何使用普通 JavaScript 解决这个问题?谢谢

最佳答案

您的问题是,您添加了黄色突出显示,但随后在最终的 for 循环中将其删除,这是由于您的最终 for 循环使用了 price_len,该值是在之前计算的您删除了$。因此,您的 for 循环将执行一次额外的迭代,因此 .charAt(i) 尝试访问不在字符串中的索引,从而为您提供一个空字符串。要解决此问题,您可以在删除附加 $ 后计算长度:

function formCheck() {
  var success = true; //default, assumes client enters all fields correctly so "process.html" will load
  var msgBox = document.getElementById('divMessage'); //feedback div

  //Price Variables
  var movPrice = document.getElementById('txtPrice');
  var priceFdBk1 = '<ul><li> Please enter <b>numbers</b> only. </li></ul>';
  var priceFdBk2 =
    '<ul><li> You entered a decimal point. Please enter a <b>number</b> both before and after the decimal place. </li></ul>';
  var priceFdBk3 = '<ul><li> Please enter a movie price between $1.00 to $99.99 (up to 2 decimal places). </li></ul>';
  var priceFdBk4 = '<ul><li> Please do not leave a space when entering the movie price. </li></ul>';

  //Price Validation
  function priceCheck(price, fdBk1, fdBk2, fdBk3, fdBk4) {
    //arguments = price and feedbacks if errors are made
    var price_clean = price.value.trim(); //price entered by client without whitespace
    

    //If there is a $ sign, remove it first
    var dollarSensor = price_clean.charAt(0);
    if (dollarSensor == '$') {
      price_clean = price_clean.substring(1);
    }

    var price_len = price_clean.length; //number of characters in price entered
    //If there is a decimal point, obtain pre- and post-decimal characters
    if (price_clean.indexOf('.') > -1) {
      var deciSensor = 1; //remember that input has a decimal
      var intValue = price_clean.split('.')[0]; //obtain pre-decimal characters)
      var decimalValue = price_clean.split('.')[1]; //obtain post-decimal characters
      var postCounter = 0;
      for (var j = 0; j < decimalValue.length; j++) {
        //count number of decimal places
        postCounter += 1;
      }
    }

    //Filter 1: Input must be a number and cannot be empty
    if (isNaN(price_clean) || price_clean == '') {
      msgBox.innerHTML = fdBk1;
      price.className = 'yellow';
      success = false;
    }

    //Filter 2: If a decimal is entered, there must at least be 1 pre- and post-decimal character
    else if ((deciSensor == 1 && intValue == '') || (deciSensor == 1 && decimalValue == '')) {
      //if client did not enter a number before and after the decimal point
      msgBox.innerHTML = fdBk2;
      price.className = 'yellow';
      success = false;
    }

    //Filter 3: Price entered must be a number that is between $1 and $99.99 (both inclusive)
    else if (price_clean < 1 || price_clean > 99.99 || postCounter > 2) {
      msgBox.innerHTML = fdBk3; //message in feedback div
      price.className = 'yellow';
      success = false; //prevent loading of "process.html" since selected movie is invalid
    } else {
      price.className = 'transparent';
    }

    //Filter 4: Price entered must not have whitespaces in between
    for (var i = 0; i < price_len; i++) {
      oneDigit = price_clean.charAt(i);
      if (oneDigit == ' ') {
        //if the price float character has a whitespace
        msgBox.innerHTML = fdBk4; //message in feedback div
        price.className = 'yellow'; //highlight error in client's input
        success = false; //prevent loading of "process.html" since selected movie is invalid
      } else if (oneDigit == '') {
        //if the price float character has no whitespace
        price.className = 'transparent'; //remove highlight from client's input
      }
    }
  }
  priceCheck(movPrice, priceFdBk1, priceFdBk2, priceFdBk3, priceFdBk4);

  return success;
}
.yellow {
  background-color: yellow;
}

.transparent {
  background-color: transparent;
}

h1 {
  color: #7157ff;
}

hr {
  display: block;
  border: 0;
  border-top: 3px solid #f90;
  padding: 0;
}

textarea {
  width: 70%;
}

#div_main {
  font-family: Sans-serif;
  margin: auto;
  margin-top: 30px;
  width: 500px;
}

#div_left {
  width: 150px;
  display: inline-block;
  float: left;
}

#div_left p {
  margin-bottom: 19px;
}

#div_right {
  width: 350px;
  display: inline-block;
  float: right;
}

.clear {
  clear: both;
}
<div id="div_main">
  <h1>
    Add Movie
  </h1>
  <hr>
  <form action="process.html" method="POST">
    <div id="div_left">
      <p>Price* ($):</p>
    </div>
    <div id="div_right">
      <p><input type="text" id="txtPrice" name="txtPrice"></p>
    </div>
    <input type="submit" id="btnSubmit" onclick="return formCheck()">
  </form>
  <div id="divMessage">
    *denotes compulsary fields.
  </div>
</div>

不过,您可以考虑对代码进行一些改进:

  1. 使用 constlet 代替 var(以帮助最大限度地减少范围问题)
  2. 更新您的代码以使用 classList.toggle()删除/添加您的突出显示类
  3. 考虑使用正则表达式或 HTML5 验证以及自定义验证消息 setCustomValidity()
  4. 通过 .addEventListener() 使用 DOM2 事件处理程序与 e.preventDefault()而不是 DOM0 (onxyz) HTML 属性

关于javascript - 为什么带有 .substring() 的变量不反射(reflect) css 样式?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70224938/

相关文章:

javascript - 是否可以使用 JavaScript 两次设置相同的 CSS 属性?

javascript - 使用 JSON 字符串为 jQuery 加载 Flexigrid

c# - javascript按键按下问题

javascript - 防止 window.location.href 编码 url

javascript - 访问对象元素

ExtJS 和 Spring 3.0 MVC 的 Javascript 测试框架

javascript - bootstrap col push pull 使用移动版

javascript - Google Maps API 服务器拒绝了您的请求。非法请求。缺少 'size' 参数

javascript - 如何使用 Node.js 将 blob base64 字符串上传到谷歌云存储

javascript - 如何滑动响应式 SVG slider ?