Сохранить / отменить выбор ввода для всех типов ввода - PullRequest
0 голосов
/ 29 октября 2019

Я пытаюсь воссоздать save / discard изменения UX не только для текста, но и для button выборов, а также radio и checkbox выборов.

Я понимаю, как сохранить data-input val(); для текста, но как применить ту же логику к входам радио и флажков, а также к кнопкам, которым присвоен активный класс (в данном случае addClass("focus")).

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

// Restricts input for each element in the set of matched elements to the given inputFilter.
(function($) {
  $.fn.inputFilter = function(inputFilter) {
    return this.on(
      "input keydown keyup mousedown mouseup select contextmenu drop",
      function() {
        if (inputFilter(this.value)) {
          this.oldValue = this.value;
          this.oldSelectionStart = this.selectionStart;
          this.oldSelectionEnd = this.selectionEnd;
        } else if (this.hasOwnProperty("oldValue")) {
          this.value = this.oldValue;
          this.setSelectionRange(this.oldSelectionStart, this.oldSelectionEnd);
        }
      }
    );
  };
})(jQuery);

$(".input--item").inputFilter(function(value) {
  return /^\d*$/.test(value);
});
$(".post__item").on("click", ".btn--cancel", function() {
  var parentItemDiv = $(this).closest(".post__item");
  var editBtnObj = parentItemDiv.find('[name="toggle"]');
  var idInput = $(editBtnObj).data("input");
  // clearing unsaved inputs
  parentItemDiv.find("." + idInput).each(function() {
    var oldInputValue = "";
    if (
      $(this).data("old_value") != null &&
      $(this).data("old_value") != ""
    ) {
      oldInputValue = $(this).data("old_value");
    }
    $(this).val(oldInputValue);
  });
  // unchecking edit button & triggering it's on change event which takes further actions like: (a) adding hidden state to "cancel" button etc.
  editBtnObj.prop("checked", false).trigger("change");
});
$(".edit :input").attr("disabled", true);
$('[name="toggle"]').on("change", function() {
  var cancel = $(this)
    .closest(".post__item")
    .find(".btn--cancel")
    .toggleClass("hidden");
  var edit = $(this)
    .closest(".post__item")
    .find(".btn--edit");
  var item = $(this).closest(".post__item");
  var icon = $(this).next("svg");
  var idInput = $(this).data("input");
  var inputEle = $("." + idInput);
  var toggleInput = $(this);
  inputEle.each(function() {
    var inputEleValue = "";
    if ($(this).val() != null && $(this).val() != "") {
      inputEleValue = $(this).val();
    }
    $(this).data("old_value", inputEleValue);
    if (toggleInput.is(":checked")) {
      inputEle.addClass("active");
      cancel.removeClass("hidden");
      edit.addClass("active");
      icon.addClass("fa-save").removeClass("fa-pencil");
      $(this).attr("disabled", false);
    } else {
      inputEle.removeClass("active");
      cancel.addClass("hidden");
      edit.removeClass("active");
      icon.addClass("fa-pencil").removeClass("fa-save");
      $(this).attr("disabled", true);
    }
  });
});
$(".button").on("click", function() {
  $(this).toggleClass("focus");
});
.post__item {
  display: flex;
  flex-direction: column;
}

.wrap {
  border: 2px solid #eee;
  display: flex;
  flex-direction: row;
  align-items: start
}

.btn__wrap {
  display: flex;
}

.btn {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 60px;
  width: 60px;
  margin: 12px;
  color: white;
}

.btn--edit {
  background: orange;
}

.btn--edit.active {
  background: #58d25e;
}

.btn--edit input[type="checkbox"] {
  display: none;
}

.btn--cancel {
  background: red;
}

.hidden {
  display: none;
}

.edit {
  display: flex;
  width: 90px;
}

.edit input {
  border: none;
  padding: 0.6rem;
  margin: 1rem;
  color: red;
}

.edit input.active {
  border: 3px solid #eee;
}

.input--item,
.input--span {
  font: inherit;
  margin: 0;
  padding: 0;
}

.input--item {
  border: none;
  min-width: 10px;
}

