0

I've 2 pop-ups to display the user list & admin list which would display 10 results per page, which is working fine.

I'm getting the page nos. from the java servlet in the JSON.

Note: There are 2 parameters passed in the url - resType and pageNo. pageNo. returns 0, 10, 20 ...(multiples of 10). resType: checks what sort of result I want. You can ignore this part.

So my url in the createTable function looks something like this instead - enter image description here

How do I disable the previous button, when it is the first page? Likewise, how do I disable the last button, when it is the last page?

Here's the code.

var currentPageNo = 0; // Keep track of currently displayed page

  $('.next-btn').unbind("click").on("click",function(){ // Give buttons an ID (include them in HTML as hidden)
   userList(currentPageNo+10);
   adminList(currentPageNo+10);
   
  });
  $('.prev-btn').unbind("click").on("click",function(){
   userList(currentPageNo-10);
   adminList(currentPageNo-10);
  });

  function userList(pageNo) {
   var resType="userList";
   createTable(resType,pageNo);
  }
  
  function adminList(pageNo) {
   var resType="adminList";
   createTable(resType,pageNo);
  }

  function createTable(resType, pageNo) {
   // Update global variable
   currentPageNo = pageNo; 
   // Set visibility of the "prev" button:
   $('.prev-btn').toggle(pageNo > 0);
   // Ask one record more than needed, to determine if there are more records after this page:
   $.getJSON("https://api.randomuser.me/?results=11&start="+pageNo, function(data) {
    $('#datatable tr:has(td)').empty();
    // Check if there's an extra record which we do not display, 
    // but determines that there is a next page
    $('.next-btn').toggle(data.results.length > 10);
    // Slice results, so 11th record is not included:
    data.results.slice(0, 10).forEach(function (record, i) { // add second argument for numbering records
     var json = JSON.stringify(record);
     $('#datatable').append(
      $('<tr>').append(
       $('<td>').append(
        $('<input>').attr('type', 'checkbox')
           .addClass('selectRow')
           .val(json),
        (i+1+pageNo) // display row number
       ),
       $('<td>').append(
        $('<a>').attr('href', record.picture.thumbnail)
          .addClass('imgurl')
          .attr('target', '_blank')
          .text(record.name.first)
       ),
       $('<td>').append(record.dob)
      )
     );
    });
    // Show the prev and/or buttons
    
    
   }).fail(function(error) {
    console.log("**********AJAX ERROR: " + error);
   });            
  }

  var savedData = []; // The objects as array, so to have an order.

  function saveData(){
   var errors = [];
   // Add selected to map
   $('input.selectRow:checked').each(function(count) {
    // Get the JSON that is stored as value for the checkbox
    var obj = JSON.parse($(this).val());
    // See if this URL was already collected (that's easy with Set)
    if (savedData.find(record => record.picture.thumbnail === obj.picture.thumbnail)) {
     errors.push(obj.name.first);
    } else {
     // Append it
     savedData.push(obj);
    }
   });
   refreshDisplay();
   if (errors.length) {
    alert('The following were already selected:\n' + errors.join('\n'));
   }
  }

  function refreshDisplay() {
   $('.container').html('');
   savedData.forEach(function (obj) {
    // Reset container, and append collected data (use jQuery for appending)
    $('.container').append(
     $('<div>').addClass('parent').append(
      $('<label>').addClass('dataLabel').text('Name: '),
      obj.name.first + ' ' + obj.name.last,
      $('<br>'), // line-break between name & pic
      $('<img>').addClass('myLink').attr('src', obj.picture.thumbnail), $('<br>'),
      $('<label>').addClass('dataLabel').text('Date of birth: '),
      obj.dob, $('<br>'),
      $('<label>').addClass('dataLabel').text('Address: '), $('<br>'),
      obj.location.street, $('<br>'),
      obj.location.city + ' ' + obj.location.postcode, $('<br>'),
      obj.location.state, $('<br>'),
      $('<button>').addClass('removeMe').text('Delete'),
      $('<button>').addClass('top-btn').text('Swap with top'),
      $('<button>').addClass('down-btn').text('Swap with down')
     ) 
    );
   })
   // Clear checkboxes:
   $('.selectRow').prop('checked', false);
   handleEvents();
  }

  function logSavedData(){
   // Convert to JSON and log to console. You would instead post it
   // to some URL, or save it to localStorage.
   console.log(JSON.stringify(savedData, null, 2));
  }

  function getIndex(elem) {
   return $(elem).parent('.parent').index();
  }

  $(document).on('click', '.removeMe', function() {
   // Delete this from the saved Data
   savedData.splice(getIndex(this), 1);
   // And redisplay
   refreshDisplay();
  });

  /* Swapping the displayed articles in the result list */
  $(document).on('click', ".down-btn", function() {
   var index = getIndex(this);
   // Swap in memory
   savedData.splice(index, 2, savedData[index+1], savedData[index]);
   // And redisplay
   refreshDisplay();
  });

  $(document).on('click', ".top-btn", function() {
   var index = getIndex(this);
   // Swap in memory
   savedData.splice(index-1, 2, savedData[index], savedData[index-1]);
   // And redisplay
   refreshDisplay();
  });
   
  /* Disable top & down buttons for the first and the last article respectively in the result list */
  function handleEvents() {
   $(".top-btn, .down-btn").prop("disabled", false).show();
   $(".parent:first").find(".top-btn").prop("disabled", true).hide();
   $(".parent:last").find(".down-btn").prop("disabled", true).hide();
  }

  $(document).ready(function(){
   $('#showExtForm-btn').click(function(){
    $('#extUser').toggle();
   });
   $("#extUserForm").submit(function(e){
    addExtUser();
    return false;
     });
  });

  function addExtUser() {
   var extObj = {
    name: {
     title: "mr", // No ladies? :-)
     first: $("#name").val(),
     // Last name ?
    },
    dob: $("#dob").val(),
    picture: {
     thumbnail: $("#myImg").val()
    },
    location: { // maybe also ask for this info?
    }
   };
   savedData.push(extObj);
   refreshDisplay(); // Will show some undefined stuff (location...)
  }
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.0/jquery.min.js"></script>
<button class="btn btn-primary btn-sm" data-toggle="modal" data-target="#userList" onclick="userList(0)">User List</button>
<button class="btn btn-primary btn-sm" onclick="logSavedData()">Get Saved Data</button>
<button class="btn btn-primary btn-sm" data-toggle="modal" data-target="#adminList" onclick="adminList(0)">User Admin</button>
<button class="btn btn-primary btn-sm" data-toggle="modal" data-target="#extUser">Open External Form</button>

       <div class="modal fade" id="userList" role="dialog">
      <div class="modal-dialog modal-lg">
      
        
        <div class="modal-content">
       <div class="modal-header">
         <button type="button" class="close" data-dismiss="modal">&times;</button>
         <h4 class="modal-title">User List</h4>
       </div>
       <div class="modal-body">
         <div class="table-responsive">
                                  <table class="table table-bordered table-hover" id="datatable">
         <tr>
          <th>Select</th>
          <th>Name</th>
          <th>DOB</th>
         </tr>
        </table>
         </div>
         <div class="row">
        <div class="col-sm-offset-3 col-sm-4">
         <button type="button" class="btn btn-primary prev-btn"><span class="glyphicon glyphicon-chevron-left"></span></button>
        </div>

        <div class="col-sm-4">
         <button type="button" class="btn btn-primary next-btn"><span class="glyphicon glyphicon-chevron-right"></span></button>
        </div>
       </div>
                                <hr/>
       <div class="row">
        <div class="col-sm-offset-3 col-sm-4">
         <button type="button" class="btn btn-primary btn-sm" onclick="saveData()">Save selected</button>
        </div>
        <div class="col-sm-4">
         <button type="button" class="btn btn-primary btn-sm close-less-modal" data-dismiss="modal">Close</button>
        </div>
       </div>
       <br />
        </div>
      </div>
       </div>
     </div>
     
     <div class="modal fade" id="adminList" role="dialog">
      <div class="modal-dialog modal-lg">
        <div class="modal-content">
       <div class="modal-header">
         <button type="button" class="close" data-dismiss="modal">&times;</button>
         <h4 class="modal-title">Admin List</h4>
       </div>
       <div class="modal-body">
         <div class="table-responsive">
                                  <table class="table table-bordered table-hover" id="datatable">
         <tr>
          <th>Select</th>
          <th>Name</th>
          <th>DOB</th>
         </tr>
        </table>
         </div>
         <div class="row">
        <div class="col-sm-offset-3 col-sm-4">
         <button type="button" class="btn btn-primary prev-btn"><span class="glyphicon glyphicon-chevron-left"></span></button>
        </div>

        <div class="col-sm-4">
         <button type="button" class="btn btn-primary next-btn"><span class="glyphicon glyphicon-chevron-right"></span></button>
        </div>
       </div>
                                <hr/>
       <div class="row">
        <div class="col-sm-offset-3 col-sm-4">
         <button type="button" class="btn btn-primary btn-sm" onclick="saveData()">Save selected</button>
        </div>
        <div class="col-sm-4">
         <button type="button" class="btn btn-primary btn-sm close-less-modal" data-dismiss="modal">Close</button>
        </div>
       </div>
       <br />
        </div>
      </div>
       </div>
     </div>
     
     <div class="modal fade" id="extUser" role="dialog">
      <div class="modal-dialog modal-lg">
      
        <!-- External User-->
        <div class="modal-content">
       <div class="modal-header">
         <button type="button" class="close" data-dismiss="modal">&times;</button>
         <h4 class="modal-title">Add External User</h4>
       </div>
       <div class="modal-body">
         <form class="form-horizontal" id="extUserForm">
        <div class="form-group">
          <label class="control-label col-sm-3" for="name">Name:</label>
          <div class="col-sm-8">
         <input type="text" class="form-control" id="name" name="name" required>
          </div>
        </div>
        <div class="form-group">
          <label class="control-label col-sm-3" for="myImg">Image:</label>
          <div class="col-sm-8">
         <input type="text" class="form-control" id="myImg" name="myImg" required>
          </div>
        </div>
                
        <div class="form-group">
          <label class="control-label col-sm-3" for="dob">DOB:</label>
          <div class="col-sm-8">
         <input type="date" class="form-control" id="dob" name="dob" required>
          </div>
        </div>
        <hr />
        <div class="form-group">        
          <div class="col-sm-offset-3 col-sm-3">
         <button class="btn btn-primary btn-sm">Submit</button>
          </div>
          <div class="col-sm-3">
         <button type="reset" class="btn btn-primary btn-sm">Reset</button>
          </div>
          <div class="col-sm-3">
         <button type="button" class="btn btn-primary btn-sm close-external-modal" data-dismiss="modal">Close</button>
          </div>
        </div>
         </form>
       </div> 
        </div>
      </div>
       </div>

