Добавление нового поля ввода не обновляет значения существующих - PullRequest
0 голосов
/ 12 июля 2020

Вот как это должно работать. По умолчанию есть два набора полей ввода, каждое из которых имеет значение 50%. Теперь всякий раз, когда добавляется новое поле ввода, значение процентного поля должно делиться между всеми из них, например, если есть 3 набора, тогда процентные поля должны иметь 33,33% каждое. Если 4, то по 25%. Теперь эта часть работает отлично.

Теперь я пытаюсь добавить больше функций поверх нее. Я просто кратко объясню функции и проблему, связанную с ними.

  1. Когда пользователь нажимает percentage input field, предыдущее значение исчезает, и пользователь вводит новое процентное значение и он делится между двумя полями ввода. Но проблема в том, что он добавляет два знака "%" в конце значения, которое только что ввел пользователь.

  2. Вторая проблема заключается в том, что предположим, что пользователь вводит новый процентное значение в первом или втором percentage field, а затем добавляет новую кнопку от input field до Add Field, проценты не делятся между всеми входными значениями. Новый input field не принимает во внимание новый percentage value. Одна из причин, о которой я мог подумать, - это то, что переменная percInput каким-то образом не обновляется.

  3. Третья проблема похожа на вторую. Если пользователь сначала добавляет новый input field, а затем набирает percentage value в этом новом input field, то процентные значения не делятся вообще. Это также может быть из-за того, что переменная percInput не обновляется. Другая проблема, связанная с этим, заключается в том, что нажатие на новое поле ввода процентов не удаляет предыдущее значение, как это происходит в полях по умолчанию.

  4. Это странное значение. Если пользователь нажимает на поле ввода процентов, но не добавляет значение и переходит к добавлению нового поля, тогда процентные значения просто делятся между всеми из них.

Все эти проблемы в некоторой степени связаны друг с другом, и я чувствую, что все они связаны с одной переменной, а именно percInput. Я думаю, он не обновляется при добавлении новых полей ввода. Раньше я использовал функцию calculatePercentage для обновления переменной percInput, где она работала. Но это не сработало, когда я попытался использовать его в описанных выше ситуациях.

Вот код, который я пробовал до сих пор:

const form = document.querySelector("form");
const span = document.querySelector("span");
const addBtn = document.querySelector("#addField");
const html = `
    <div class="url-pair">
        <input type="url" placeholder="3">
        <input type="text" class="perc">
        <button class="delete-btn" type="button">Delete</button>
    </div>
`;

// percentage variable and percentage calculation for the first time
let percInput = document.querySelectorAll('.urls-container .perc');
let percentage = (100 / percInput.length).toFixed(0).toString() + "%";

percInput.forEach((item) => {
    item.setAttribute("value", percentage);
});

const removeField = (e) => {
    if (!e.target.classList.contains('delete-btn')) return;
    e.target.parentElement.remove();
    calculatePercentage(); 
}

// percentage input variable update and percentage calculation
const calculatePercentage = () => {
    percInput = document.querySelectorAll('.urls-container .perc');
    percentage = (100 / percInput.length).toFixed(0).toString() + "%";

    percInput.forEach((item) => {
        item.setAttribute("value", percentage);
    });
}

// remove a field
form.addEventListener('click', removeField);

// add input field
addBtn.addEventListener('click', () => {
    span.insertAdjacentHTML("beforeBegin", html);
    calculatePercentage(); 
});


const percInputChange = function() {
    let val = this.value,
    $allInputs = $(percInput);

    if(val > 100) {
        $allInputs.val((100 / $allInputs.length) + "%");
        calculatePercentage();
    }else {
        $(percInput).not(this).val( (100 - val) / ($allInputs.length - 1) + "%");

        setTimeout(() => {
            this.value = this.value + "%";
        }, 500);

        calculatePercentage();

        return;
    }
};

// event listener when user types in a new percentage value
$( percInput ).on('keyup', percInputChange);

// event listener to hide previous input value
$( percInput ).focus(function() {
    this.value = "";
});

