Search code examples
javascripthtmljquerycss

Add additional field issue


I'm working on this page where I have some custom JS/jQuery to add a search feature for a list. I need to be able to "add" a field if required. I had it working before implementing the search feature, but now it's become a lot more convoluted. I think I need to use a "closest" or an "each" somewhere in here

$(function() {
  let count = 1;
  $("#addMore").click(function(e) {
    count++;
    var newChargeGroup = $("#chargeGroup1").clone().attr({
      id: "chargeGroup" + parseInt(count),
      name: "charge" + parseInt(count)
    });
    newChargeGroup.val("");
    $("#chargeGroups").append(newChargeGroup);
  });

  document.getElementById("addMore").addEventListener("click", function(event) {
    event.preventDefault()
  });

  $(document).ready(function() {
    $('#dropdownDisplay').on('click', function() {
      $('#dropdownContent').toggle();
    });

    $('#chargeSearch' + parseInt(count)).on('input', function() {
      let value = $(this).val().toLowerCase();
      $('#charge li').filter(function() {
        $(this).toggle($(this).text().toLowerCase().indexOf(value) > -1);
      });
    });

    /* $('.charge').on('click', 'li', function (e) {
        //$(e.target).closest('span').text($(this).text());
        $('#dropdownDisplay > span').text($(this).text());
        $('#hiddenCharge').val($(this).text());
        $('#dropdownContent').hide();
      });*/
    $('.charge').on('click', 'li', function(e) {
      //$(e.target).closest('span').text($(this).text());
      $('#dropdownDisplay > span').text($(this).text());
      $('#hiddenCharge').val($(this).text());
      $('#dropdownContent').hide();
    });

    $(document).on('click', function(e) {
      if (!$(e.target).closest('.search-dropdown').length) {
        $('#dropdownContent').hide();
      } else {
        $("#chargeSearch1").focus();
      }

    });
  });

  // populate charges
  const chargeSelect = document.getElementById("charge");
  for (let state in myCharges) {
    let opt = document.createElement('li');
    opt.innerHTML = state;
    chargeSelect.appendChild(opt);
  }


});



const myCharges = {
  "this charge": "",
  "second charge": "",
  "third charge": "",
};
form .group {
  display: table;
  width: 100%;
}

form p.group label,
form div.group label {
  display: table-cell;
  width: 20%;
}

form p.group input,
form p.group select {
  /* display: table-cell; */
  width: 100%;
}

.terms-section {
  width: 100%;
  max-width: 400px;
  margin: 0 auto 1em;
}

#selectCharges>select {}

#addMore {
  margin: auto auto 1em;
  display: table-cell;
  text-align: center;
}

#termsCheck {
  cursor: pointer;
}

#scrollable {
  border: solid 1px;
  height: 100px;
  margin: 1em auto;
  padding: 10px;
  overflow-y: scroll;
}

.close {
  position: absolute;
  color: #fff;
  top: 0;
  right: 0;
  padding: 2px 10px;
  margin: 5px;
  background: rgba(0, 0, 0, 0.5);
  border-radius: 50px;
  cursor: pointer;
}

#popup {
  display: none;
  font-size: 1em;
  position: absolute;
  top: 0;
  width: 80%;
  max-width: 400px;
  height: 20em;
  padding: 20px;
  margin: auto;
  border: 1px solid;
  background: #eee;
  overflow-y: scroll;
  z-index: 101;
}

#mask {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background-color: #000;
  display: none;
  z-index: 100;
}

.search-dropdown {
  margin-bottom: 1em;
}

.dropdown-display {
  /* width: 75%; */
  /* display: table-cell; */
  padding: 0 6px 1px;
  border: 1px solid #bbb;
  cursor: pointer;
}

.dropdown-content {
  display: none;
}

.dropdown-content .search-input {
  display: table-cell;
  width: 100%;
  margin: 1em 5% 0 0;
}

.dropdown-content ul {
  list-style-type: none;
  padding: 0;
  margin: 0;
  display: inline-block;
  padding-top: 1em;
  width: 100%;
}

.dropdown-content ul li {
  padding: 0 10px;
  cursor: pointer;
  border: 1px solid #bbb;
  /* display: table-header-group; */
}

.dropdown-content ul li:not(:first-child) {
  border-top: 0;
}

