0

Need help with sorting a table that I dynamically create with adding new rows with the Add Contact button. I managed to sort it by clicking on the column headers but I need to make it work with the HTML Tag. The table has index column, first name column, last name column, email, password, and phone column. I made the index to be random just so I don't need to input anything in the input fields and can try sorting the table with just adding new Contacts (rows) and sorting them by an index for start. I just need help sorting them by the index and populating the table. The rest I will figure it out. Any help will be appreciated.

<!DOCTYPE html>
<html>
    <head>
        <title>Page Title</title>
        <link rel="stylesheet" type="text/css" media="screen" href="CSS/style.css" />
    </head>
    <body>
        <div id="inputs-div">
            <input type="text" placeholder="Your Name Sir" id="name-input">
            <input type="text" placeholder="Your Last Name Sir" id="lastname-input">
            <input type="text" placeholder="Your Email Sir" id="email-input">
            <input type="password" placeholder="Your Password Sir" id="pass-input" >
            <input type="text" placeholder="Your Phone Number" id="phone-input" >
            <button id="new-row-btn">Add Contact</button>
        </div>

        <select class="custom-select" id="sort">
                <option selected>Choose...</option>
                <option value="1">Index</option>
                <option value="2">First Name</option>
                <option value="3">Last Name</option>
                <option value="4">Email</option>
                <option value="5">Phone Number</option>
        </select>

        <div>
            <table id="my-table">
                <thead>
                    <tr id="first-row">
                        <th>ID</th>
                        <th>First name</th>
                        <th>Last name</th>
                        <th>Email</th>
                        <th>Password</th>
                        <th>Phone</th>
                        <th>Sxxxy Action</th>
                        <th>Delete Action</th>
                    </tr>
                </thead>
                <tbody id="tbody">

                </tbody>
            </table>
        </div>

        <script src="JS/jquery-3.2.1.js"></script>
        <script src="JS/script.js"></script>
    </body>
</html>

And here is the script