.input--span {
  display: none;
  white-space: pre;
}

.button.focus {
  background: green
}
<script src="https://pro.fontawesome.com/releases/v5.8.1/js/all.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="post__item">
  <div class="btn__wrap">
    <label class="btn btn--edit" for="edit">
  <input id="edit" data-input="update" type="checkbox" name="toggle"/>
    <i class="fa fa-pencil"></i>
  </label>
    <a class="btn btn--cancel hidden" href="#">
      <i class="fas fa-times"></i>
    </a>
  </div>
  <div class="wrap">
    Cost:
    <div class="edit">
      <span class="input--span"></span>
      <input class="update input--item qty" type="text" name="name" autocomplete="off" value="312" />
    </div>
    Price:
    <div class="edit">
      <span class="input--span"></span>
      <input class="update input--item cost" type="text" name="name" autocomplete="off" value="55" />
    </div>
    <div class="subwrap">
      Option:
      <div class="edit">
        <input class="update input--item option" type="radio" name="radio" />
        <input class="update input--item option" type="radio" name="radio" />
        <input class="update input--item option" type="radio" name="radio" checked/>
      </div>
      Button:
      <div class="edit">
        <button class="update button" />Button 1</button>
        <button class="update button focus" />Button 2</button>
        <button class="update button" />Button 3</button>
      </div>
      </div>
      </div>
      <div class="post__item">
        <div class="btn__wrap">
          <label class="btn btn--edit" for="edit1">
  <input id="edit1" data-input="update1" type="checkbox" name="toggle"/>
    <i class="fa fa-pencil"></i>
  </label>
          <a class="btn btn--cancel hidden" href="#">
            <i class="fas fa-times"></i>
          </a>
        </div>
        <div class="wrap">
          Cost:
          <div class="edit">
            <span class="input--span"></span>
            <input class="update1 input--item qty" type="text" name="name" autocomplete="off" value="40" maxlength="3" />
          </div>
          Price:
          <div class="edit">
            <span class="input--span"></span>
            <input class="update1 input--item cost" type="text" name="name" autocomplete="off" value="79" maxlength="4" />
          </div>
          Option:
          <div class="edit">
            <input class="update1 input--item option" type="checkbox" name="radio1" />
            <input class="update1 input--item option" type="checkbox" name="radio1" checked/>
            <input class="update1 input--item option" type="checkbox" name="radio1" checked/>
          </div>
        </div>
      </div>

1 Ответ

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

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

См. Этот код:

function changeInput(inputElements, update = true) {
  // first get all input values and add to data
  inputElements.each(function(i, el) {
    const inputEl = jQuery(el);
    const type = jQuery(el).attr('type');
    const currentValue = inputEl.data("data-value");
    let newValue = '';

    switch (type) {
      case "radio":
      case "checkbox":
        newValue = update ? inputEl.is(":checked") : currentValue;

        if (!update)
          inputEl.prop('checked', newValue);
        break;
      case "text":
        newValue = update ? inputEl.val() : currentValue;

        if (!update)
          inputEl.val(newValue);
        break;
      default:
        // Assuming its button element
        newValue = update ? inputEl.hasClass("focus") : currentValue;

        if (!update)
          // Restore btn focus status if cancelled
          inputEl.toggleClass("focus", newValue);
        break;
    }

    inputEl.data("data-value", newValue);
  });
}

$(".post__item").each(function(i, e) {
  let _this = jQuery(e);
  let parent = _this;
  let inputElements = _this.find(':input');
  let editBtn = _this.find('.btn--edit');
  let saveBtn = _this.find('.btn--save');
  let cancelBtn = _this.find('.btn--cancel');
	
	// disable on load
	inputElements.prop("disabled", true);
	
	// save current data
  changeInput(inputElements);

  // Add click to btns
  editBtn.on("click", function() {
    _this.attr("data-mode", 'edit');

    inputElements.prop("disabled", false).addClass("active");
  });

  saveBtn.on("click", function() {
    _this.attr("data-mode", 'none');

    changeInput(inputElements);
    inputElements.prop("disabled", true).removeClass("active");
  });

  cancelBtn.on("click", function() {
    _this.attr("data-mode", 'none');

    changeInput(inputElements, false);
    inputElements.prop("disabled", true).removeClass("active");
  });
});


