-1

I am toying around with objects in javascript to get a better grasp on my ability to use functions, and manipulate objects. I have a program that 'builds' an Array of Objects. Each of those 'objects' are a persons 'firstName' 'middleName' and 'lastName'. I am trying to sort and output my array of objects alphabetically by First Name 'firstName'.

Later after I get this down, I will sort my Array by Middle Name, and then last Name.

This is ideally what the function to be: (but it isn't working) I want to get it to work in this manner, so that I can sort my array in various ways: firstName, middleName, and lastName.

function fNameS(arr, prop) {
  arr.sort(function (a, b) {
    var nameA = a.prop.toLowerCase(),
        nameB = b.prop.toLowerCase();
    if (nameA < nameB) { //sort string ascending
      return -1;
    }
    if (nameA > nameB) {
      return 1;
    }
    return 0; //default return value (no sorting)
  });
}

fNameS(allInfo, 'firstName');

This is what my code currently is using: (and its not working either)

function fNameS(arr) {
  arr.sort(function (a, b) {
    var nameA = a.firstName.toLowerCase(),
        nameB = b.firstName.toLowerCase();
    if (nameA < nameB) { //sort string ascending
      return -1;
    }
    if (nameA > nameB) {
      return 1;
    }
    return 0; //default return value (no sorting)
  });
}

Here is my JavaScript File:

var allInfo = []; //Store names (as objects) here
var output = printList('output');
var cache = [];
var numOfNames = 0;
var nameCounter = 0;
var firstNameSorted = fNameS(allInfo);
alert("JS Works");


function buildList() { //Makes a new object, and pushes it to the 'allInfo' Array
  var info = {};
  info.firstName = document.getElementById('firstName').value;
  info.middleName = document.getElementById('middleName').value;
  info.lastName = document.getElementById('lastName').value;
  allInfo.push(info);
  addName(1);
  clear();
  alert("Logged");
}


function resetList() {
  allInfo = [];
  numOfNames = 0;
  nameCounter = 0;
  addName(0);
  blankOut();
}

function blankOut() {
  document.getElementById('output').innerHTML = " ";
}


function generate(list) { //print out list function/generate list.
  var counter = 1;
  var out = '<ul>';
  var i;
  for (i in list) {
    var rec = list[i];

    var row = [];
    for (var field in rec) {
      var fieldLabel;
      if (field === 'firstName') {
        fieldLabel = "First Name";
      } else if (field === 'middleName') {
        fieldLabel = "Middle Name";
      } else if (field === 'lastName') {
        fieldLabel = "Last Name";
      }

      row.push(fieldLabel + ': ' + rec[field]);
    }

    out += "<li>" + counter + ".) " + row.join('    | - - - |    ') + "</li>";
    counter++;
  }

  out += "</ul>"
  document.getElementById('output').innerHTML = out;
  return out;
}

//First Name Sort
function fNameS(arr) {
  arr.sort(function (a, b) {
    var nameA = a.firstName.toLowerCase(),
        nameB = b.firstName.toLowerCase();
    if (nameA < nameB) { //sort string ascending
      return -1;
    }
    if (nameA > nameB) {
      return 1;
    }
    return 0; //default return value (no sorting)
  });
}


function addName(x) { //Name Counter Function
  if (x > 0) {
    nameCounter++;
    numOfNames = nameCounter;
    document.getElementById('numOfNames').innerHTML = numOfNames;
  } else {
    nameCounter = 0;
    numOfNames = 0;
    document.getElementById('numOfNames').innerHTML = numOfNames;
  }
}

function printList(x) {
  var output = getById(x);
  return function (text) {
    output.innerHTML += text + '\n';
  };
}


function getById(x) {
  return document.getElementById(x);
}


function clear() {
  document.getElementById("firstName").value = "";
  document.getElementById("middleName").value = "";
  document.getElementById("lastName").value = "";
}

Here is my HTML:

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <title>Array Name Sorting</title>
  <link rel="stylesheet" href="css/main.css">
  <script type="text/javascript" src="http://code.jquery.com/jquery-latest.js"></script>
  <script type="text/javascript" src="js/script.js"></script>
</head>

<body>
  <header>
    <h1>Array Name Sorting</h1>
    <h2>By: Jeff Ward</h2>
  </header>
  <label>First Name:
    <input type='text' name='firstName' id='firstName' placeholder="First Name">
  </label>
  <br>
  <br>
  <label>Middle Name:
    <input type='text' name='middleName' id='middleName' placeholder="Middle Name">
  </label>
  <br>
  <br>
  <label>Last Name:
    <input type='text' name='lastName' id='lastName' placeholder="Last Name">
  </label>
  <br>
  <br>
  <button type="button" id="add" onclick="buildList()">Add to List</button>
  <button type="button" id="print" onclick="generate(allInfo)">Print</button>
  <button type="button" id="clearScreen" onclick="blankOut()">Clear Screen</button>
  <button type="button" id="reset" onclick="resetList()">Reset List</button>
  <br>
  <button type="button" id="sortFirst" onclick="generate(firstNameSorted)">Sort by First Name</button>
  <button type="button" id="sortMiddle" onclick="">Sort by Middle Name</button>
  <button type="button" id="sortLast" onclick="">Sort by Last Name</button>
  <button type="button" id="pickRandom" onclick="">Pick Random Name</button>
  <br>
  <br>
  <label>Search:
    <input type='text' name='search' id='search' placeholder="Search">
  </label>
  <br>
  <br>
  <label>Number of Names in List:</label>
  <div id="numOfNames"></div>
  <br>
  <br>
  <br>
  <label>Names in list</label>
  <div id="output"></div>


</body>

</html>

What am I doing wrong in my sort function? I have tried for hours to diagnose it and cannot find out what I am doing wrong. I am a semi-noobie if you cant tell, but I am learning fast.

Link to JSFiddle: https://jsfiddle.net/jeffward01/4zrzg4a1/

This is not a duplicate because the code is not sorting. The other question (duplicate)(not by written by me) is HOW to sort. Mine is to diagnose an issue.

jward01
  • 750
  • 4
  • 11
  • 26
  • Your first function fails because you should be doing `a[prop].toLowerCase()` and `b[prop].toLowerCase()` but your second one looks fine. What exactly isn't working? – Mike Cluck Aug 06 '15 at 17:10
  • The second one isn't working either. It just doesn't 'output' anything at all. – jward01 Aug 06 '15 at 17:12
  • Check the console for errors. Your sort function is fine, something else is going wrong. – Mike Cluck Aug 06 '15 at 17:13
  • 1
    The fiddle is completely non-functional. In the HTML pane it tells you not to include ``, etc tags. When I click on the buttons I get lots of JavaScript errors. – Shadowen Aug 06 '15 at 17:21

2 Answers2

3

From what I can see at a glance:

function fNameS(arr, prop) {
  arr.sort(function (a, b) {
    var nameA = a[prop].toLowerCase(),
        nameB = b[prop].toLowerCase();
    ...

This will get the property specified by prop, rather than the property "prop".

As well, due to the nature of binding JavaScript functions to HTML elements, you need to define your functions BEFORE using them in onClick attributes. I moved all your script into a <script> tag at the top of the file and that fixed a lot of errors.

<script>
JavaScript stuff
</script>

HTML stuff

Of course, this is extremely ugly. Therefore, you might try to use JavaScript to set the onClick() attribute AFTER the functions are defined. For example, using JQuery:

var doSomething = function(){
};
$('button').click(doSomething);
Shadowen
  • 838
  • 5
  • 14
  • 1
    you missed dot before `toLowerCase` – Grundy Aug 06 '15 at 17:17
  • 1
    Fix'd. My backspace is too aggressive. – Shadowen Aug 06 '15 at 17:18
  • Would adding an event listener fix this problem as well? I am not familiar with event listeners but will learn about them. – jward01 Aug 06 '15 at 17:32
  • 1
    This is adding an event listener to the `onclick` event. Both ways are. The problem is, your listener is not defined **at the time you add it**, so you're trying to call an undefined function. – Shadowen Aug 06 '15 at 17:43
2

You should get the names using a[prop].toLowerCase() rather than a.prop.toLowerCase(). You also have to actually return the sorted array.

Here is a simplified version of your sorting function utilizing the localeCompare function:

function fNameS(arr, prop) {
    return arr.sort(function (a, b) {
        var nameA = a[prop].toLowerCase(),
            nameB = b[prop].toLowerCase();
        return nameA.localeCompare(nameB);
    });
}
dhouty
  • 1,969
  • 12
  • 21
  • I ran your code and it did 'output' something. However, the array was not sorted. I called the function like this: var firstNameSorted = fNameS(allInfo, 'firstName'); – jward01 Aug 06 '15 at 17:20
  • Here is the link to the JSFiddle (using your code), it doesn't sort :( : https://jsfiddle.net/jeffward01/q68xvczf/ – jward01 Aug 06 '15 at 17:22
  • 1
    It sorts for me, check out [this](http://jsfiddle.net/f97592x8/1/) fiddle and look at the console. – dhouty Aug 06 '15 at 17:26
  • Thank you! You have helped a ton! – jward01 Aug 06 '15 at 17:30