<div class="container"></div>
Sunny
  • 902
  • 3
  • 18
  • 41

1 Answers1

1

In createTable a distinction should be made between which of the two tables you want to populate. So you should use a selector like:

$('#' + resType + ' table')

The same distinction should be made for the prev/next button selectors:

$('#' + resType + ' .next-btn')

And it is also wrong to call both userList and adminList in the same click handler, as it will make you skip a page of results (from 0 to 20). You should call the appropriate one based one the selector. So change your prev/next click handlers to:

// Select button that is descendant of userList
$('#userList .prev-btn').click(function(){ 
    userList(currentPageNo-10);
});
$('#userList .next-btn').click(function(){ 
    userList(currentPageNo+10);
});
$('#adminList .prev-btn').click(function(){ 
    adminList(currentPageNo-10);
});
$('#adminList .next-btn').click(function(){ 
    adminList(currentPageNo+10);
});

Finally, the code will hide the next button if you change one thing on the server: let it return 11 records instead of 10. The JavaScript code can then know if after the 10 records there is still more data (without showing the 11th record).

Here is updated code:

var currentPageNo = 0; // Keep track of currently displayed page


// Select button that is descendant of userList
$('#userList .prev-btn').click(function(){ 
    userList(currentPageNo-10);
});
$('#userList .next-btn').click(function(){ 
    userList(currentPageNo+10);
});
$('#adminList .prev-btn').click(function(){ 
    adminList(currentPageNo-10);
});
$('#adminList .next-btn').click(function(){ 
    adminList(currentPageNo+10);
});

