skip to Main Content

https://phpout.com/wp-content/uploads/2024/03/4PpsO.png

This is very unique requirement that I want to make up/down (sort order row) functionality. I can able to do up/down using jQuery but I have required complicated requirement which I tried but can’t able to do it. As I attached snapshot. If I click down button #trMain-1989 then that row with next 4 row move after #trMain-1991

Same thing if I click up button of #trMain-1995 then it will move all 5 rows(#trMain-1995, #trLang-1995, #trQuestion-1995, #trAnswer-1995 and #trAct-1995) move to up before #trMain-1993

Here are my codes which I am trying last 3-4 days but not success.

Code: 1

$(document).on('click','.fas', function(event){
    var $element = this;
    var row = $($element).parents("tr:first");
    let index = oTable.row(row).index();
    console.log(index);
    if($(this).is('.up')){
        row.eq(index-4).insertBefore(row.prev());
    }else{
        row.eq(index+4).insertAfter(row.next());
    }
    return false;
    });

Code: 2

$(document).on('click','.fas', function(event){
    
    if(oTable){
        let tr = $(this).closest('tr');
        let cls = $(tr).attr("class");
        //console.log(cls);
            cls = cls.split("-");
        //console.log(cls[1]);
        let index = oTable.row(tr).index();
        let indexes = oTable.rows()[0];
        
        let order = -1;
        let buttonName = event.currentTarget.className;
        if(buttonName.indexOf('down') > 0){
            order = 1;
        }
        
        let data1 = oTable.row(index).data();
        console.log(data1);
        let base_index = indexes.indexOf(index) + order;
        console.log(base_index);
        let index2 = indexes[base_index];
        console.log(index2);
        var data2 = oTable.row(index2).data();
        //console.log(data1);
        oTable.row(index).data(data2);
        oTable.row(index2).data(data1);
});

I am expecting that if anyone can help me to correct my code or give any smart solution if it then it would be great for me. Thanks

2

Answers


  1. You want to move them as if they were groups.

    Each group start with a tr that has class that starts with trMain- and ends with a tr that has class that starts with trAct-.

    In order to move up from tr_current we find the previous trMain- and call it tr_target. We start moving our tr_current and all its next siblings to before the tr_target until tr_current points to the next trMain- which we won’t move.

    In order to move down, it’s the same logic only a little more advanced since we move like 10 elements below rather than 5 above. Look at code.

    document.querySelectorAll(".up").forEach(function(button) {
      button.addEventListener('click', moveUp)
    })
    
    document.querySelectorAll(".down").forEach(function(button) {
      button.addEventListener('click', moveDown)
    })
    
    function moveUp(ev) {
      var tr_current = ev.target.closest('tr')
    
      // find previous tr that has class that starts with 'main-'
      var tr_target = tr_current.previousElementSibling
      while (tr_target && ![...tr_target.classList].some((cls) => cls.startsWith('trMain-'))) {
        tr_target = tr_target.previousElementSibling
      }
      if (!tr_target) {
        return
      }
    
      // move each tr_current before tr_target until has class that starts with 'main-'
      do {
        var next = tr_current.nextElementSibling
        tr_current.parentNode.insertBefore(tr_current, tr_target)
        tr_current = next
      } while (tr_current && ![...tr_current.classList].some((cls) => cls.startsWith('trMain-')))
    
    }
    
    // same logic but a step further 
    function moveDown(ev) {
      var tr_current = ev.target.closest('tr')
    
      var tr_target = tr_current.nextElementSibling
      while (tr_target && ![...tr_target.classList].some((cls) => cls.startsWith('trMain-'))) {
        tr_target = tr_target.nextElementSibling
      }
      if (!tr_target) {
        return
      }
      var tr_target = tr_target.nextElementSibling
      while (tr_target && ![...tr_target.classList].some((cls) => cls.startsWith('trAct-'))) {
        tr_target = tr_target.nextElementSibling
      }
    
      do {
        var next = tr_current.nextElementSibling
        tr_current.parentNode.insertBefore(tr_current, tr_target.nextElementSibling)
        tr_current = next
        tr_target = tr_target.nextElementSibling
      } while (tr_current && ![...tr_current.classList].some((cls) => cls.startsWith('trMain-')))
    
    }
    table {
      width: 100%;
      border-collapse: collapse;
    }
    
    [class*="trMain-"] {
      background: yellow;
    }
    <table border="1">
      <tbody>
        <tr class="trMain-1989">
          <td>trMain 1989 <button class="up">up</button> <button class="down">down</button></td>
        </tr>
        <tr class="trLang-1989">
          <td>trLang 1989</td>
        </tr>
        <tr class="trQuestion-1989">
          <td>trQuestion 1989</td>
        </tr>
        <tr class="trAnswer-1989">
          <td>trAnswer 1989</td>
        </tr>
        <tr class="trAct-1989">
          <td>trAct 1989</td>
        </tr>
        <tr class="trMain-1991">
          <td>trMain 1991 <button class="up">up</button> <button class="down">down</button></td>
        </tr>
        <tr class="trLang-1991">
          <td>trLang 1991</td>
        </tr>
        <tr class="trQuestion-1991">
          <td>trQuestion 1991</td>
        </tr>
        <tr class="trAnswer-1991">
          <td>trAnswer 1991</td>
        </tr>
        <tr class="trAct-1991">
          <td>trAct 1991</td>
        </tr>
        <tr class="trMain-1993">
          <td>trMain 1993 <button class="up">up</button> <button class="down">down</button></td>
        </tr>
        <tr class="trLang-1993">
          <td>trLang 1993</td>
        </tr>
        <tr class="trQuestion-1993">
          <td>trQuestion 1993</td>
        </tr>
        <tr class="trAnswer-1993">
          <td>trAnswer 1993</td>
        </tr>
        <tr class="trAct-1993">
          <td>trAct 1993</td>
        </tr>
        <tr class="trMain-1995">
          <td>trMain 1995 <button class="up">up</button> <button class="down">down</button></td>
        </tr>
        <tr class="trLang-1995">
          <td>trLang 1995</td>
        </tr>
        <tr class="trQuestion-1995">
          <td>trQuestion 1995</td>
        </tr>
        <tr class="trAnswer-1995">
          <td>trAnswer 1995</td>
        </tr>
        <tr class="trAct-1995">
          <td>trAct 1995</td>
        </tr>
      </tbody>
    </table>
    Login or Signup to reply.
  2. As of jQuery 3.4, the :first pseudo-class is deprecated. Remove it
    from your selectors and filter the results later using .first().

    Since there is already an answer for your current schema, I’ll suggest some improvements.

    • Pre-fixing your class names with tr is redundant when the element name is also tr. This expands to tr.trMain-1999 which could be reduced to tr.main-1999 without loosing any information.

    • Your class names appear to post-fixed with a year, and since we want to group by this data, you could store this as a data- property instead of a class.

    let GetGroup = (group) => $(`table tr[data-group="${group}"]`);
    
    $('table') //this is just boiler plate to generate a table
      .html([...Array(10)].map((u, i) =>  ['main','language','question','answer','act'].map((item) => `<tr class="${item}" data-group="${i + 1985}" style="background-color:#${(i * 369e3).toString(16).padStart(6, '0')}22"><td><button data-move="up">↑</button><button data-move="down">↓</button><span>${i + 1985}</span><span>${item}</span></td></tr>`)).join(''))
      .on('click', 'button[data-move]', function() {
        let $group = GetGroup($(this).parents('tr').attr('data-group'));
        
        ({
          up: () => {
            if ($group.first().prev()) { //can we move up?
              $group.insertBefore(
                GetGroup($group.first().prev().attr('data-group')).first());
            }
          },
          down: () => {
            if ($group.last().next()) { //can we move down?
              $group.insertAfter(
                GetGroup($group.last().next().attr('data-group')).last());
            }
          }
        }[this.dataset.move])(); //which button was clicked
      });
    <table></table>
    
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search