47

I have been testing with radio buttons. Everything seems okay until i ran it through JS lint. I fixed all errors except one:

Unexpected 'for'

for (i = 0; i < radios.length; i += 1) {

Here is my Javascript:

/*global body,window,document,alert*/
(function () {
"use strict";

var UIlogic;

UIlogic = {
    myLoad: function () {
        var elems, elemText, btn1, winter, summer, fall, spring, header, btns;

        winter = "<div><input type='radio' name='cb' id='cbA' value='0'/><label for='cbA'>Winter</label></div>";
        summer = "<div><input type='radio' name='cb' id='cbB' value='1'/><label for='cbB'>Summer</label></div>";
        fall = "<div><input type='radio' name='cb' id='cbC' value='2'/><label for='cbC'>Fall</label></div>";
        spring = "<div><input type='radio' name='cb' id='cbD' value='3'/><label for='cbD'>Spring</label></div>";

        header = "Header";

        btns = "<br /><button class='btns' id='btn1'>Go!</button>";

        elemText = "Menu/nav";

        elems = "<center><div>" + header + "</div></center>";//title
        elems += "<div>" + elemText + "</div></center>";//menu
        elems += "<div id='container'><br />";//container opens
        elems += "<div id='div1'>" + winter + "</div>";
        elems += "<div id='div2'>" + summer + "</div>";
        elems += "<div id='div2'>" + fall + "</div>";
        elems += "<div id='div2'>" + spring + "</div>";
        elems += "<div id='div3'>" + btns + "</div>";
        elems += "</div>";//container closes
        elems += "<h6><div id='footer'>Ehawk 2015</div></h6>";

        body.innerHTML = elems;
        btn1 = document.getElementById("btn1");
        btn1.addEventListener('click', UIlogic.intoFunction, false);

    },
    intoFunction: function () {
        var radios, found, i = 0;
        radios = document.getElementsByName("cb");
        found = 1;
        for (i = 0; i < radios.length; i += 1) {//issue occurs here
            if (radios[i].checked) {
                alert(radios[i].value);
                found = 0;
                break;
            }
        }
        if (found === 1) {
            alert("Please Select Radio");
        }
    }
};
window.onload = function () {
    UIlogic.myLoad();
};
}());

Am i running my loop wrong? why would JSlint see a problem here even thought the code works? I could really use some insight on loops, as i have the most issues with them. I have been told not to use them, but i don't see the problem with running a loop to detect radio buttons and checked radios. Is this something i should be concerned with?

Pointy
  • 371,531
  • 55
  • 528
  • 584
MrEhawk82
  • 751
  • 2
  • 8
  • 22
  • 1
    You can check Tolerate... for statement in the options to suppress this warning. – Bill the Lizard May 28 '15 at 23:23
  • 1
    [Here's a relevant question, despite being tagged java rather than javascript](http://stackoverflow.com/q/6850380/497418) – zzzzBov May 28 '15 at 23:37
  • Also asked [here](http://stackoverflow.com/questions/30265001/what-does-jslint-mean-by-unexpected-expression-i-in-statement-position), though the title could be misleading. – ruffin May 28 '15 at 23:57

2 Answers2

60

JSLint suggests you use other loops such as forEach. http://www.jslint.com/help.html#for

You can just select the tolerate "for statement" option at the bottom if this bothers you but the code looks fine.

Alex
  • 616
  • 5
  • 2
  • 1
    Good find. That's my vote for "accepted answer" there. – garryp May 28 '15 at 23:32
  • 4
    There's one problem with that suggestion - you cannot break a `forEach()` as is conceptually done with the original `for` loop. Consider `every()` in this case. – jdphenix May 28 '15 at 23:37
18

Here's the best explanation I could find for you,

Recently I decided I don't need to use for anymore. I'm done with for loops. for loops were invented, they came out of Fortran. They were intended to be a way of working through an array, but in ES5 we added forEach() and map() and all the others, I was like 'Yeah, that's the way to do it'. The for syntax is so weird anyway with the thing with the three statements in it.

Crockford further goes on to talk about being done with loop constructs altogether in ES6, and using just functional constructs instead.

You can choose to ignore it - just pass the option to JSLint to tolerate for.


However, let's say you decided to do away with the for loop you have. You could with every(). It would be something like (not tested):

intoFunction: function () {
    var radios, found; 
    radios = document.getElementsByName("cb");
    found = Array.prototype.slice.call(radios).every(function(radio) {
        if (radio.checked) { 
            alert(radio.value); 
            return false; 
        }
        return true; 
    }); 

    if (found) {
        alert("Please Select Radio");
    }
}

It is honestly arguable in my opinion if this is easier to understand that a for loop. Honestly it depends upon your own personal / project's coding standards.


Updated with a working snippet demonstrating every() to accomplish this.

function into() {
  var radios, found;
  radios = document.getElementsByName("cb");
  found = Array.prototype.slice.call(radios).every(function(radio) {
    if (radio.checked) {
      alert(radio.value);
      return false;
    }
    return true;
  });

  if (found) {
    alert("Please Select Radio");
  }
}

jQuery("[name='cb']").on("click", into);
jQuery("button").on("click", function() {
  jQuery("[name='cb']").prop("checked", false);
  into();
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<p>
  <label>
    <input type="radio" name="cb" value="M">Male</label>
</p>
<p>
  <label>
    <input type="radio" name="cb" value="F">Female</label>
</p>
<p>
  <label>
    <input type="radio" name="cb" value="I">I don't know</label>
</p>
<p>
  <label>
    <input type="radio" name="cb" value="B">Both</label>
</p>
<p>
  <button>Clear Radios</button>
jdphenix
  • 13,519
  • 3
  • 37
  • 68