1

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

2
  • There are a lot of inputs (of type time) in every tr now... what are the input which should be taken to compute the diff? the one with class start and end? Commented Jan 20, 2020 at 8:49
  • @grodzi class="start" and class="end" to class="actual". Others I wrote to show what the code looks like Commented Jan 20, 2020 at 9:53

2 Answers 2

1

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>

Sign up to request clarification or add additional context in comments.

3 Comments

is it possible to refer to a specific table? because I'm currently reading the first table from the page
@blackZombie Normally querySelector('table') should return the first table matched. If you want to be explicit you can still enforce querySelector('table:first-child')
unfortunately I had to update the question in my case, but when the inputs are more side by side this script does not work, sorry for the problem
0

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)
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.