.dropdown-content ul li:hover {
  background-color: #f1f1f1;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
<form action="google.com" method="get" target="_parent" name="inmateInfo" id="inmateInfo">
  <div id="chargeGroups">
    <label>Charges: </label>
    <div class="search-dropdown group" id="chargeGroup1" name="charge1">
      <div class="dropdown-display" id="dropdownDisplay">
        <span>Select Charge</span>
        <input name="chargehide" type="hidden" id="hiddenCharge">
      </div>
      <div class="dropdown-content" id="dropdownContent">
        <input type="text" placeholder="Search..." id="chargeSearch1" class="search-input">
        <ul id="charge" name="charge">

        </ul>
      </div>
    </div>
  </div>

  <button id="addMore">Add Charge</button>

</form>

Edit: What I'm looking to do, is have the "Add Additional Charge" button replicate upon click. In it, the ID for the dropdown/input field will be consistent. Currently, after selecting a charge, that text will be placed in a hidden input field. I need to have multiple charge fields available to send data.


Solution

  • Since you are cloning things and then trying to use event handlers on the cloned element too, you can not do that directly. Use the [event delegation concept]

    Also id should be unique, so instead of using it and trying to change id's for cloned elements using incremental value is not required at all, you can easily go for class concept.

    Working snippet (by removing duplicate id's and not using id until necessary):

    const myCharges = {
      "this charge": "",
      "second charge": "",
      "third charge": "",
    };
    
    let chargeHtml = '';
    
    $.each(myCharges, function(i, n) {
      chargeHtml += '<li>' + i + '</li>';
    });
    
    $(function() {
      $('#addMore').click(function() {
        $('#chargeGroups').append($('.search-dropdown:first').clone());
      });
    
      $('#chargeGroups').on('click', '.dropdown-display', function() {
        $(this).next('.dropdown-content').toggle();
        $(this).next('.dropdown-content').find('ul').html(chargeHtml);
    
      });
      $('#chargeGroups').on('input','.search-input', function() {
        let value = $(this).val().toLowerCase();
        $(this).next('ul').find('li').filter(function() {
          $(this).toggle($(this).text().toLowerCase().indexOf(value) > -1);
        });
      });
    
      $('#chargeGroups').on('click', 'ul > li', function(e) {
        $(this).closest('.search-dropdown').find('.dropdown-display > span').text($(this).text());
        $(this).closest('.search-dropdown').find('.dropdown-display > input[type=hidden]').val($(this).text());
        $(this).closest('.dropdown-content').hide();
      });
    
    });
    form .group {
      display: table;
      width: 100%;
    }
    
    form p.group label,
    form div.group label {
      display: table-cell;
      width: 20%;
    }
    
    form p.group input,
    form p.group select {
      /* display: table-cell; */
      width: 100%;
    }
    
    .terms-section {
      width: 100%;
      max-width: 400px;
      margin: 0 auto 1em;
    }
    
    #selectCharges>select {}
    
    #addMore {
      margin: auto auto 1em;
      display: table-cell;
      text-align: center;
    }
    
    #termsCheck {
      cursor: pointer;
    }
    
    #scrollable {
      border: solid 1px;
      height: 100px;
      margin: 1em auto;
      padding: 10px;
      overflow-y: scroll;
    }
    
    .close {
      position: absolute;
      color: #fff;
      top: 0;
      right: 0;
      padding: 2px 10px;
      margin: 5px;
      background: rgba(0, 0, 0, 0.5);
      border-radius: 50px;
      cursor: pointer;
    }
    
    #popup {
      display: none;
      font-size: 1em;
      position: absolute;
      top: 0;
      width: 80%;
      max-width: 400px;
      height: 20em;
      padding: 20px;
      margin: auto;
      border: 1px solid;
      background: #eee;
      overflow-y: scroll;
      z-index: 101;
    }
    
    #mask {
      position: fixed;
      top: 0;
      left: 0;
      width: 100%;
      height: 100%;
      background-color: #000;
      display: none;
      z-index: 100;
    }
    
    .search-dropdown {
      margin-bottom: 1em;
    }
    
    .dropdown-display {
      /* width: 75%; */
      /* display: table-cell; */
      padding: 0 6px 1px;
      border: 1px solid #bbb;
      cursor: pointer;
    }
    
    .dropdown-content {
      display: none;
    }
    
    .dropdown-content .search-input {
      display: table-cell;
      width: 100%;
      margin: 1em 5% 0 0;
    }
    
    .dropdown-content ul {
      list-style-type: none;
      padding: 0;
      margin: 0;
      display: inline-block;
      padding-top: 1em;
      width: 100%;
    }
    
    .dropdown-content ul li {
      padding: 0 10px;
      cursor: pointer;
      border: 1px solid #bbb;
      /* display: table-header-group; */
    }
    
    .dropdown-content ul li:not(:first-child) {
      border-top: 0;
    }
    
    .dropdown-content ul li:hover {
      background-color: #f1f1f1;
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
    <form action="google.com/" method="get" target="_parent" name="inmateInfo" id="inmateInfo">
      <div id="chargeGroups">
        <label>Charges: </label>
        <div class="search-dropdown group" name="charge1">
          <div class="dropdown-display">
            <span>Select Charge</span>
            <input name="chargehide" type="hidden">
          </div>
          <div class="dropdown-content">
            <input type="text" placeholder="Search..." class="search-input">
            <ul name="charge">
    
            </ul>
          </div>
        </div>
      </div>
    
      <button id="addMore">Add Charge</button>
    
    </form>