Search code examples
javascripthtmljquery

Reordering rows with javascript


I have multiple select dropdowns and each dropdown has a corresponding input field. What I'm trying to do is a JS function that will allow reordering the rows with icons UP/DOWN click.

What I'm trying to do also is simply for the first row to have only a DOWN icon, for the last row to have only a UP icon, and for everything else between them to have both UP and DOWN. What is happening is that I have UP and DOWN for the first and second rows and UP for the last one.

Here is the code that I have so far

$(document).ready(function () {

  function moveUp(index) {
    if (index === 0) return;
    var $currentItem = $('[name="status[' + index + ']"]').closest('.line');
    var $prevItem = $('[name="status[' + (index - 1) + ']"]').closest('.line');
    $currentItem.insertBefore($prevItem);
    updateIconsVisibility();
  }

  function moveDown(index) {
    var $currentItem = $('[name="status[' + index + ']"]').closest('.line');
    var $nextItem = $('[name="status[' + (index + 1) + ']"]').closest('.line');
    $nextItem.insertAfter($currentItem);
    updateIconsVisibility();
  }

  function updateIconsVisibility() {
    $('.line').each(function (index, element) {
      var $line = $(element);
      var $arrows = $line.find('.arrows');
      var $upIcon = $arrows.find('.fa-chevron-circle-up');
      var $downIcon = $arrows.find('.fa-chevron-circle-down');

      if (index === 0) {
        $upIcon.hide();
        $downIcon.show();
      } else if (index === $('.line').length - 1) {
        $upIcon.show();
        $downIcon.hide();
      } else {
        $upIcon.show();
        $downIcon.show();
      }
    });
  }

  $(document).on('click', '.move-up-button', function() {
    var index = $(this).data('index');
    moveUp(index);
  });

  $(document).on('click', '.move-down-button', function() {
    var index = $(this).data('index');
    moveDown(index);
  });

  updateIconsVisibility();
});
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css" rel="stylesheet"/>
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<div class="mb-3"   id="dropdown-container-edit">
<div class="line" style="margin-top: 15px;display: flex;min-width: 329px;">
    <div style="float:left;display: flex; flex-direction: column;width: 10%;">
        <label for="select-group" class="form-label">Select Status</label>
    </div>
</div>

<div class="line" style="margin-top: 15px;display: flex;min-width: 329px;">
    <div style="float:left;display: flex; flex-direction: column;width: 10%;">
        <select class="select-group" name="status[0]">
            <option value="" data-id="">Select Status</option>
            <option value="0" data-id="" selected>Status_1</option>
            <option value="1" data-id="" >Status_2</option>
            <option value="2" data-id="" >Status_3</option>   
        </select>
    </div>
    <div style="float:left; display: flex; flex-direction: column; width: 90%;">
        <input type="text" class="input-field status-input" name="status-input[0]" style="margin-left: 5px;" value="status_1">
    </div>
 
    <div class="arrows" style="display: inherit;margin-left: 10px;margin-top: 3px; ">
        <i class="fa fa-chevron-circle-up fa-2x move-up-button" data-index="0" style="margin-right: 5px;"></i>
        <i class="fa fa-chevron-circle-down fa-2x move-down-button" data-index="0"></i>
    </div>
</div>

<div class="line" style="margin-top: 15px;display: flex;min-width: 329px;">
    <div style="float:left;display: flex; flex-direction: column;width: 10%;">
        <select class="select-group" name="status[1]">
            <option value="" data-id="">Select Status</option>
            <option value="0" data-id="" >Status_1</option>
            <option value="1" data-id="" selected>Status_2</option>
            <option value="2" data-id="" >Status_3</option>   
        </select>
    </div>
    <div style="float:left; display: flex; flex-direction: column; width: 90%;">
        <input type="text" class="input-field status-input" name="status-input[1]" style="margin-left: 5px;" value="status_2">
    </div>
 
    <div class="arrows" style="display: inherit;margin-left: 10px;margin-top: 3px; ">
        <i class="fa fa-chevron-circle-up fa-2x move-up-button" data-index="1" style="margin-right: 5px;"></i>
        <i class="fa fa-chevron-circle-down fa-2x move-down-button" data-index="1"></i>
    </div>
</div>

<div class="line" style="margin-top: 15px;display: flex;min-width: 329px;">
    <div style="float:left;display: flex; flex-direction: column;width: 10%;">
        <select class="select-group" name="status[2]">
            <option value="" data-id="">Select Status</option>
            <option value="0" data-id="" >Status_1</option>
            <option value="1" data-id="" >Status_2</option>
            <option value="2" data-id="" selected>Status_3</option>   
        </select>
    </div>
    <div style="float:left; display: flex; flex-direction: column; width: 90%;">
        <input type="text" class="input-field status-input" name="status-input[2]" style="margin-left: 5px;" value="status_3">
    </div>
 
    <div class="arrows" style="display: inherit;margin-left: 10px;margin-top: 3px; ">
        <i class="fa fa-chevron-circle-up fa-2x move-up-button" data-index="2" style="margin-right: 5px;"></i>
        <i class="fa fa-chevron-circle-down fa-2x move-down-button" data-index="2"></i>
    </div>
</div>
</div>

If Need here is the JSFiddle too: https://jsfiddle.net/tm51dkra/2/


