How can I select the current div with Javascript

Viewed 74

I have code to imitate a survey. Basically there are questions and some options under them. What I tried to do is something "object-oriented" let's say.

So I am grouping every question and there under each question I can add many options but all options should belong to their question.

A question would have a questionName and a list of options. I have implemented the grouping of the questions but I don't know how to exactly choose the current question so that when the user is adding options, they would be added to the last question let's say.

This is my code:

newQuestion()

function newQuestion() {
  // Create a variable which is basically the questionaire from the html
  var questionaire = document.getElementById('questionaire');

  /* HERE I AM CREATING A DIV WHICH WILL BE REPRESENTING EACH QUESTION */
  // Create a variable which is a new div to be the question
  const question = document.createElement('div');
  // add classname and put it as a child of questionaire
  question.classList.add("question");
  questionaire.append(question);

  /* HERE I AM CREATING A DIV WHICH WILL BE REPRESENTING THE QUESTION NAME */
  // Create a variable which is a new div to be the question name
  const qname = document.createElement('div');
  // add a classname, make it editable and set the text to be shown
  qname.classList.add("qName");
  qname.innerHTML = '<div contenteditable="true">Your Question</div>';
  // put qName as a child of question
  question.appendChild(qname);
  // add a new option and pass as parameter the question
  newOption(question)
}


function newOption(father) {
  /* IF THERE IS AN ARGUMENT, father is the question where this option will belong */

  // else you need to get the question from the html
  if (arguments.length == 0) {
    // select current question

    /* PROBLEM IS HERE BUT DON'T KNOW HOW TO FIX*/

    var father = document.getElementsByClassName('question')[0];
  }

  // Create a variable which is a new div to be an option
  const op = document.createElement('div');
  // add a classname, make it editable and set the text to be shown
  op.classList.add("option");
  op.innerHTML = '<div> <ul id="optionList"> <li class="optionName" contenteditable="true">Option <li class="box">  <input type="checkbox"> </li> </ul> </div>';
  // put option as a child of question
  father.appendChild(op);
}
body {
  background-color : #00ffaa;
  }
#myText {
  margin-top       : 15px;
  font-family      : 'Gill Sans', 'Gill Sans MT', Calibri, 'Trebuchet MS', sans-serif;
  text-align       : center;
  }
.question {
  border           : 3px solid black;
  border-radius    : 25px;
  margin           : 30px 200px 20px 200px;
  }
.qName {  
  color            : rgb(86, 17, 150);
  margin-top       : 10px;
  font-size        : 25px;
  text-align       : center;
  }
.optionname {
  margin-left      : -50px;
  }
.box {
  margin-left      : 90px;
  }
.option {
  display          : table;
  margin-left      : auto;
  margin-right     : auto;
  margin-top       : 10px;   
  }
ul#optionList li {
  display          : inline;
  }
.optionName {
  font-size        : 19px;
  font-style       : oblique;
}
<h1 id="myText" contenteditable="true">Survey Name</h1>

<button type="button" id="addQuButton" onclick="newQuestion()">
  Add Question
</button>
<button type="button" id="addOpButton" onclick="newOption()">
  Add Option
</button>

<form>
  <div id="questionaire"></div>
</form>