$(".button").on("click", function() {
  $(this).toggleClass("focus");
});
.post__item {
    display: flex;
    flex-direction: column;
}

.post__item[data-mode='none'] .btn--cancel,
.post__item[data-mode='none'] .btn--save {
    display: none;
}

.post__item[data-mode='edit'] .btn--cancel,
.post__item[data-mode='edit'] .btn--save {
    display: flex;
}

.post__item[data-mode='edit'] .btn--edit {
    display: none;
}

.post__item .wrap {
    border: 2px solid #eee;
    display: flex;
    flex-direction: row;
    align-items: start;
}

.post__item .btn__wrap {
    display: flex;
}

.post__item .btn__wrap .btn--edit {
    background: orange;
}

.post__item .btn__wrap .btn--save {
    background: #58d25e;
}

.post__item .btn__wrap .btn--cancel {
    background: red;
}

.post__item .btn {
    display: flex;
    align-items: center;
    justify-content: center;
    height: 60px;
    width: 60px;
    margin: 12px;
    color: white;
}

.hidden {
    display: none;
}

.edit {
    display: flex;
    width: 90px;
}

.edit input {
    border: none;
    padding: 0.6rem;
    margin: 1rem;
    color: red;
}

.edit input.active {
    border: 3px solid #eee;
}

.input--item,
.input--span {
    font: inherit;
    margin: 0;
    padding: 0;
}

.input--item {
    border: none;
    min-width: 10px;
}

.input--span {
    display: none;
    white-space: pre;
}

.button.focus {
    background: green;
}
<script src="https://pro.fontawesome.com/releases/v5.8.1/js/all.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="post__item" data-mode='none'>
  <div class="btn__wrap">
    <a class="btn btn--save " href="#">
      <i class="fa fa-save"></i>
    </a>
    <a class="btn btn--edit " href="#">
      <i class="fa fa-pencil"></i>
    </a>
    <a class="btn btn--cancel" href="#">
      <i class="fas fa-times"></i>
    </a>
  </div>
  <div class="wrap">
    Cost:
    <div class="edit">
      <span class="input--span"></span>
      <input class="input--item qty" type="text" name="name" autocomplete="off" value="312" />
    </div>
    Price:
    <div class="edit">
      <span class="input--span"></span>
      <input class="input--item cost" type="text" name="name" autocomplete="off" value="55" />
    </div>
    <div class="subwrap">
      Option:
      <div class="edit">
        <input class="input--item option" type="radio" name="radio" />
        <input class="input--item option" type="radio" name="radio" />
        <input class="input--item option" type="radio" name="radio" checked />
      </div>
      Button:
      <div class="edit">
        <button class="button">Button 1</button>
        <button class="button focus">Button 2</button>
        <button class="button">Button 3</button>
      </div>
    </div>
  </div>
</div>
<div class="post__item" data-mode='none'>
  <div class="btn__wrap">
    <a class="btn btn--save " href="#">
      <i class="fa fa-save"></i>
    </a>
    <a class="btn btn--edit " href="#">
      <i class="fa fa-pencil"></i>
    </a>
    <a class="btn btn--cancel" href="#">
      <i class="fas fa-times"></i>
    </a>
  </div>
  <div class="wrap">
    Cost:
    <div class="edit">
      <span class="input--span"></span>
      <input class="input--item qty" type="text" name="name" autocomplete="off" value="40" maxlength="3" />
    </div>
    Price:
    <div class="edit">
      <span class="input--span"></span>
      <input class="input--item cost" type="text" name="name" autocomplete="off" value="79" maxlength="4" />
    </div>
    Option:
    <div class="edit">
      <input class="input--item option" type="checkbox" name="radio1" />
      <input class="input--item option" type="checkbox" name="radio1" checked />
      <input class="input--item option" type="checkbox" name="radio1" checked />
    </div>
  </div>
</div>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...