2

I am trying to make a Js to search & filter items in JSON

so I use many radio in the "form" , the result will be [X,X,X,X,X,X]

I will set 50tags x 3(choose), I can feel my function will be large.

What ways can I change my function to be simpler?

function myFunction() {
  var elements1 = document.getElementsByName("chair"),
    elements2 = document.getElementsByName("car"),
    elements3 = document.getElementsByName("house"),
    elements4 = document.getElementsByName("tree"),
    elements5 = document.getElementsByName("flower"),
    elements6 = document.getElementsByName("grass");
  var i;
  for (var a = "", i = elements1.length; i--;) {
    if (elements1[i].checked) {
      var a = elements1[i].value;
      break;
    }
  };
  for (var b = "", i = elements2.length; i--;) {
    if (elements2[i].checked) {
      var b = elements2[i].value;
      break;
    }
  };
  for (var c = "", i = elements3.length; i--;) {
    if (elements3[i].checked) {
      var c = elements3[i].value;
      break;
    }
  };
  for (var d = "", i = elements4.length; i--;) {
    if (elements4[i].checked) {
      var d = elements4[i].value;
      break;
    }
  };
  for (var e = "", i = elements5.length; i--;) {
    if (elements5[i].checked) {
      var e = elements5[i].value;
      break;
    }
  };
  for (var f = "", i = elements6.length; i--;) {
    if (elements6[i].checked) {
      var f = elements6[i].value;
      break;
    }
  };
  var o2 = document.getElementById("output2");
  o2.value = "[" + a + "," + b + "," + c + "," + d + "," + e + "," + f + "]";
  o2.innerHTML = o2.value;
}
<form><input type="radio" id="chair1" name="chair" class="chair" value="1">
  <input type="radio" id="chair0" name="chair" class="chair" value="0" checked>
  <input type="radio" id="chair-1" name="chair" class="chair" value="-1">
  <input type="radio" id="car1" name="car" class="car" value="1">
  <input type="radio" id="car0" name="car" class="car" value="0" checked>
  <input type="radio" id="car-1" name="car" class="car" value="-1">
  <input type="radio" id="house1" name="house" class="house" value="1">
  <input type="radio" id="house0" name="house" class="house" value="0" checked>
  <input type="radio" id="house-1" name="house" class="house" value="-1">
  <input type="radio" id="tree1" name="tree" class="tree" value="1">
  <input type="radio" id="tree0" name="tree" class="tree" value="0" checked>
  <input type="radio" id="tree-1" name="tree" class="tree" value="-1">
  <input type="radio" id="flower1" name="flower" class="flower" value="1">
  <input type="radio" id="flower0" name="flower" class="flower" value="0" checked>
  <input type="radio" id="flower-1" name="flower" class="flower" value="-1">
  <input type="radio" id="grass1" name="grass" class="grass" value="1">
  <input type="radio" id="grass0" name="grass" class="grass" value="0" checked>
  <input type="radio" id="grass-1" name="grass" class="grass" value="-1">
  <div> <input type="button" value="Search" id="filter" onclick="myFunction()" /> </div>
</form>
<div id="output2"></div>
Luca Kiebel
  • 9,790
  • 7
  • 29
  • 44
RAMHEART
  • 25
  • 5

5 Answers5

0

Use document.querySelector() to directly select the value of the checked radio button based on element names.

function myFunction() {
  var chair = document.querySelector('input[name="chair"]:checked').value;
  var car = document.querySelector('input[name="car"]:checked').value;
  var house = document.querySelector('input[name="house"]:checked').value;
  var tree = document.querySelector('input[name="tree"]:checked').value;
  var flower = document.querySelector('input[name="flower"]:checked').value;
  var grass = document.querySelector('input[name="grass"]:checked').value;

  var o2 = document.getElementById("output2");
  o2.value = "[" + chair + "," + car + "," + house + "," + tree + "," + flower + "," + grass + "]";
  o2.innerHTML = o2.value;
}
Adam
  • 3,829
  • 1
  • 21
  • 31
0

Use arrays!

function myFunction() {
    var elem_ids = [ "chair", "car", "house", "tree", "flower", "grass"];
    var elems = elem_ids.map(id => document.getElementById(id));
    var elems_check_values = elems.map(el => {
        // el is kind of an array so
        for(var i = 0; i < el.length; ++i)
            if(el[i].checked)
                return el[i].value;
        return undefined;
    }).filter(value => value == undefined) // to filter undefined values;

  var output = "[" + elems_check_values.join(",") + "]";
  var o2 = document.getElementById("output2");
  o2.innerHTML = output
}
amin
  • 3,672
  • 5
  • 33
  • 61
0

Give the form an id, and you can refer to it as an object.

function myFunction() {

    var form = document.getElementById("myForm");
    var parts = [
        form.chair.value,
        form.car.value,
        form.house.value,
        form.tree.value,
        form.flower.value,
        form.grass.value
    ];

    var o2 = document.getElementById("output2");
    o2.innerHTML = '[' + parts.join(',') + ']';
}

And this is an even simpler solution using a FormData object. It supports an arbitrary number of named form fields without having to actually name them in the function:

function myFunction() {

    var myForm = document.getElementById('myForm');
    var formData  = new FormData(myForm);
    var parts = Array.from(formData.values());

    var o2 = document.getElementById("output2");
    o2.innerHTML = '[' + parts.join(',') + ']';
}
Phil Hilton
  • 185
  • 1
  • 2
  • 8
0

Your issue can be generalized to: how can I aggregate values for all fields in a given form?
The solution is a function that can be merely as long as 5 lines, and work for any amount of inputs with any type. The DOM model for <form> elements provides named keys (eg, myform.inputName) which each have a value property. For radio buttons, eg myform.tree.value will automatically provide the value of the selected radio button.

With this knowledge, you can create a function with a simple signature that takes a form HTMLElement, and an array of field names for the values that you need, like below: (hit the search button for results, and feel free to change the radio buttons).

function getFormValues(form, fields) {
  var result = [];
  for (var i = 0; i < fields.length; i++) {
    result.push(form[fields[i]].value);
  }
  return result;
}

document.getElementById('filter').addEventListener('click', function(e) {
  var o2 = document.getElementById("output2");
  o2.innerHTML = getFormValues(document.forms[0], ['chair','car','house','tree','flower','grass']);
});
<form><input type="radio" id="chair1" name="chair" class="chair" value="1">
  <input type="radio" id="chair0" name="chair" class="chair" value="0" checked>
  <input type="radio" id="chair-1" name="chair" class="chair" value="-1">
  <input type="radio" id="car1" name="car" class="car" value="1">
  <input type="radio" id="car0" name="car" class="car" value="0" checked>
  <input type="radio" id="car-1" name="car" class="car" value="-1">
  <input type="radio" id="house1" name="house" class="house" value="1">
  <input type="radio" id="house0" name="house" class="house" value="0" checked>
  <input type="radio" id="house-1" name="house" class="house" value="-1">
  <input type="radio" id="tree1" name="tree" class="tree" value="1">
  <input type="radio" id="tree0" name="tree" class="tree" value="0" checked>
  <input type="radio" id="tree-1" name="tree" class="tree" value="-1">
  <input type="radio" id="flower1" name="flower" class="flower" value="1">
  <input type="radio" id="flower0" name="flower" class="flower" value="0" checked>
  <input type="radio" id="flower-1" name="flower" class="flower" value="-1">
  <input type="radio" id="grass1" name="grass" class="grass" value="1">
  <input type="radio" id="grass0" name="grass" class="grass" value="0" checked>
  <input type="radio" id="grass-1" name="grass" class="grass" value="-1">
  <div> <input type="button" value="Search" id="filter"/> </div>
</form>
<div id="output2"></div>
webketje
  • 10,376
  • 3
  • 25
  • 54
0

The thing you need to do is break the code up into reusable chunks. So make a method to get the value. That will reduce a lot of code. After than, you should look at a way to reduce how many elements you need to list. Finally, find an easy way to fetch all the values.

So below is code that does this. It uses a helper method to get the elements, find the value. Than it uses an array to know what element groups to look for. And finally it uses map to iterate over the list so you do not have to code multiple function calls.

function getSelected (radioBtnGroup) {
   // get the elements for the radio button group
   var elms = document.getElementsByName(radioBtnGroup)
   // loop over them
   for(var i=0; i<elms.length; i++) {
     // if checked, return value and exit loop
     if (elms[i].checked) {
       return elms[i].value
     }
   }
   // if nothing is selected, return undefined
   return undefined
}

// list the groups you want to get the values for
var groups = ['rb1', 'rb2', 'rb3', 'rb4']

// call when you want to get the values
function getValues () {
  // use map to get the values of the rabio button groups.
  // map passes the index value as the first argument.
  // code is map(function(k){return getSelected(k)})
  var results = groups.map(getSelected)
  //displat the results
  console.log(results);
}

document.querySelector('#btn').addEventListener('click', getValues);
<form>
  <fieldset>
    <legend>Item 1</legend>
    <label><input type="radio" name="rb1" value="1-1"> One</label>
    <label><input type="radio" name="rb1" value="1-2"> Two</label>
    <label><input type="radio" name="rb1" value="1-3"> Three</label>
  </fieldset>
  <fieldset>
    <legend>Item 2</legend>
    <label><input type="radio" name="rb2" value="2-1"> One</label>
    <label><input type="radio" name="rb2" value="2-2"> Two</label>
    <label><input type="radio" name="rb2" value="2-3"> Three</label>
  </fieldset>
  <fieldset>
    <legend>Item 3</legend>
    <label><input type="radio" name="rb3" value="3-1"> One</label>
    <label><input type="radio" name="rb3" value="3-2"> Two</label>
    <label><input type="radio" name="rb3" value="3-3"> Three</label>
  </fieldset>
   <fieldset>
    <legend>Item 4</legend>
    <label><input type="radio" name="rb4" value="4-1"> One</label>
    <label><input type="radio" name="rb4" value="4-2"> Two</label>
    <label><input type="radio" name="rb4" value="4-3"> Three</label>
  </fieldset>
  <button type="button" id="btn">Get Results</button>
</form>

Personally I would not store the values in an array, I would use an object with key value pairs.

 var results = groups.reduce(function (obj, name) {
   obj[name] = getSelected(name)
   return obj
 }, {});
epascarello
  • 204,599
  • 20
  • 195
  • 236