function userList(pageNo) {
    var resType="userList";
    createTable(resType,pageNo);
}

function adminList(pageNo) {
    var resType="adminList";
    createTable(resType,pageNo);
}

function createTable(resType, pageNo) {
    // Update global variable
    currentPageNo = pageNo; 
    // Set visibility of the correct "prev" button:
    $('#' + resType + ' .prev-btn').toggle(pageNo > 0);
    // Ask one record more than needed, to determine if there are more records after this page:
    $.getJSON("https://api.randomuser.me/?results=11&resType="+resType + "&pageIndex=" + pageNo, function(data) {
        var $table = $('#' + resType + ' table');
        $('tr:has(td)', $table).empty();
        // Check if there's an extra record which we do not display, 
        // but determines that there is a next page
        $('#' + resType + ' .next-btn').toggle(data.results.length > 10);
        // Slice results, so 11th record is not included:
        data.results.slice(0, 10).forEach(function (record, i) { // add second argument for numbering records
            var json = JSON.stringify(record);
            $table.append(
                $('<tr>').append(
                    $('<td>').append(
                        $('<input>').attr('type', 'checkbox')
                                    .addClass('selectRow')
                                    .val(json),
                        (i+1+pageNo) // display row number
                    ),
                    $('<td>').append(
                        $('<a>').attr('href', record.picture.thumbnail)
                                .addClass('imgurl')
                                .attr('target', '_blank')
                                .text(record.name.first)
                    ),
                    $('<td>').append(record.dob)
                )
            );
        });
        // Show the prev and/or buttons
        
        
    }).fail(function(error) {
        console.log("**********AJAX ERROR: " + error);
    });            
}

