How do I get rid of thousands of lines

Viewed 94

To show which course a student is taking, I wrote these simple lines, click the student and see the course, but there seems to be thousands of code lines since I should list so many students and courses. Is there a way to write a single function to get the value of the object instead of writing a seperate function for each click?

//and goes on thousands of times like this...
var txt = document.getElementById("txt");  
var students = {
   student1: "english",
   student2: "maths",
   student3: "history",
   student4: "geography",
   student5: "science",
   student6: "maths",
   student7: "maths",
   student8: "history",
   student9: "french",
   student10: "geography",
};
//and there are thousands of students...

function f1(){txt.innerHTML = students.student1;};
function f2(){txt.innerHTML = students.student2;};
function f3(){txt.innerHTML = students.student3;};
function f4(){txt.innerHTML = students.student4;};
function f5(){txt.innerHTML = students.student5;};
function f6(){txt.innerHTML = students.student6;};
function f7(){txt.innerHTML = students.student7;};
function f8(){txt.innerHTML = students.student8;};
function f9(){txt.innerHTML = students.student9;};
function f10(){txt.innerHTML = students.student10;};
// so there are thousands of functions...
 <a class="k"  onClick="f1(); return false;" href="#">student1</a><br/>
 <a class="k"  onClick="f2(); return false;" href="#">student2</a><br/>
 <a class="k"  onClick="f3(); return false;" href="#">student3</a><br/>
<div id="txt"></div>

Actually I tried this, reasoning that it would work:

var stdnt = document.querySelectorAll(".k);
var x = stdnt.innerHTML;
var result = "";

if ( x === students[x] ){
    x = students[x];
}
result = x;
function forAll (){
    txt.innerHTML = result;
}

But it doesn't work at all (I guess it's natural for an absolute beginner). I badly need an idea.

3 Answers

You could condense it to use a single function and hand over innerHTML of the anchor elemenet. This string can be used as accessor for the object.

var txt = document.getElementById("txt");  
var students = {
   student1: "english",
   student2: "maths",
   student3: "history",
   student4: "geography",
   student5: "science",
   student6: "maths",
   student7: "maths",
   student8: "history",
   student9: "french",
   student10: "geography",
};

function f(key) {
    txt.innerHTML = students[key];
};
<a class="k" onClick="f(this.innerHTML); return false;" href="#">student1</a><br/>
<a class="k" onClick="f(this.innerHTML); return false;" href="#">student2</a><br/>
<a class="k" onClick="f(this.innerHTML); return false;" href="#">student3</a><br/>
<div id="txt"></div>

Have a look at this

It is using several recommended methods

  1. eventListeners
  2. DRY (Don't Repeat Yourself)
  3. delegation

const students = {
  student1: "english",
  student2: "maths",
  student3: "history",
  student4: "geography",
  student5: "science",
  student6: "maths",
  student7: "maths",
  student8: "history",
  student9: "french",
  student10: "geography",
};
// create the html so only one place to add a student
const html = Object.entries(students)
  .map(entry => `<a href="#" class="k" 
    data-student="${entry[1]}">${entry[0]}</a>`);

// on page load fill the student Div     
window.addEventListener('load', function() {
  const div = document.getElementById("studentDiv");
  const text = document.getElementById('text')
  div.innerHTML = html.join('<br/>');
  // delegate the click to the container, so only ONE event handler is used
  div.addEventListener('click', function(e) {
    const tgt = e.target;
    if (tgt.classList.contains('k')) {
      e.preventDefault(); // stop the link from executing
      text.innerHTML = tgt.dataset.student;
    }
  });
});
<div id="studentDiv"></div>
<div id="text"></div>

Simpler

const students = {
  student1: "english",
  student2: "maths",
  student3: "history",
  student4: "geography",
  student5: "science",
  student6: "maths",
  student7: "maths",
  student8: "history",
  student9: "french",
  student10: "geography",
};
// create the html so only one place to add a student
const html = Object.entries(students)
  .map(entry => `<a href="#" class="k">${entry[0]}</a>`);

// on page load fill the student Div     
window.addEventListener('load', function() {
  const div = document.getElementById("studentDiv");
  const text = document.getElementById('text')
  div.innerHTML = html.join('<br/>');
  // delegate the click to the container, so only ONE event handler is used
  div.addEventListener('click', function(e) {
    const tgt = e.target;
    if (tgt.classList.contains('k')) {
      e.preventDefault(); // stop the link from executing
      text.innerHTML = students[tgt.textContent]
    }
  });
});
<div id="studentDiv"></div>
<div id="text"></div>

You can make this in one function and maintaining the html for example, one to handle the id of the course:

<a class="k"  onClick="getCourse(“student1”); return false;" href="#">student1</a><br/>


function getCourse(student) { // Contains the student
   txt.innerHTML = students[student];
 }
Related