Сделать так, чтобы значения группы входов не превышали указанное значение - PullRequest
1 голос
/ 02 ноября 2019

Я создаю игру и использую JavaScript / jQuery, чтобы тратить очки атрибутов персонажа. У меня есть шесть входов, подобных этому, каждый из которых представляет один атрибут:

<input class="attributeVal" type="number" min="1" max="36" step="1" value="1">

И один вход, подобный этому («пул»):

<input id="pool" type="number" min="0" max="36" step="1" value="36" readonly>

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

  • Изменение любого из входных данных «attributeVal» вычитает или восстанавливает точки в пуле, которые не могут быть больше 36 и меньше 0.
  • Каждый вход «attributeVal» не может быть меньше 1 и больше 36.
  • «attributeVal» и «pool» не могут быть отрицательными.

Я пробовал разные подходы, ноне мог помешать игроку превысить значения, превышающие максимум пула, в основном потому, что я не знаю, как предотвратить событие изменения.

Это то, что я пробовал до сих пор:

<script>
    let attributeVal = $(".attributeVal");

    attributeVal.on("change paste keyup", function (e) {
        let prev = $(this).data('val');
        let maxPointsOverall = 42;
        let spentPoints = 0;
        let poolInput = $('#poolInput');

        $(".attributeVal").each(function () {
            spentPoints += +$(this).val();
        });

        if ((maxPointsOverall - spentPoints) < 0) {
            $(this).val(prev);
            poolInput.val(0);
        } else {
            poolInput.val(42 - spentPoints);
        }
    });

    attributeVal.on("cut copy paste", function (e) {
        e.preventDefault();
    });
</script>

Не могли бы вы дать мне какие-нибудь советы, как я могу заставить это работать?

let attributeVal = $(".attributeVal");

attributeVal.on("change paste keyup", function(e) {
  let prev = $(this).data('val');
  let maxPointsOverall = 42;
  let spentPoints = 0;
  let poolInput = $('#poolInput');

  $(".attributeVal").each(function() {
    spentPoints += +$(this).val();
  });

  if ((maxPointsOverall - spentPoints) < 0) {
    $(this).val(prev);
    poolInput.val(0);
  } else {
    poolInput.val(42 - spentPoints);
  }
});

attributeVal.on("cut copy paste", function(e) {
  e.preventDefault();
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<label class="font-weight-bold unselectable mb-3">Points available
  <input id="poolInput" type="number" min="0" max="36" step="1" value="36" readonly>
</label>

<div class="form-group">
  <label>Strength
    <input class="attributeVal" type="number" min="1" max="36" step="1" value="1">
  </label>
</div>
<div class="form-group">
  <label>Endurance
    <input class="attributeVal" type="number" min="1" max="36" step="1" value="1">
  </label>
</div>
<div class="form-group">
  <label>Dexterity
    <input class="attributeVal" type="number" min="1" max="36" step="1" value="1">
  </label>
</div>
<div class="form-group">
  <label>Perception
    <input class="attributeVal" type="number" min="1" max="36" step="1" value="1">
  </label>
</div>
<div class="form-group">
  <label>Intelligence
    <input class="attributeVal" type="number" min="1" max="36" step="1" value="1">
  </label>
</div>
<div class="form-group">
  <label>Charisma
    <input class="attributeVal" type="number" min="1" max="36" step="1" value="1">
  </label>
</div>

Вот JSFiddle, чтобы проиллюстрировать проблему

1 Ответ

1 голос
/ 02 ноября 2019

Проблема заключается в том, что после того, как событие ввода было запущено, вы не можете сбросить его на предыдущее число без сохранения состояния каждого входа где-то, что немного грязно. Вы можете сначала проверить значение:

  • Убедитесь, что это целое число от 0 до 36
  • Подсчитайте количество баллов, потраченных на другие атрибуты. Убедитесь, что текущее значение, при добавлении к нему, не превышает maxPointsOverall. (Если он переполнен, уменьшите текущее значение до такой точки, чтобы pointsSpentOnOtherAttribs + newVal === maxPointsOverall)

Затем установите текущее значение на проверенный newVal и вычислите / заполните значение для #poolInput.

Чтобы обеспечить немедленную фиксацию входов, а не на короткую задержку, добавьте прослушиватель input (который будет срабатывать при нажатии клавиш, а не при нажатии):

const attributeVal = $(".attributeVal");

attributeVal.on("change paste keyup input", function(e) {
  let newVal = Math.floor($(this).val());
  newVal = Math.max(1, newVal);
  newVal = Math.min(36, newVal);
  const maxPointsOverall = 42;
  let pointsSpentOnOtherAttribs = 0;
  $(".attributeVal").not(this).each(function() {
    pointsSpentOnOtherAttribs += +$(this).val();
  });
  if (newVal + pointsSpentOnOtherAttribs > maxPointsOverall) {
    // Invalid, reset these points to the maximum allowable:
    newVal = maxPointsOverall - pointsSpentOnOtherAttribs;
  }
  // New value has been validated, put it into the DOM:
  $(this).val(newVal);
  const pointsLeft = maxPointsOverall - (pointsSpentOnOtherAttribs + newVal);
  $('#poolInput').val(pointsLeft);
});

attributeVal.on("cut copy paste", function(e) {
  e.preventDefault();
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<label class="font-weight-bold unselectable mb-3">Points available
  <input id="poolInput" type="number" min="0" max="36" step="1" value="36" readonly>
</label>

<div class="form-group">
  <label>Strength
    <input class="attributeVal" type="number" min="1" max="36" step="1" value="1">
  </label>
</div>
<div class="form-group">
  <label>Endurance
    <input class="attributeVal" type="number" min="1" max="36" step="1" value="1">
  </label>
</div>
<div class="form-group">
  <label>Dexterity
    <input class="attributeVal" type="number" min="1" max="36" step="1" value="1">
  </label>
</div>
<div class="form-group">
  <label>Perception
    <input class="attributeVal" type="number" min="1" max="36" step="1" value="1">
  </label>
</div>
<div class="form-group">
  <label>Intelligence
    <input class="attributeVal" type="number" min="1" max="36" step="1" value="1">
  </label>
</div>
<div class="form-group">
  <label>Charisma
    <input class="attributeVal" type="number" min="1" max="36" step="1" value="1">
  </label>
</div>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...