var savedData = []; // The objects as array, so to have an order.

function saveData(){
    var errors = [];
    // Add selected to map
    $('input.selectRow:checked').each(function(count) {
        // Get the JSON that is stored as value for the checkbox
        var obj = JSON.parse($(this).val());
        // See if this URL was already collected (that's easy with Set)
        if (savedData.find(record => record.picture.thumbnail === obj.picture.thumbnail)) {
            errors.push(obj.name.first);
        } else {
            // Append it
            savedData.push(obj);
        }
    });
    refreshDisplay();
    if (errors.length) {
        alert('The following were already selected:\n' + errors.join('\n'));
    }
}

function refreshDisplay() {
    $('.container').html('');
    savedData.forEach(function (obj) {
        // Reset container, and append collected data (use jQuery for appending)
        $('.container').append(
            $('<div>').addClass('parent').append(
                $('<label>').addClass('dataLabel').text('Name: '),
                obj.name.first + ' ' + obj.name.last,
                $('<br>'), // line-break between name & pic
                $('<img>').addClass('myLink').attr('src', obj.picture.thumbnail), $('<br>'),
                $('<label>').addClass('dataLabel').text('Date of birth: '),
                obj.dob, $('<br>'),
                $('<label>').addClass('dataLabel').text('Address: '), $('<br>'),
                obj.location.street, $('<br>'),
                obj.location.city + ' ' + obj.location.postcode, $('<br>'),
                obj.location.state, $('<br>'),
                $('<button>').addClass('removeMe').text('Delete'),
                $('<button>').addClass('top-btn').text('Swap with top'),
                $('<button>').addClass('down-btn').text('Swap with down')
            ) 
        );
    })
    // Clear checkboxes:
    $('.selectRow').prop('checked', false);
    handleEvents();
}

function logSavedData(){
    // Convert to JSON and log to console. You would instead post it
    // to some URL, or save it to localStorage.
    console.log(JSON.stringify(savedData, null, 2));
}

function getIndex(elem) {
    return $(elem).parent('.parent').index();
}

$(document).on('click', '.removeMe', function() {
    // Delete this from the saved Data
    savedData.splice(getIndex(this), 1);
    // And redisplay
    refreshDisplay();
});