$(document).ready(function(){

let idCounter = parseFloat(Math.random() * 100).toFixed(0)

    $('#new-row-btn').click(function(){

        $("#my-table").append("<tr><td class='td-id'>"+ idCounter+"</td><td class='f_Name'>"+$("#name-input").val()+
        "</td><td class='l_Name'>"+$("#lastname-input").val()+
        "</td><td class='e_mail'>"+$("#email-input").val()+
        "</td><td class='pass_in'>"+$("#pass-input").val()+
        "</td><td class='phone_in'>"+$("#phone-input").val()+
        "</td><td class='td-three-Btn'><button id='saveBtn"+idCounter+"' class='save-Btn'>save</button><button id='editBtn"+idCounter+"' class='edit-Btn'>edit</button><button id='delBtn"+idCounter+"' class='del-Btn'>del</button></td>"+ "<td class='td-del'><button class='del-row'>Del</button></td>"+ "</tr>")

        $("#name-input").val("")
        $("#lastname-input").val("")
        $("#email-input").val("")
        $("#pass-input").val("")
        $("#phone-input").val("")
        idCounter++;

            $("td:even").css( "background-color", "#a35635" );
            $("td:odd").css( "background-color", "#828e20" );


            idCounter = parseFloat(Math.random() * 100).toFixed(0)

    });

    $(document).on('click', '.del-row', function (event) {
        $(event.target).parent().parent().remove()
        $("td:even").css( "background-color", "#a35635" );
        $("td:odd").css( "background-color", "#828e20" );
});

    $(document).on('click', '.edit-Btn', function (event) {
        var $row = $(this).closest('tr');
        var id = $row.find('.td-id').text();
        var fName = $row.find('.f_Name').text();
        var lName = $row.find('.l_Name').text();
        var email = $row.find('.e_mail').text();
        var pass = $row.find('.pass_in').text();
        var phone = $row.find('.phone_in').text();



        let choose_your_poison = "<td class='td-id'>"+ id +"</td><td class='f_Name'>"+"<input class='in_f_name' type='text' value='"+fName+"'>"+
        "</td><td class='l_Name'>"+"<input class='in_l_name' type='text' value='"+lName+"'>"+
        "</td><td class='e_mail'>"+"<input class='in_e_mail' type='text' value='"+email+"'>"+
        "</td><td class='pass_in'>"+"<input class='in_pass_in' type='text' value='"+pass+"'>"+
        "</td><td class='phone_in'>"+"<input class='in_phone_in' type='text' value='"+phone+"'>"+
        "</td><td class='td-three-Btn'><button id='saveBtn"+idCounter+"' class='save-Btn'>save</button><button id='editBtn"+idCounter+"' class='edit-Btn'>edit</button><button id='delBtn"+idCounter+"' class='del-Btn'>del</button></td>"+ "<td class='td-del'><button class='del-row'>Del</button></td>"

        $(this).closest('tr').html(choose_your_poison);

        $("td:even").css( "background-color", "#a35635" );
        $("td:odd").css( "background-color", "#828e20" );


        let edit = $row.find('.edit-Btn')
        let del_btn = $row.find('.del-Btn')
        let save_btn = $row.find('.save-Btn')

        edit.css('display','none');
        del_btn.css('display','none');
        save_btn.css('display','block');
    });


    $(document).on('click', '.save-Btn', function (event) {

        var $row = $(this).closest('tr');

        var f_Name = $row.find('.in_f_name').val();
        var l_Name = $row.find('.in_l_name').val();
        var e_Mail = $row.find('.in_e_mail').val();
        var pass_W = $row.find('.in_pass_in').val();
        var phone_N = $row.find('.in_phone_in').val();


        $row.find('.f_Name').html(f_Name);
        $row.find('.l_Name').html(l_Name);
        $row.find('.e_mail').html(e_Mail);
        $row.find('.pass_in').html(pass_W);
        $row.find('.phone_in').html(phone_N);


        let edit = $row.find('.edit-Btn')
        let del_btn = $row.find('.del-Btn')
        let save_btn = $row.find('.save-Btn')

        edit.css('display','inline');
        del_btn.css('display','inline');
        save_btn.css('display','none');

    });

//===================================================================
// Need Help
//===================================================================


$("#sort").on("change", function(event){
        var pickedValue = event.target.value;

        switch(pickedValue){
            case '1': //sort by index
            sortTable = (function(a, b){
                var asc  = order === 'asc',
                tbody = table.find('tbody');

            tbody.find('tr').sort(function(a, b) {
                if (asc) {
                    return  (parseInt($('td:first', a).text()) - parseInt($('td:first', b).text()));

                }
                else 
                {
                    return (parseInt($('td:first', b).text()) - parseInt($('td:first', a).text()));
                }
            }).appendTo(tbody);

            })
                break;
            case '2': // sort by first name
                sortingFunction = (a, b) => 
                        (a.localeCompare(b));
                break;
            case '3': // sort by last name
                sortingFunction = (a, b) => 
                    (a.localeCompare(b));
                break;
            case '4': // sort by email date
                sortingFunction = (a, b) => 
                    (a.localeCompare(b));
                break;
            case '5': // sort by phone
                sortingFunction = (a, b) => 
                (parseInt(a) - parseInt(b));
                break;
            default:
                break;
        }
        sortTable($('#mytable'),'asc');

    });



//===================================================================
// It works
//===================================================================

$('th').click(function(){
    var table = $(this).parents('table').eq(0)
    var rows = table.find('tr:gt(0)').toArray().sort(comparer($(this).index()))
    this.asc = !this.asc
    if (!this.asc){rows = rows.reverse()}
    for (var i = 0; i < rows.length; i++){table.append(rows[i])}
})
function comparer(index) {
    return function(a, b) {
        var valA = getCellValue(a, index), valB = getCellValue(b, index)
        return $.isNumeric(valA) && $.isNumeric(valB) ? valA - valB : valA.localeCompare(valB)
    }
}
function getCellValue(row, index){ return $(row).children('td').eq(index).text() }


});
Emad Emami
  • 4,148
  • 3
  • 23
  • 34
