ZombieDivision
ZombieDivision

Reputation: 183

Looping change listening and counting loop in JavaScript

EDIT 20.01.2020 --- NEW PROBLEM

Problem/principle of operation:

  1. I have tables, divided into X rows and Y columns. In creating the table uses Razor syntax for ASP.NET Core.
  2. In the table I have to make a mathematical equation giving me the differences of two inputs with type = "time" (max 23:59), and quickly write this difference to the another input.

I am early calculating by:

Notes:

1.this references the html code below

  var elements_s = document.getElementsByClassName("forUser1");
  var elements_e = document.getElementsByClassName("forUser2");


 for (var i = 0; i < elements_s.length; i++) {
        elements_s[i].addEventListener("change", function (e) {
            document.getElementById("actual_1").value = diff_1();
                           // (---- few lines code later)
            document.getElementById("actual_31").value = diff_31();
        });
    }


 for (var i = 0; i < elements_e.length; i++) {
        elements_e[i].addEventListener("change", function (e) {
            document.getElementById("actual_1").value = diff_1();
                          //  (---- few lines code later)
            document.getElementById("actual_31").value = diff_31();
        });
    }

// I have these diff functions from diff_1 to diff_31

  function diff_1() {
        start = document.getElementById("start_1").value;
        end = document.getElementById("end_1").value;

        start = start.split(":");
        end = end.split(":");
        var startDate = new Date(0, 0, 0, start[0], start[1], 0);
        var endDate = new Date(0, 0, 0, end[0], end[1], 0);
        var diff = endDate.getTime() - startDate.getTime();
        var hours = Math.floor(diff / 1000 / 60 / 60);
        diff -= hours * 1000 * 60 * 60;
        var minutes = Math.floor(diff / 1000 / 60);
        return (hours < 9 ? "0" : "") + hours + ":" + (minutes < 9 ? "0" : "") + minutes;
   }

one of the answers that has improved it

  1. This code works only when the inputs are first in the table and the resulting input is next to them
  2. it doesn't work in my case

function diff (start, end) {
  start = start.split(":");
  end = end.split(":");
  const startDate = new Date(0, 0, 0, start[0], start[1], 0);
  const endDate = new Date(0, 0, 0, end[0], end[1], 0);
  let diff = endDate.getTime() - startDate.getTime();
  const hours = Math.floor(diff / 1000 / 60 / 60);
  diff -= hours * 1000 * 60 * 60;
  const minutes = Math.floor(diff / 1000 / 60);
  return (hours < 9 ? "0" : "") + hours + ":" + (minutes < 9 ? "0" : "") + minutes;
}
document.querySelector('table').addEventListener('change', function(e) {
  const classList = e.target.classList
  if (classList.contains('start') || classList.contains('end')) {
    //retrieve the associated inputs
    const tr = e.target.parentNode.parentNode
    const [start, end, actual] = [...tr.querySelectorAll('input')]
    const value = diff(start.value, end.value)
    actual.value = value
  }
})
<table>

<tr class="day"> 
  <td class="forUser0"><input type="time"></td>
  <td class="forUser0"><input type="text"></td>
  <td class="forUser1"><input type="time" class="start" id="start_1"></td>
  <td class="forUser2"><input type="time" class="end"  id="end_1"></td>
  <td class="forUser0"><input type="time"></td>
  <td class="forUser0"><input type="time"></td>
  <td class="forUser3"><input type="time" class="actual"  id="actual_1" readonly></td>
</tr>

<tr class="day">
  <td class="forUser0"><input type="time"></td>
  <td class="forUser0"><input type="text"></td>
  <td class="forUser1"><input type="time" class="start"  id="start_2"></td>
  <td class="forUser2"><input type="time" class="end" id="end_2"></td>
  <td class="forUser0"><input type="time"></td>
  <td class="forUser0"><input type="time"></td>
  <td class="forUser3"><input type="time" class="actual" id="actual_2" readonly></td>
</tr>


</table>

EDIT

Notes:

  1. I have to edit the code, I updated the html code above

  2. I gave only 2 cases, ultimately I have over 30 cases

  3. sorry for the wrong question asked before

Upvotes: 1

Views: 96

Answers (2)

grodzi
grodzi

Reputation: 5703

Assuming your original sample code is correct, that is you want to compute diff with input whose id are start_x and end_x (x being some number), notice that only those inputs have respectively class start and end.

  1. To select them in particular, you may use the css selector '.start,.end,.actual' (or eventually 'input.start,input.end,input.actual')

  2. Your diff should just take two input nodes (or even just two string, which feels better since you could then test it without having to care about the DOM)

    function diff(strA, strB){
      //guess what
      return str
    }
    
  3. Use the DOM which is already grouping your inputs:

    [...document.querySelectorAll('.start,.end')].addEventListener('change', function (e) {
      //retrieve the associated inputs
      const tr = e.target.parentNode.parentNode
      const [start, end, actual] = [...tr.querySelectorAll('input')]
    })
    
  4. Instead of binding an event to every input, delegate it to the table

    document.querySelector('table').addEventListener('change', function(e) {
      const classList = e.target.classList
      if (classList.contains('start') || classList.contains('end')){
    
        //retrieve the associated inputs
        const tr = e.target.parentNode.parentNode
        const [start, end, actual] = [...tr.querySelectorAll('input')]
      }
    })
    

Updated code with copy pasted diff which you still have to debug

function diff (start, end) {
  start = start.split(":");
  end = end.split(":");
  const startDate = new Date(0, 0, 0, start[0], start[1], 0);
  const endDate = new Date(0, 0, 0, end[0], end[1], 0);
  let diff = endDate.getTime() - startDate.getTime();
  const hours = Math.floor(diff / 1000 / 60 / 60);
  diff -= hours * 1000 * 60 * 60;
  const minutes = Math.floor(diff / 1000 / 60);
  return (hours < 9 ? "0" : "") + hours + ":" + (minutes < 9 ? "0" : "") + minutes;
}
document.querySelector('table').addEventListener('change', function(e) {
  const classList = e.target.classList
  if (classList.contains('start') || classList.contains('end')) {
    //retrieve the associated inputs
    const tr = e.target.parentNode.parentNode
    const [start, end, actual] = [...tr.querySelectorAll('.start,.end,.actual')]
    const value = diff(start.value, end.value)
    actual.value = value
  }
})
<table>

<tr class="day"> 
<td class="forUser0"><input type="time"></td>
<td class="forUser0"><input type="text"></td>
  <td class="forUser1"><input type="time" class="start" id="start_1"></td>
  <td class="forUser2"><input type="time" class="end"  id="end_1"></td>
  <td class="forUser0"><input type="time"></td>
  <td class="forUser0"><input type="time"></td>
  <td class="forUser3"><input type="time" class="actual"  id="actual_1" readonly></td>
</tr>

<tr class="day">
<td class="forUser0"><input type="time"></td>
<td class="forUser0"><input type="text"></td>
  <td class="forUser1"><input type="time" class="start"  id="start_2"></td>
  <td class="forUser2"><input type="time" class="end" id="end_2"></td>
  <td class="forUser0"><input type="time"></td>
  <td class="forUser0"><input type="time"></td>
  <td class="forUser3"><input type="time" class="actual" id="actual_2" readonly></td>
</tr>


</table>

Upvotes: 1

Tom Shaw
Tom Shaw

Reputation: 1712

Creates an an array of elements.

var elems = document.querySelectorAll(selectors);

Iterate and log each item.

for (var i = 0, total = elems.length; i < total; i++) {
  var item = elems[i];
  console.log('item', item)
}

Upvotes: 0

Related Questions