автоматы c суммирование значений / зацикливание кода - PullRequest
0 голосов
/ 20 января 2020

Описание ситуации:

У меня есть входы времени, описанные в class = "start", и входы времени, описанные в class = "end". Разница рассчитывается на основе уравнения «конец-начало = факт»; «фактические» - входные данные времени. Фактические входы должны складываться и записываться на вход с id = "sum_actual" (type = text)

Проблема:

  1. У меня есть два проблемы в этом вопросе:

    a) Я не знаю, как l oop код, который суммирует отдельные входные данные: класс = фактический, в конечном счете их более 30

    b) код написано так, что мне нужно вручную ввести время в классе ввода = фактическое, чтобы оно обновлялось до всей суммы, когда результат вычисляется автоматически, он не складывается

Примечания:

  1. в конечном счете, класс = фактические входные данные будут доступны только для чтения

  2. в конечном итоге есть несколько других столбцов с входами (неважно) между началом и концом и фактическими входами (косметика, я обращаю внимание на способ написания кода)

Мой код / ​​я пробовал этот код выше в javascript должен быть улучшен

  
  
  
//code that sums values ​​from the actual class / should loop it
  function msToTime(duration) {
        var minutes = Math.floor((duration / (1000 * 60)) % 60),
            hours = Math.floor(duration / (1000 * 60 * 60));

        hours = hours < 10 ? "0" + hours : hours;
        minutes = minutes < 10 ? "0" + minutes : minutes;
        

        return hours + ":" + minutes;
      }
      console.log(msToTime(300000));
      function sum_diff() {
        zxc = document.getElementById("actual_1").value;
        xcz = document.getElementById("actual_2").value;
        czx = document.getElementById("actual_3").value;

        zxc = zxc.split(":");
        xcz = xcz.split(":");
        czx = czx.split(":");

        var zxcDate = new Date(0, 0, 0, zxc[0], zxc[1], 0);
        var xczDate = new Date(0, 0, 0, xcz[0], xcz[1], 0);
        var czxDate = new Date(0, 0, 0, czx[0], czx[1], 0);

        var zxcMs =
          zxcDate.getHours() * 60 * 60 * 1000 +
          zxcDate.getMinutes() * 60 * 1000;
        var xczMs =
          xczDate.getHours() * 60 * 60 * 1000 +
          xczDate.getMinutes() * 60 * 1000;
        var czxMs =
          czxDate.getHours() * 60 * 60 * 1000 +
          czxDate.getMinutes() * 60 * 1000;

        var ms = zxcMs + xczMs + czxMs;

        return msToTime(ms);
      }

      var elements = document.getElementsByClassName("actual");
      for (var i = 0; i < elements.length; i++) {
        elements[i].addEventListener("change", function(e) {
          document.getElementById("sum_actual").value = sum_diff();
        });
      }
      
      
      // code calculating differences start from end and writing to actual / do not touch it
          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>
<tbody>
<tr>
<td><input class="start" type="time"/></td>
<td><input class="end" type="time"/></td>
<td><input class="actual" type="time" id="actual_1" value="00:00" /></td>
</tr>
<tr><td><input class="actual" type="time" id="actual_2" value="00:00" /></td></tr>
<tr><td><input class="actual" type="time" id="actual_3" value="00:00" /></td></tr>
</tbody>
<tfoot>
<tr><th><input type="text" id="sum_actual" readonly /></th></tr>
</tfoot>    
</table>

Примечание: спасибо, оказалось, что у меня проблема со скриптом подсчета, и он считает только 99:59, может вы меняете этот лимит? показывать часы до 300: 00?

Ответы [ 2 ]

1 голос
/ 21 января 2020

Когда я сталкиваюсь с подобным типом ситуаций, мне нравится разбивать мою большую проблему на очень маленькие проблемы и создавать действительно маленькие функции, которые выполняют одно, но делают это хорошо:

const actuals = [...document.getElementsByClassName("actual")];

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;
    updateActualSum();
  }
});

// Update total duration once on load
updateActualSum();

function msToTime(duration) {
  const minutes = Math.floor((duration / (1000 * 60)) % 60),
        hours = Math.floor(duration / (1000 * 60 * 60));
  return twoOrMoreDigits(hours) + ":" + twoOrMoreDigits(minutes);
}

function twoOrMoreDigits(n) {
  return n < 10 ? '0' + n : n;
}

function timeToMs(time) {
  if (time) { // may be "" if the value is not set
    const [hours, minutes] = time.split(":").map(str => parseInt(str, 10));
    return (hours * 60 + minutes) * 60 * 1000;
  }
  return 0;
}

function sum_diff() {
  const sum = actuals.reduce((acc, el) => acc + timeToMs(el.value), 0);
  return msToTime(sum);
}

function diff(start, end) {
  return msToTime(timeToMs(end) - timeToMs(start));
}

function updateActualSum() {
  document.getElementById('sum_actual').value = sum_diff();
}
body {font-family: Arial, Helvetica, sans-serif; } table { border-collapse: collapse; } td, th { border: 1px solid #ddd; padding: .2rem; } input[readonly] { background: #f5f5f5; border: none; font-family: inherit; text-align: center; padding: .2rem; }
<table>
  <tbody>
    <thead>
      <tr>
        <th>Start</th>
        <th>End</th>
        <th>Duration</th>
      </tr>
    </thead>
    <tr>
      <td><input class="start" type="time" /></td>
      <td><input class="end" type="time" /></td>
      <td><input class="actual" type="time" id="actual_1" value="00:00" readonly /></td>
    </tr>
    <tr>
      <td><input class="start" type="time" /></td>
      <td><input class="end" type="time" /></td>
      <td><input class="actual" type="time" id="actual_2" value="00:00" readonly /></td>
    </tr>
    <tr>
      <td><input class="start" type="time" /></td>
      <td><input class="end" type="time" /></td>
      <td><input class="actual" type="time" id="actual_2" value="00:00" readonly /></td>
    </tr>
    <tr>
      <td><input class="start" type="time" /></td>
      <td><input class="end" type="time" /></td>
      <td><input class="actual" type="time" id="actual_2" value="00:00" readonly /></td>
    </tr>
    <tr>
      <td><input class="start" type="time" /></td>
      <td><input class="end" type="time" /></td>
      <td><input class="actual" type="time" id="actual_3" value="00:00" readonly /></td>
    </tr>
  </tbody>
  <tfoot>
    <tr>
      <th colspan="3"><input type="text" id="sum_actual" readonly /></th>
    </tr>
  </tfoot>
</table>
0 голосов
/ 21 января 2020

Получить все actual значения в массиве, а затем, используя момент, вычислить сумму продолжительности

//const durations = document.getElementsByClassName('actual').map(input => input.value);

// And let say, we got following durations

const durations = ['01:30', '05:00', '10:20'];

const totalDuration = durations.slice(1)
 .reduce((prev, cur) => moment.duration(cur).add(prev),
  moment.duration(durations[0]));
  
const requiredOutput = `${totalDuration.asHours().toFixed(0)}:${totalDuration.minutes().toString().padStart(2, '0')}`;
console.log(requiredOutput)
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.24.0/moment.min.js"></script>
...