Happy Coconut
  • 755
  • 1
  • 9
  • 24
  • You can use `JQuery data-table`, so no extra efforts needed for searching and sorting, – harish sharma Feb 07 '18 at 04:12
  • Here's the datatables plugin: https://datatables.net/ If you learn how to use it, you'll find all sorts of things that you can do. Sorting is just one of them. – BobRodes Feb 07 '18 at 04:56
  • Dig in to the accepted answer here for one possible solution https://stackoverflow.com/q/10123953/125981 – Mark Schultheiss Feb 07 '18 at 05:00
  • Thanks for the suggestions however i need to solve this without plugins. I hope i will find my answer here like Mark suggested. Have a nice day and thanks for your time. – Happy Coconut Feb 07 '18 at 05:08
  • IF you read the accepted answer it is not a plug-in. FYI `var asc = order === 'asc',` the `order` is not defined there. – Mark Schultheiss Feb 07 '18 at 05:25
  • Sorry Mark for the misunderstanding but i didn't mean that your suggestion was to use plug-in. I was referring to BobRodes's comment. – Happy Coconut Feb 07 '18 at 05:36

2 Answers2

0

OK here is one possible solution using your existing column header for the sort, just trigger the click on the select choice (not sure why both exist but this does that). Note added the first row, cloned it and removed it - should make it easier to maintain than editing code.

I also took some liberty with classes, using CSS to style instead of script, using classes to target stuff etc.

Basically this manipulates the row in place on an edit. Two "delete" BUTTONS but I have no idea what the other is for so I used the delete row one.

This keeps the "id" in the table as data, increment from 0, not duplicating if rows removed.

$(document).ready(function() {
  // get first row,clone it then remove it
  var firstRow = $("#my-table")
    .find('tbody')
    .find('.contact-row')
    .first().hide();
  var cloneRow = firstRow.clone(true).data('last-row-counter', 0).show();
  firstRow.remove();

  $('#new-row-btn').on('click', function() {
    // just use the table to keep track of rows added
    let idCounter = $("#my-table").data('lastrowadded') + 1;
    $("#my-table").data('lastrowadded', idCounter);

    var newRow = cloneRow.clone(true);
    newRow.find('.save-Btn').hide()
    newRow.find('.td-id').html(idCounter);
    newRow.find('.f_Name').html($("#name-input").val()); +
    newRow.find('.l_Name').html($("#lastname-input").val());
    newRow.find('.e_mail').html($("#email-input").val());
    newRow.find('.pass_in').html($("#pass-input").val());
    newRow.find('.phone_in').html($("#phone-input").val());
    $("#my-table").find('tbody').append(newRow);
    // blank out the onputs
    $("#inputs-div").find(".contactfield").val("");
  });
  $('#my-table').on('click', '.del-row', function(event) {
    $(this).closest('.contact-row').remove();
  });
  $('#my-table').on('click', '.edit-Btn', function(event) {
    var $row = $(this).closest('.contact-row');
    var edits = $row.find('.f_Name,.l_Name,.e_mail,.pass_in,.phone_in');
    edits.each(function(index, element) {
      var inp = $("<input class='editable' type='text'/>").val($(element).text());
      $(element).html(inp);
    });
    $row.find('.edit-Btn').hide();
    $row.find('.del-Btn').hide();
    $row.find('.save-Btn').show();
  });
  $('#my-table').on('click', '.save-Btn', function(event) {
    var $row = $(this).closest('tr.contact-row');
    var edits = $row.find('.f_Name,.l_Name,.e_mail,.pass_in,.phone_in');
    edits.each(function(index, element) {
      var inp = $(element).find('input.editable');
      $(element).html(inp.val());
    });

    $row.find('.edit-Btn').show();
    $row.find('.del-Btn').show();
    $row.find('.save-Btn').hide();
  });
  $("#sort").on("change", function(event) {
    var pickedValue = event.target.value;
    $('#my-table').find('.first-row').find('th').eq(pickedValue).trigger('click');
    //  console.log(pickedValue);
  });

  $('#my-table').on('click', 'th', function() {
    var table = $(this).closest('table');
    var rows = table.find('tr.contact-row')
      .toArray()
      .sort(comparer($(this).index()));
    this.asc = !this.asc;
    if (!this.asc) {
      rows = rows.reverse();
    }
    for (var i = 0; i < rows.length; i++) {
      table.append(rows[i]);
    }
  });

  function comparer(index) {
    return function(a, b) {
      var valA = getCellValue(a, index),
        valB = getCellValue(b, index);
      return $.isNumeric(valA) && $.isNumeric(valB) ? valA - valB : valA.localeCompare(valB);
    }
  }

  function getCellValue(row, index) {
    return $(row).children('td').eq(index).text();
  }
});
#my-table tbody tr.contact-row>td {
  background-color: #a35635;
}