// event listener to divide the percetange values when the user clicks away
$( percInput ).blur(function() {
    if(this.value === ""){
        percInput.forEach(item => {
            item.value = ( 100 / percInput.length ).toFixed(0).toString() + "%";
            return;
        });
    }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<form action="#" method="POST">

  <div class="urls-container">
    <div class="url-pair">
      <input type="url" placeholder="1">
      <input type="text" class="perc">
      <button class="delete-btn" type="button">Delete</button>
    </div>

    <div class="url-pair">
      <input type="url" placeholder="2">
      <input type="text" class="perc">
      <button class="delete-btn" type="button">Delete</button>
    </div>

    <span></span>
  </div>

  <div>
    <div>
      <button type="button" id="addField">Add Field</button>
    </div>

    <div>
      <button type="submit">Create</button>
    </div>
  </div>

</form>

Я знаю, что этот пост странный, с таким большим количеством проблем. Но, пожалуйста, терпите меня, так как я все еще учусь, и я не смогу учиться, если я sh не столкнусь с этими сложными проблемами кодирования и застряну. Вчера я провел целый день, пробуя разные методы, исходя из имеющихся у меня знаний. Пост был бы действительно большим, если бы я применил все методы, которые пробовал. Так что терпите меня. Пожалуйста, помогите другому программисту, который в этом нуждается. Спасибо

PS. Я использовал jQuery и JS вместе, что было бы неправильно. Но я проведу рефакторинг и изменю их, как только исправлю проблемы. PS.

1 Ответ

1 голос
/ 12 июля 2020

Я не совсем уверен, чего именно вы хотите достичь с помощью своего скрипта. Но у меня был go при запуске fre sh путем удаления лишних битов. Следующий фрагмент позволит вам добавлять или удалять строки ввода и соответственно корректировать проценты.

Может быть, вы можете указать как вы хотите, чтобы сценарий реагировал на любой ввод пользователя?

// add flields:
function addfields(){
   let all=$('.urls-container'), r=$('div:last',all).clone(),
       url=r.find('input[type=url]')[0];
   url.placeholder=+url.placeholder+1;
   $('.perc',r).removeAttr('data-manual');
   all.append(r); calcperc();
 }
// even distribution:
function calcperc(){
  let fix=$('.perc[data-manual]'),sum=0;
  fix.each(function(){sum+=parseFloat(this.value)});
  let rest= $('.perc').not(fix);
  rest.val(((100-sum)/rest.length).toFixed(2)+'%')
}

// manual distribution:
function recalc(){let inps=$('.perc'),cur=parseFloat(this.value);
 if (inps.length>1){
  this.value=cur.toFixed(2)+'%'; this.dataset.manual=1;
  calcperc();
} else this.value="100%"
}
// delegated event management:
$('form')
 .on('submit',function(e){e.preventDefault()}) // de-activate submit for testing
 .on('change','.perc',recalc)
 .on('click','.delete-btn',function(){$(this).parent().remove();calcperc()})
 .on('click','#addField',addfields);
 
 // initial distribution:
 calcperc();
<script type="text/javascript" src="https://code.jquery.com/jquery-3.5.1.min.js"></script>

<form action="#" method="POST">

  <div class="urls-container">
    <div class="url-pair">
      <input type="url" placeholder="1">
      <input type="text" class="perc">
      <button class="delete-btn" type="button">Delete</button>
    </div>

    <div class="url-pair">
      <input type="url" placeholder="2">
      <input type="text" class="perc">
      <button class="delete-btn" type="button">Delete</button>
    </div>

    <span></span>
  </div>

  <div>
    <div>
      <button type="button" id="addField">Add Field</button>
    </div>

    <div>
      <button type="submit">Create</button>
    </div>
  </div>

</form>

Моя текущая версия recalc() позволяет вам перезаписывать одно процентных значений. Затем все остальные значения будут скорректированы, так что общая сумма снова составит 100%.

Обратите внимание, что в моей версии recalc() запускается в событии input, а не в событии keyup, иначе добавление знака процента серьезно помешает любой попытке ввода пользователем.

Изменить Последнее редактирование включает в себя «пометку» вручную измененных процентов с помощью атрибута data-manual в поле ввода. Это защитит это поле от будущих перерасчетов. Оставшиеся проценты будут равномерно распределены между нефиксированными полями.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...