HTML CODE: (just the basic structure of the survey)
JAVASCRIPT CODE: (here's is most of the work where I have 2 functions to add the questions and options)
CSS CODE: (here's just for styling)

If anyone knows how to help with this code or you think an other approach would be better it would be highly appreciated. Thank you.

2 Answers

I ended up changing more than originally intended. There were multiple ids and deep nested <div><div><ul><li><li> ... structures that resultet in many case in invalid html. For this reason I simplified both your markup and your JavaScript code. I also took the liberty of creating multiple "Add Option" buttons (one for each question). The page is by far not ready yet but I hope it can be a pointer of where to go ...

const questionnaire=document.getElementById('questionaire');
newQuestion();

function newQuestion() {
 questionnaire.insertAdjacentHTML('beforeend',
  `<div class="question">
    <div contenteditable="true">Your Question</div>
    <ul></ul>
    <button type="button">Add Option</button>
   </div>`);
  newOption(questionnaire.querySelector("div.question:last-child ul"));
}

function newOption(q) {
  q.insertAdjacentHTML('beforeend',
   `<li class="optionName">
      <span contenteditable="true">Option</span>
      <input type="checkbox">
     </li>`);
}

questionnaire.onclick=ev=>{
 if (ev.target.tagName==="BUTTON") newOption( ev.target.closest(".question").querySelector('ul') )
}
document.getElementById("addQuButton").onclick=newQuestion
body {
  background-color : #ccc;
  }
#myText {
  margin-top       : 15px;
  font-family      : 'Gill Sans', 'Gill Sans MT', Calibri, 'Trebuchet MS', sans-serif;
  text-align       : center;
  }
.question {
  border           : 3px solid black;
  border-radius    : 25px;
  margin           : 30px 200px 20px 200px;
  text-align       : center;
  }

.question ul li {
  display          : block;
  }
<h1 id="myText" contenteditable="true">Survey Name</h1>
<button type="button" id="addQuButton">Add Question</button>
<form> <div id="questionaire"></div> </form>

Please check the newly added line and modified line in newOption(father) function

newQuestion()

function newQuestion() {
  // Create a variable which is basically the questionaire from the html
  var questionaire = document.getElementById('questionaire');

  /* HERE I AM CREATING A DIV WHICH WILL BE REPRESENTING EACH QUESTION */
  // Create a variable which is a new div to be the question
  const question = document.createElement('div');
  // add classname and put it as a child of questionaire
  question.classList.add("question");
  questionaire.append(question);

  /* HERE I AM CREATING A DIV WHICH WILL BE REPRESENTING THE QUESTION NAME */
  // Create a variable which is a new div to be the question name
  const qname = document.createElement('div');
  // add a classname, make it editable and set the text to be shown
  qname.classList.add("qName");
  qname.innerHTML = '<div contenteditable="true">Your Question</div>';
  // put qName as a child of question
  question.appendChild(qname);
  // add a new option and pass as parameter the question
  newOption(question)
}


function newOption(father) {
  /* IF THERE IS AN ARGUMENT, father is the question where this option will belong */

  // else you need to get the question from the html
  if (arguments.length == 0) {
    // select current question

    /* PROBLEM IS HERE BUT DON'T KNOW HOW TO FIX*/

var fatherlen = document.getElementsByClassName('question').length;//newly added one
    var father = document.getElementsByClassName('question')[fatherlen-1];//modified
  }

  // Create a variable which is a new div to be an option
  const op = document.createElement('div');
  // add a classname, make it editable and set the text to be shown
  op.classList.add("option");
  op.innerHTML = '<div> <ul id="optionList"> <li class="optionName" contenteditable="true">Option <li class="box">  <input type="checkbox"> </li> </ul> </div>';
  // put option as a child of question
  father.appendChild(op);
}
body {
  background-color : #00ffaa;
  }
#myText {
  margin-top       : 15px;
  font-family      : 'Gill Sans', 'Gill Sans MT', Calibri, 'Trebuchet MS', sans-serif;
  text-align       : center;
  }
.question {
  border           : 3px solid black;
  border-radius    : 25px;
  margin           : 30px 200px 20px 200px;
  }
.qName {  
  color            : rgb(86, 17, 150);
  margin-top       : 10px;
  font-size        : 25px;
  text-align       : center;
  }
.optionname {
  margin-left      : -50px;
  }
.box {
  margin-left      : 90px;
  }
.option {
  display          : table;
  margin-left      : auto;
  margin-right     : auto;
  margin-top       : 10px;   
  }
ul#optionList li {
  display          : inline;
  }
.optionName {
  font-size        : 19px;
  font-style       : oblique;
}
<h1 id="myText" contenteditable="true">Survey Name</h1>

<button type="button" id="addQuButton" onclick="newQuestion()">
  Add Question
</button>
<button type="button" id="addOpButton" onclick="newOption()">
  Add Option
</button>

<form>
  <div id="questionaire"></div>
</form>

Related