Почему переменная с .substring() не отражает стиль css?

#javascript

#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 == '

 .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? Спасибо

Комментарии:

1. кстати, почему бы не использовать регулярное выражение для проверки?

2. Спасибо за ваш ответ. Как вы могли подозревать, это для присваивания, и регулярное выражение не разрешено.

3. <input type="number" min="1" max="99.99" step="0.01" />

4. Не относите класс непосредственно к переменной, присвойте класс (в зависимости от результата) идентификатору div / input, где будет отображаться вывод.

Ответ №1:

Ваша проблема заключается в том, что вы добавляете желтую подсветку, но затем удаляете ее в своем последнем цикле 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 == '

 .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. Используйте const или let вместо var (чтобы помочь свести к минимуму проблемы с областью видимости)
  2. Обновите свой код, чтобы использовать classList.toggle() его для удаления / добавления класса highlight
  3. Рассмотрите возможность использования регулярных выражений или проверки HTML5 с пользовательскими сообщениями проверки с использованием setCustomValidity()
  4. Используйте обработчики событий DOM2, используя .addEventListener() with e.preventDefault() вместо DOM0 (onxyz) HTML-атрибутов

Ответ №2:

Небольшое исправление в вашем коде: вы установили price_len перед удалением ведущего $

    const price_len = price_clean.length;
   for(var i=0; i<price_len; i  ){
     ...
   }
 
 <html>
    <head>
    <style> 
        .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;
    }
    </style>

    <script language="javascript">
        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 amp;amp; intValue==""||deciSensor==1 amp;amp; 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
        const price_len = price_clean.length;
        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;
}
</script>
</head>
<body>
<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>
</body>
</html> 

) {
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 amp;amp; intValue == '') || (deciSensor == 1 amp;amp; 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;
}



Код работает нормально, но имеет 1 проблему, которая, как я подозреваю, исходит из этой строки:


В частности, всякий раз, когда я ввожу знак "$" в форму, мой код удаляет знак "$" и проверяет ввод, как обычно. Однако, когда ввод неверен, поле ввода больше не выделяется желтым цветом.

Могу ли я узнать, что происходит и как это можно исправить с помощью ванильного javascript? Спасибо

Комментарии:

1. кстати, почему бы не использовать регулярное выражение для проверки?

2. Спасибо за ваш ответ. Как вы могли подозревать, это для присваивания, и регулярное выражение не разрешено.

3. <input type="number" min="1" max="99.99" step="0.01" />

4. Не относите класс непосредственно к переменной, присвойте класс (в зависимости от результата) идентификатору div / input, где будет отображаться вывод.

Ответ №1:

Ваша проблема заключается в том, что вы добавляете желтую подсветку, но затем удаляете ее в своем последнем цикле for , это связано с использованием вашего окончательного цикла for price_len , который вычисляется перед удалением $ . В результате ваш цикл for выполняет одну дополнительную итерацию и поэтому .charAt(i) пытается получить доступ к индексу, которого нет в вашей строке, выдавая вам пустую строку. Чтобы исправить это, вы можете рассчитать длину после удаления дополнительного $ :




Однако есть несколько улучшений, которые вы можете рассмотреть в своем коде:

  1. Используйте const или let вместо var (чтобы помочь свести к минимуму проблемы с областью видимости)
  2. Обновите свой код, чтобы использовать classList.toggle() его для удаления / добавления класса highlight
  3. Рассмотрите возможность использования регулярных выражений или проверки HTML5 с пользовательскими сообщениями проверки с использованием setCustomValidity()
  4. Используйте обработчики событий DOM2, используя .addEventListener() with e.preventDefault() вместо DOM0 (onxyz) HTML-атрибутов

Ответ №2:

Небольшое исправление в вашем коде: вы установили price_len перед удалением ведущего $



) {
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 amp;amp; intValue == '') || (deciSensor == 1 amp;amp; 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;
}



Однако есть несколько улучшений, которые вы можете рассмотреть в своем коде:

  1. Используйте const или let вместо var (чтобы помочь свести к минимуму проблемы с областью видимости)
  2. Обновите свой код, чтобы использовать classList.toggle() его для удаления / добавления класса highlight
  3. Рассмотрите возможность использования регулярных выражений или проверки HTML5 с пользовательскими сообщениями проверки с использованием setCustomValidity()
  4. Используйте обработчики событий DOM2, используя .addEventListener() with e.preventDefault() вместо DOM0 (onxyz) HTML-атрибутов

Ответ №2:

Небольшое исправление в вашем коде: вы установили price_len перед удалением ведущего $



) {
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 amp;amp; intValue == ») || (deciSensor == 1 amp;amp; 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;
}



Код работает нормально, но имеет 1 проблему, которая, как я подозреваю, исходит из этой строки:


В частности, всякий раз, когда я ввожу знак «$» в форму, мой код удаляет знак «$» и проверяет ввод, как обычно. Однако, когда ввод неверен, поле ввода больше не выделяется желтым цветом.

Могу ли я узнать, что происходит и как это можно исправить с помощью ванильного javascript? Спасибо

Комментарии:

1. кстати, почему бы не использовать регулярное выражение для проверки?

2. Спасибо за ваш ответ. Как вы могли подозревать, это для присваивания, и регулярное выражение не разрешено.

3. <input type="number" min="1" max="99.99" step="0.01" />

4. Не относите класс непосредственно к переменной, присвойте класс (в зависимости от результата) идентификатору div / input, где будет отображаться вывод.

Ответ №1:

Ваша проблема заключается в том, что вы добавляете желтую подсветку, но затем удаляете ее в своем последнем цикле for , это связано с использованием вашего окончательного цикла for price_len , который вычисляется перед удалением $ . В результате ваш цикл for выполняет одну дополнительную итерацию и поэтому .charAt(i) пытается получить доступ к индексу, которого нет в вашей строке, выдавая вам пустую строку. Чтобы исправить это, вы можете рассчитать длину после удаления дополнительного $ :




Однако есть несколько улучшений, которые вы можете рассмотреть в своем коде:

  1. Используйте const или let вместо var (чтобы помочь свести к минимуму проблемы с областью видимости)
  2. Обновите свой код, чтобы использовать classList.toggle() его для удаления / добавления класса highlight
  3. Рассмотрите возможность использования регулярных выражений или проверки HTML5 с пользовательскими сообщениями проверки с использованием setCustomValidity()
  4. Используйте обработчики событий DOM2, используя .addEventListener() with e.preventDefault() вместо DOM0 (onxyz) HTML-атрибутов

Ответ №2:

Небольшое исправление в вашем коде: вы установили price_len перед удалением ведущего $