Solution

  • I've changed only a few things:

    in your moveDown function you have this code: $nextItem.insertAfter($currentItem); but it should be $currentItem.insertAfter($nextItem);

    I also remove class line from the first div.

    <div class="" style="margin-top: 15px;display: flex;min-width: 329px;">
        <div style="float:left;display: flex; flex-direction: column;width: 10%;">
            <label for="select-group" class="form-label">Select Status</label>
        </div>
    </div>
    

    Because you use .line as a selector, like in:

    function updateIconsVisibility() {
        $('.line').each(function (index, element) {
    

    I've added an updateIndexes function to update the indexes, so they sorting will work.

    Demo

    $(document).ready(function() {
    
      function moveUp(index) {
        index = parseInt(index);
        if (index === 0) return;
        var $currentItem = $('[name="status[' + index + ']"]').closest('.line');
        var $prevItem = $('[name="status[' + (index - 1) + ']"]').closest('.line');
        $currentItem.insertBefore($prevItem);
        updateIndexes();
        updateIconsVisibility();
      }
    
      function moveDown(index) {
        index = parseInt(index);
        var $currentItem = $('[name="status[' + index + ']"]').closest('.line');
        var $nextItem = $('[name="status[' + (index + 1) + ']"]').closest('.line');
        if ($nextItem.length === 0) return;
        $currentItem.insertAfter($nextItem);
        updateIndexes();
        updateIconsVisibility();
      }
      
      function updateIndexes() {
        $('.line').each(function(i) {
          $(this).find('select[name^="status"]').attr('name', 'status[' + i + ']');
          $(this).find('input[name^="status-input"]').attr('name', 'status-input[' + i + ']');
          $(this).find('.move-up-button, .move-down-button').attr('data-index', i);
        });
      }
    
      function updateIconsVisibility() {
        $('.line').each(function(index) {
          var $upIcon = $(this).find('.fa-chevron-circle-up');
          var $downIcon = $(this).find('.fa-chevron-circle-down');
    
          if (index === 0) {
            $upIcon.hide();
          } else {
            $upIcon.show();
          }
          if (index === $('.line').length - 1) {
            $downIcon.hide();
          } else {
            $downIcon.show();
          }
        });
      }
    
      $(document).on('click', '.move-up-button', function() {
        var index = $(this).attr('data-index');
        moveUp(index);
      });
    
      $(document).on('click', '.move-down-button', function() {
        var index = $(this).attr('data-index');
        moveDown(index);
      });
      updateIndexes();
      updateIconsVisibility();
    });
    <link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css" rel="stylesheet" />
    <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet" />
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
    <div class="mb-3" id="dropdown-container-edit">
      <div class="" style="margin-top: 15px;display: flex;min-width: 329px;">
        <div style="float:left;display: flex; flex-direction: column;width: 10%;">
          <label for="select-group" class="form-label">Select Status</label>
        </div>
      </div>
    
      <div class="line" style="margin-top: 15px;display: flex;min-width: 329px;">
        <div style="float:left;display: flex; flex-direction: column;width: 10%;">
          <select class="select-group" name="status[0]">
            <option value="" data-id="">Select Status</option>
            <option value="0" data-id="" selected>Status_1</option>
            <option value="1" data-id="">Status_2</option>
            <option value="2" data-id="">Status_3</option>
          </select>
        </div>
        <div style="float:left; display: flex; flex-direction: column; width: 90%;">
          <input type="text" class="input-field status-input" name="status-input[0]" style="margin-left: 5px;" value="status_1">
        </div>
    
        <div class="arrows" style="display: inherit;margin-left: 10px;margin-top: 3px; ">
          <i class="fa fa-chevron-circle-up fa-2x move-up-button" data-index="0" style="margin-right: 5px;"></i>
          <i class="fa fa-chevron-circle-down fa-2x move-down-button" data-index="0"></i>
        </div>
      </div>
    
      <div class="line" style="margin-top: 15px;display: flex;min-width: 329px;">
        <div style="float:left;display: flex; flex-direction: column;width: 10%;">
          <select class="select-group" name="status[1]">
            <option value="" data-id="">Select Status</option>
            <option value="0" data-id="">Status_1</option>
            <option value="1" data-id="" selected>Status_2</option>
            <option value="2" data-id="">Status_3</option>
          </select>
        </div>
        <div style="float:left; display: flex; flex-direction: column; width: 90%;">
          <input type="text" class="input-field status-input" name="status-input[1]" style="margin-left: 5px;" value="status_2">
        </div>
    
        <div class="arrows" style="display: inherit;margin-left: 10px;margin-top: 3px; ">
          <i class="fa fa-chevron-circle-up fa-2x move-up-button" data-index="1" style="margin-right: 5px;"></i>
          <i class="fa fa-chevron-circle-down fa-2x move-down-button" data-index="1"></i>
        </div>
      </div>
    
      <div class="line" style="margin-top: 15px;display: flex;min-width: 329px;">
        <div style="float:left;display: flex; flex-direction: column;width: 10%;">
          <select class="select-group" name="status[2]">
            <option value="" data-id="">Select Status</option>
            <option value="0" data-id="">Status_1</option>
            <option value="1" data-id="">Status_2</option>
            <option value="2" data-id="" selected>Status_3</option>
          </select>
        </div>
        <div style="float:left; display: flex; flex-direction: column; width: 90%;">
          <input type="text" class="input-field status-input" name="status-input[2]" style="margin-left: 5px;" value="status_3">
        </div>
    
        <div class="arrows" style="display: inherit;margin-left: 10px;margin-top: 3px; ">
          <i class="fa fa-chevron-circle-up fa-2x move-up-button" data-index="2" style="margin-right: 5px;"></i>
          <i class="fa fa-chevron-circle-down fa-2x move-down-button" data-index="2"></i>
        </div>
      </div>
    
    
    </div>