Skip to content

Javascript Input type=“color” validation for form

Beginner level with Javascript and have a question regarding the input type color.

I am trying to make the user choose the color black before proceeding with next page of the form. The default color is yellow.

Could someone please help me with this and explain where I have gone wrong or missing something?

And have done research to try figure it out myself but stuck, probably the simplest thing as per normal. Thanks

Here is a snippet:

function validate() {

    var elements = document.getElementById("form1").elements;
        
    for (var i = 0, element; element = elements[i++];) {
            
        if (element.style.backgroundColor =='rgb(255, 153, 153)') {
        
            alert("Please enter data for any fields highlighted in red");
        
            return false;
        
        }

    }
}


function spamCheck() {
        
    //alert("Spam Check Working.......");
        
    var color = document.getElementById("color").value;
        
    if (!color == "#000000") {
            
        alert("Please enter the color black to proceed.");
        color.focus;
        return false;
                
    }
}
<form id="form1">
  <span class="center">Spam Check. What colour is black? (choose a colour) 
    <input name="color" id="color" type="color" value="#FFFF00" />
  </span>
            
  <span class="button">
    <button type="submit" onClick="validate(), spamCheck()">Continue &rarr;  </button>
  </span>
</form>

Answer

There a couple of things to be improved here as the logic does not really add up. Heres your code, amended and annotated with comments:

function validate() {
    var elements = document.getElementById("form1").elements;
    for (var i = 0, element; element = elements[i++];) {

        // When using the `not equal` operator, use it _in the operator_.
        // Putting a `!` in front of a variable will change the variable first
        // before comparing. This can cause unexpected issues!
        // Also added a type check as the button does not have a value of
        // '#000000', so the alert would _always_ show. This prevents that.

        if (element.type === 'color' && element.value !== '#000000') {
            alert("Please enter data for any fields highlighted in red");
            return false;
        }
    }
    // to allow your HTML prevention of submission, make sure to always return a boolean value.
    return true;
}


function spamCheck() {
    // As you want to focus on this element later, store the element
    // NOT the value.
    var color = document.getElementById("color");

    // This is the point where the placement of the `!` is changed
    // Because if you invert the value of a string, you might get
    // unexpected results!
    if (color.value !== "#000000") {
            
        alert("Please enter the color black to proceed.");

        // Focus is a _method_ of an <input> node,
        // not a property, so call it with ().
        // Also, because you originally set color to the _value_, 
        // it is only a string and not the <node>
        color.focus();

        return false; 
    }
    // to allow your HTML prevention of submission, make sure to always return a boolean value.
    return true;
}
<form id="form1">
  <span class="center">Spam Check. What colour is black? (choose a colour) 
    <input name="color" id="color" type="color" value="#FFFF00" />
  </span>
            
  <span class="button">
    <!-- To prevent submission, your onclick is changed -->
    <button type="submit" onClick="return (validate() && spamCheck())">Continue &rarr;  </button>
  </span>
</form>

Please note that your validate() will always throw an alert as your button does not have a value of #000000, which is also considered an element. Therefor not all elements pass your test. However, I have amended this by checking if the elements type is that of color, and only then checking for that value and alerting.

But here’s the main issue: how do you do this properly? Well, javascript uses event listeners for that, and it could greatly improve your code. I have added my suggestion to the snippet below. Keep in mind that attaching events to HTML elements using onSomething attributes on elements is considered bad practise. That’s mostly because it makes your code too tightly coupled together, meaning that if you have to amend it later it will be a mix of JS, HTML and other elements thrown in and it will become confusing.

Event Listeners solve that issue for you, you can attach them to the element using only javascript, but that does mean that your form can be subm,itted without javascript. That’s technically what you want – but keep in mind that SPAM bots usually disable javascript anyhow, so nothing of what you do has any affect unless you write your form using only javascript.

Now, onto an improved version of the provided code that is not as tightly coupled. I added some properties to your HTML (and removed other just to make it simpler but you can keep the spans, for example). These properties are not tightly coupled to JS. They are there for JS to read, but make no difference otherwise. It also means someone who only knows HTML can edit the messages.

The checkColor is now also rolled into your validation function, as is validation to anything. Now even better would be to check using regex patterns, but that’s beyond the scope of this question.

var form = document.getElementById('myForm');

// Only run this function when a submit button is clicked and the form is
// considered to be submitted. Pass the function an event as well.
form.addEventListener('submit', function(event){
  
  // Lets assume the form is valid
  var isValid = true;
  
  // Lets use a standard for loop, it's easier to read
  for(var i = 0, element; element = form.elements[i]; i++){

    // I;ve added two data-properties in your HTML, one that tells us what
    // value your are looking for and another that provides the hint
    // you want to show people
    var match = element.getAttribute('data-match');
    var hint = element.getAttribute('data-hint');

    // If there is something to match and it does not match the value provided
    // then set isValid to false and alert the hint (if there is one);
    if(match && match !== element.value){
       isValid = false;
       if(hint) alert(hint);
    }
  }
  
  // If one element has set the isValid to false, then we want to prevent
  // the form from actually submitting. Heres were the event comes into play:
  // event.preventDefault() will stop the form from actually submitting.
  if(!isValid) event.preventDefault();
  
});
<form id="myForm">
  <input name="color" id="color" data-hint="Enter the color black in HEX to proceed." data-match="#000000" type="color" placeholder="#000000" />
  <input type="submit" value="Continue &rarr;" />
</form>