#my-table tbody tr.contact-row>td:nth-child(odd) {
  background-color: #828e20;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>

<body>
  <div id="inputs-div">
    <input class="contactfield" type="text" placeholder="Your Name Sir" id="name-input">
    <input class="contactfield" type="text" placeholder="Your Last Name Sir" id="lastname-input">
    <input class="contactfield" type="text" placeholder="Your Email Sir" id="email-input">
    <input class="contactfield" type="password" placeholder="Your Password Sir" id="pass-input">
    <input class="contactfield" type="text" placeholder="Your Phone Number" id="phone-input">
    <button id="new-row-btn">Add Contact</button>
  </div>
  <div>
    <select class="custom-select" id="sort">
 <option selected>Choose...</option>
 <option value="0">Index</option>
 <option value="1">First Name</option>
 <option value="2">Last Name</option>
 <option value="3">Email</option>
 <option value="5">Phone Number</option>
</select>
  </div>
  <div>
    <table id="my-table" data-lastrowadded="0">
      <thead>
        <tr class="first-row">
          <th>ID</th>
          <th>First name</th>
          <th>Last name</th>
          <th>Email</th>
          <th>Password</th>
          <th>Phone</th>
          <th>Sxxxy Action</th>
          <th>Delete Action</th>
        </tr>
      </thead>
      <tbody>
        <tr class="contact-row">
          <td class='td-id'>0</td>
          <td class='f_Name'></td>
          <td class='l_Name'></td>
          <td class='e_mail'></td>
          <td class='pass_in'></td>
          <td class='phone_in'></td>
          <td class='td-three-Btn'><button class='save-Btn'>save</button><button class='edit-Btn'>edit</button><button class='del-Btn'>del</button>
          </td>
          <td class='td-del'>
            <button class='del-row'>Del Row</button>
          </td>
        </tr>
      </tbody>
    </table>
  </div>
</body>
Mark Schultheiss
  • 28,892
  • 9
  • 63
  • 88
0

This will do it even keeping your random numbers as id and sorting them accordingly.