/* Swapping the displayed articles in the result list */
$(document).on('click', ".down-btn", function() {
    var index = getIndex(this);
    // Swap in memory
    savedData.splice(index, 2, savedData[index+1], savedData[index]);
    // And redisplay
    refreshDisplay();
});

$(document).on('click', ".top-btn", function() {
    var index = getIndex(this);
    // Swap in memory
    savedData.splice(index-1, 2, savedData[index], savedData[index-1]);
    // And redisplay
    refreshDisplay();
});
    
/* Disable top & down buttons for the first and the last article respectively in the result list */
function handleEvents() {
    $(".top-btn, .down-btn").prop("disabled", false).show();
    $(".parent:first").find(".top-btn").prop("disabled", true).hide();
    $(".parent:last").find(".down-btn").prop("disabled", true).hide();
}

$(document).ready(function(){
    $('#showExtForm-btn').click(function(){
        $('#extUser').toggle();
    });
    $("#extUserForm").submit(function(e){
        addExtUser();
        return false;
   });
});

function addExtUser() {
    var extObj = {
        name: {
            title: "mr", // No ladies? :-)
            first: $("#name").val(),
            // Last name ?
        },
        dob: $("#dob").val(),
        picture: {
            thumbnail: $("#myImg").val()
        },
        location: { // maybe also ask for this info?
        }
    };
    savedData.push(extObj);
    refreshDisplay(); // Will show some undefined stuff (location...)
}
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<button class="btn btn-primary btn-sm" data-toggle="modal" data-target="#userList" onclick="userList(0)">User List</button>
<button class="btn btn-primary btn-sm" onclick="logSavedData()">Get Saved Data</button>
<button class="btn btn-primary btn-sm" data-toggle="modal" data-target="#adminList" onclick="adminList(0)">User Admin</button>
<button class="btn btn-primary btn-sm" data-toggle="modal" data-target="#extUser">Open External Form</button>

  <div class="modal fade" id="userList" role="dialog">
    <div class="modal-dialog modal-lg">
    
      
      <div class="modal-content">
        <div class="modal-header">
          <button type="button" class="close" data-dismiss="modal">&times;</button>
          <h4 class="modal-title">User List</h4>
        </div>
        <div class="modal-body">
          <div class="table-responsive">
              <table class="table table-bordered table-hover" id="datatable">
                <tr>
                    <th>Select</th>
                    <th>Name</th>
                    <th>DOB</th>
                </tr>
            </table>
          </div>
          <div class="row">
            <div class="col-sm-offset-3 col-sm-4">
                <button type="button" class="btn btn-primary prev-btn"><span class="glyphicon glyphicon-chevron-left"></span></button>
            </div>

            <div class="col-sm-4">
                <button type="button" class="btn btn-primary next-btn"><span class="glyphicon glyphicon-chevron-right"></span></button>
            </div>
        </div>
            <hr/>
        <div class="row">
            <div class="col-sm-offset-3 col-sm-4">
                <button type="button" class="btn btn-primary btn-sm" onclick="saveData()">Save selected</button>
            </div>
            <div class="col-sm-4">
                <button type="button" class="btn btn-primary btn-sm close-less-modal" data-dismiss="modal">Close</button>
            </div>
        </div>
        <br />
      </div>
    </div>
  </div>
</div>

<div class="modal fade" id="adminList" role="dialog">
    <div class="modal-dialog modal-lg">
      <div class="modal-content">
        <div class="modal-header">
          <button type="button" class="close" data-dismiss="modal">&times;</button>
          <h4 class="modal-title">Admin List</h4>
        </div>
        <div class="modal-body">
          <div class="table-responsive">
              <table class="table table-bordered table-hover" id="datatable">
                <tr>
                    <th>Select</th>
                    <th>Name</th>
                    <th>DOB</th>
                </tr>
            </table>
          </div>
          <div class="row">
            <div class="col-sm-offset-3 col-sm-4">
                <button type="button" class="btn btn-primary prev-btn"><span class="glyphicon glyphicon-chevron-left"></span></button>
            </div>

            <div class="col-sm-4">
                <button type="button" class="btn btn-primary next-btn"><span class="glyphicon glyphicon-chevron-right"></span></button>
            </div>
        </div>
            <hr/>
        <div class="row">
            <div class="col-sm-offset-3 col-sm-4">
                <button type="button" class="btn btn-primary btn-sm" onclick="saveData()">Save selected</button>
            </div>
            <div class="col-sm-4">
                <button type="button" class="btn btn-primary btn-sm close-less-modal" data-dismiss="modal">Close</button>
            </div>
        </div>
        <br />
      </div>
    </div>
  </div>
</div>

<div class="modal fade" id="extUser" role="dialog">
    <div class="modal-dialog modal-lg">
    
      <!-- External User-->
      <div class="modal-content">
        <div class="modal-header">
          <button type="button" class="close" data-dismiss="modal">&times;</button>
          <h4 class="modal-title">Add External User</h4>
        </div>
        <div class="modal-body">
          <form class="form-horizontal" id="extUserForm">
            <div class="form-group">
              <label class="control-label col-sm-3" for="name">Name:</label>
              <div class="col-sm-8">
                <input type="text" class="form-control" id="name" name="name" required>
              </div>
            </div>
            <div class="form-group">
              <label class="control-label col-sm-3" for="myImg">Image:</label>
              <div class="col-sm-8">
                <input type="text" class="form-control" id="myImg" name="myImg" required>
              </div>
            </div>
                                            
            <div class="form-group">
              <label class="control-label col-sm-3" for="dob">DOB:</label>
              <div class="col-sm-8">
                <input type="date" class="form-control" id="dob" name="dob" required>
              </div>
            </div>
            <hr />
            <div class="form-group">        
              <div class="col-sm-offset-3 col-sm-3">
                <button class="btn btn-primary btn-sm">Submit</button>
              </div>
              <div class="col-sm-3">
                <button type="reset" class="btn btn-primary btn-sm">Reset</button>
              </div>
              <div class="col-sm-3">
                <button type="button" class="btn btn-primary btn-sm close-external-modal" data-dismiss="modal">Close</button>
              </div>
            </div>
          </form>
        </div> 
      </div>
    </div>
  </div>

<div class="container"></div>
trincot
  • 317,000
  • 35
  • 244
  • 286
  • I did exactly the same, but for some reason I can't see the previous & next buttons in both the pop-ups when I use my url and JSON! Could that the problem with the pageIndex, as I mentioned in my note above? – Sunny Apr 17 '17 at 06:01
  • Also, I'm trying to update the display based on the newJSON received which has my savedData. But, it is throwing an error. Could you please take a look? Here's my question - http://stackoverflow.com/questions/43446315/saving-new-json-recieved-through-ajax-to-the-existing-array – Sunny Apr 17 '17 at 06:32
  • I think pageIndex here is different from data.results.length. – Sunny Apr 17 '17 at 06:43
  • Could you please help me with this one as well? This is the only one I'm left with! I think it is working partially for me. – Sunny Apr 17 '17 at 12:24
  • I don't know how I can help you with this, as I have provided a working snippet. Maybe you can provide a fiddle that illustrates that the buttons do not appear in your case? – trincot Apr 17 '17 at 19:34
  • I tried playing around with it and I believe it is something to do with the number of results I get from the server, as you suggested. So, I'll probably take a look into that, and try to fix this. Thanks a ton btw :) – Sunny Apr 18 '17 at 02:55
  • The table headers (Select, Name, DOB) have gone missing in the table now. How do we fix that? – Sunny Apr 18 '17 at 02:57
  • There was a missing `$` at the start of `$('tr:has(td)', $table).empty();`. Corrected. NB: You really should try to spot such errors yourself. Don't give up too soon ;-) – trincot Apr 18 '17 at 06:29
  • Hmm...yeah..I desperately need to :-)..Thank you so much! – Sunny Apr 18 '17 at 10:05
  • Hello Sir, I'd asked a question about retaining the checkbox selection on moving across pages in the modal. Could you please help me with that? http://stackoverflow.com/questions/43866259/retain-checkbox-selection-on-click-of-previous-and-next-in-the-bootstrap-modal – Sunny May 09 '17 at 10:19