Basically first you add a attr data-id to each tr. Then you hide all the tr rows. You loop through all the data-id and get the values (this being the id's) and put them in an array. Then you sort the array by either .sort which is ASC or .reverse as DESC. Change this value as needed. Then loop through the new sorted array arr and recreate the html by adding appending each new row according to sort order then display... BAM Done!

If you need to sort by other fields then you would change the class td-id of the td class you need

arr.push($(this).find('.td-id').text());

You just need to figure out how to let the code know which field it needs to sort by

$(document).ready(function() {

  let idCounter = parseFloat(Math.random() * 100).toFixed(0)
  var current;

  $('#new-row-btn').click(function() {

    current = '';

    $("#my-table").append("<tr class='tr-id' data-id='" + idCounter + "'><td class='td-id'>" + idCounter + "</td><td class='f_Name'>" + $("#name-input").val() +
      "</td><td class='l_Name'>" + $("#lastname-input").val() +
      "</td><td class='e_mail'>" + $("#email-input").val() +
      "</td><td class='pass_in'>" + $("#pass-input").val() +
      "</td><td class='phone_in'>" + $("#phone-input").val() +
      "</td><td class='td-three-Btn'><button id='saveBtn" + idCounter + "' class='save-Btn'>save</button><button id='editBtn" + idCounter + "' class='edit-Btn'>edit</button><button id='delBtn" + idCounter + "' class='del-Btn'>del</button></td>" + "<td class='td-del'><button class='del-row'>Del</button></td>" + "</tr>")

    $("#name-input").val("")
    $("#lastname-input").val("")
    $("#email-input").val("")
    $("#pass-input").val("")
    $("#phone-input").val("")
    idCounter++;

    $("td:even").css("background-color", "#a35635");
    $("td:odd").css("background-color", "#828e20");


    idCounter = parseFloat(Math.random() * 100).toFixed(0)

    $('.tr-id').hide();

    var arr = [];
    $('.tr-id').each(function() {
      arr.push($(this).find('.td-id').text());
    });

    // if asc use .sort, if desc use .reverse
    arr.sort(function(a, b) {
      return a - b;
    });

    var i;

    for (i = 0; i < arr.length; ++i) {
      current += "<tr class='tr-id' data-id='" + arr[i] + "'>" + $('.tr-id[data-id="' + arr[i] + '"]').html() + "</tr>";
    }
    $('#tbody').html(current);
  });

  $(document).on('click', '.del-row', function(event) {
    $(event.target).parent().parent().remove()
    $("td:even").css("background-color", "#a35635");
    $("td:odd").css("background-color", "#828e20");
  });

  $(document).on('click', '.edit-Btn', function(event) {
    var $row = $(this).closest('tr');
    var id = $row.find('.td-id').text();
    var fName = $row.find('.f_Name').text();
    var lName = $row.find('.l_Name').text();
    var email = $row.find('.e_mail').text();
    var pass = $row.find('.pass_in').text();
    var phone = $row.find('.phone_in').text();



    let choose_your_poison = "<td class='td-id'>" + id + "</td><td class='f_Name'>" + "<input class='in_f_name' type='text' value='" + fName + "'>" +
      "</td><td class='l_Name'>" + "<input class='in_l_name' type='text' value='" + lName + "'>" +
      "</td><td class='e_mail'>" + "<input class='in_e_mail' type='text' value='" + email + "'>" +
      "</td><td class='pass_in'>" + "<input class='in_pass_in' type='text' value='" + pass + "'>" +
      "</td><td class='phone_in'>" + "<input class='in_phone_in' type='text' value='" + phone + "'>" +
      "</td><td class='td-three-Btn'><button id='saveBtn" + idCounter + "' class='save-Btn'>save</button><button id='editBtn" + idCounter + "' class='edit-Btn'>edit</button><button id='delBtn" + idCounter + "' class='del-Btn'>del</button></td>" + "<td class='td-del'><button class='del-row'>Del</button></td>"

    $(this).closest('tr').html(choose_your_poison);

    $("td:even").css("background-color", "#a35635");
    $("td:odd").css("background-color", "#828e20");


    let edit = $row.find('.edit-Btn')
    let del_btn = $row.find('.del-Btn')
    let save_btn = $row.find('.save-Btn')

    edit.css('display', 'none');
    del_btn.css('display', 'none');
    save_btn.css('display', 'block');
  });


  $(document).on('click', '.save-Btn', function(event) {

    var $row = $(this).closest('tr');

    var f_Name = $row.find('.in_f_name').val();
    var l_Name = $row.find('.in_l_name').val();
    var e_Mail = $row.find('.in_e_mail').val();
    var pass_W = $row.find('.in_pass_in').val();
    var phone_N = $row.find('.in_phone_in').val();


    $row.find('.f_Name').html(f_Name);
    $row.find('.l_Name').html(l_Name);
    $row.find('.e_mail').html(e_Mail);
    $row.find('.pass_in').html(pass_W);
    $row.find('.phone_in').html(phone_N);


    let edit = $row.find('.edit-Btn')
    let del_btn = $row.find('.del-Btn')
    let save_btn = $row.find('.save-Btn')

    edit.css('display', 'inline');
    del_btn.css('display', 'inline');
    save_btn.css('display', 'none');

  });

  //===================================================================
  // Need Help
  //===================================================================


  $(document).on("change", "#sort", function(event) {
    var pickedValue = event.target.value;

    switch (pickedValue) {
      case '1': //sort by index
        sortTable = (function(a, b) {
          var asc = order === 'asc',
            tbody = table.find('tbody');

          tbody.find('tr').sort(function(a, b) {
            if (asc) {
              return (parseInt($('td:first', a).text()) - parseInt($('td:first', b).text()));

            } else {
              return (parseInt($('td:first', b).text()) - parseInt($('td:first', a).text()));
            }
          }).appendTo(tbody);

        })
        break;
      case '2': // sort by first name
        sortingFunction = (a, b) =>
          (a.localeCompare(b));
        break;
      case '3': // sort by last name
        sortingFunction = (a, b) =>
          (a.localeCompare(b));
        break;
      case '4': // sort by email date
        sortingFunction = (a, b) =>
          (a.localeCompare(b));
        break;
      case '5': // sort by phone
        sortingFunction = (a, b) =>
          (parseInt(a) - parseInt(b));
        break;
      default:
        break;
    }
    sortTable($('#mytable'), 'asc');

  });



  //===================================================================
  // It works
  //===================================================================

  $('th').click(function() {
    var table = $(this).parents('table').eq(0)
    var rows = table.find('tr:gt(0)').toArray().sort(comparer($(this).index()))
    this.asc = !this.asc
    if (!this.asc) {
      rows = rows.reverse()
    }
    for (var i = 0; i < rows.length; i++) {
      table.append(rows[i])
    }
  })

  function comparer(index) {
    return function(a, b) {
      var valA = getCellValue(a, index),
        valB = getCellValue(b, index)
      return $.isNumeric(valA) && $.isNumeric(valB) ? valA - valB : valA.localeCompare(valB)
    }
  }

  function getCellValue(row, index) {
    return $(row).children('td').eq(index).text()
  }


});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<title>Page Title</title>
<link rel="stylesheet" type="text/css" media="screen" href="CSS/style.css" />
</head>

<body>
  <div id="inputs-div">
    <input type="text" placeholder="Your Name Sir" id="name-input">
    <input type="text" placeholder="Your Last Name Sir" id="lastname-input">
    <input type="text" placeholder="Your Email Sir" id="email-input">
    <input type="password" placeholder="Your Password Sir" id="pass-input">
    <input type="text" placeholder="Your Phone Number" id="phone-input">
    <button id="new-row-btn">Add Contact</button>
  </div>

  <select class="custom-select" id="sort">
                <option selected>Choose...</option>
                <option value="1">Index</option>
                <option value="2">First Name</option>
                <option value="3">Last Name</option>
                <option value="4">Email</option>
                <option value="5">Phone Number</option>
        </select>

  <div>
    <table id="my-table">
      <thead>
        <tr id="first-row">
          <th>ID</th>
          <th>First name</th>
          <th>Last name</th>
          <th>Email</th>
          <th>Password</th>
          <th>Phone</th>
          <th>Sxxxy Action</th>
          <th>Delete Action</th>
        </tr>
      </thead>
      <tbody id="tbody">

      </tbody>
    </table>
  </div>

  <script src="JS/jquery-3.2.1.js"></script>
  <script src="JS/script.js"></script>
</body>

</html>

.

Cesar Bielich
  • 4,018
  • 7
  • 33
  • 71