Reputation: 13
Im new to JavaScript, I'm using vanilla js , html and css to survey website where user can add question, and option as well, when they click a button it will create a container which they can fill with the 'tag:textarea'. I'm using the 'createElement()', 'setAttribute()' method for creating a new container. But since each container has so many nested nodes or components, I have write a tons of boilerplate code to create a container, plus I have to change the id of some element with the nested 'Hell' , It become so hard to managed. My html code is Below:
<div id="create-question-container-id" class="create-question-container" >
<div id="create-question-textarea-container-id_0" class="create-question-textarea-container">
<textarea id="create-question-textarea-id"
name="textareaquestion" class="create-question-textarea"
cols="50" row="1" style="font-size: 20pt;">
Untitled Question
</textarea>
<div id="create-answer-textarea-container-id-0" class="create-answer-textarea-container">
<div id="create-answer-N-container-id-0-0" class="create-answer-N-container">
<div class="create-qeuestion-radio-outer-circle" >
<div class="create-qeuestion-radio-innner-circle"></div>
</div>
<textarea id="opt1" name="textareaopt" class="create-answer-textarea"
placeholder="opt1" style="font-size: 14pt;">
</textarea>
</div>
</div>
<button onclick="addOption()" class="create-add-answer-btn" >
Add Option
</button>
</div>
</div>
<div class="create-main-container-submit-button">
<button onclick="clonecontainer()" class="create-main-submit-btn" >
Submit
</button>
</div>
And this is the Javascript Code from hell:
var answer_container = document.getElementsByClassName('create-answer-textarea-container');
//increment this one
var answer_container_id = document.getElementById('create-answer-textarea-container-id-0');
var lastChildAnswer = answer_container[answer_container.length - 1];
var asnwer_container_list = answer_container_id.childNodes[answer_container.length];
//id of container wrapping around the question and the options named questionasnwcontain(this need to increment id)
var question_answer_container_list = document.getElementById('create-question-textarea-container-id_0')
//id of container wrapping around the questionasnwcontain(main container)
var all_question_asnwer_container = document.getElementById('create-question-container-id');
var all_question_asnwer_container_class_Name = document.getElementsByClassName('create-question-container');
var all_counter = all_question_asnwer_container.childElementCount -1;
function clonecontainer() {
var dashed_delimeter = '-';
var lastChildContainer = answer_container_id.lastElementChild.getAttribute('id')
var trimlastChild = answer_container_id.lastElementChild.lastElementChild.getAttribute('id')
var delimeter = 't'
var trimlastChildSubString = trimlastChild.split(delimeter);
var lastChildString = trimlastChildSubString[1]
//split lastChildContainer
var splitted_lastChildContainer = lastChildContainer.split(dashed_delimeter)[5];
var new_id_spliited_lastChildContainer = 'create-answer-N-container-id-' + ((parseInt(splitted_lastChildContainer)) + (all_question_asnwer_container.childElementCount -1) ) + '-0';
//get the cloned container's child id for incremental
var last_main_container_child = all_question_asnwer_container.lastElementChild.getAttribute('id');
var trimlast_id = seperateWithDelimeter(last_main_container_child);
var trimlast_new_id ='_' + (parseInt(trimlast_id[1]) + (all_question_asnwer_container.childElementCount -1) );
console.log(trimlast_new_id)
//(fixed)
var last_cloned_delimeter = '_';
var last_cloned_container = all_question_asnwer_container.childNodes[all_question_asnwer_container_class_Name.length].getAttribute('id')
var splitted_cloned_container = last_cloned_container.split(last_cloned_delimeter);
var new_splitted_cloned_container_id = 'create-answer-textarea-container-id-' + ((parseInt(splitted_cloned_container[1])) + (all_question_asnwer_container.childElementCount )) ;
console.log(new_splitted_cloned_container_id)
//new div fr asnwer container
var new_div_fr_answer_container_id = document.createElement('div');
new_div_fr_answer_container_id.setAttribute('class' , 'create-question-textarea-container');
new_div_fr_answer_container_id.setAttribute('id' ,'create-question-textarea-container-id' + trimlast_new_id)
console.log(new_div_fr_answer_container_id)
//new question text area
var new_textarea_fr_create_question_textarea_id = document.createElement('textarea');
new_textarea_fr_create_question_textarea_id.setAttribute('class' , 'create-question-textarea');
new_textarea_fr_create_question_textarea_id.setAttribute('id' , 'create-question-textarea-id')
new_textarea_fr_create_question_textarea_id.setAttribute('cols' , 50);
new_textarea_fr_create_question_textarea_id.setAttribute('row' , 1);
new_textarea_fr_create_question_textarea_id.style.fontSize = '20pt';
//new for option text area wrrapeer
var new_option_text_area_wrapper = document.createElement('div');
new_option_text_area_wrapper.setAttribute('class' , 'create-answer-textarea-container');
new_option_text_area_wrapper.setAttribute('id' , new_splitted_cloned_container_id);
var new_option_N_text_area_wrapper = document.createElement('div');
new_option_N_text_area_wrapper.setAttribute('class' , 'create-answer-N-container');
new_option_N_text_area_wrapper.setAttribute('id', new_id_spliited_lastChildContainer);
var new_checkbox_inner = document.createElement('div');
new_checkbox_inner.setAttribute('class' , 'create-qeuestion-radio-inner-circle');
//create Element for checkBox outerCircle
var new_checkbox = document.createElement('div');
new_checkbox.setAttribute('class' , 'create-qeuestion-radio-outer-circle');
//append innerCircle
new_checkbox.appendChild(new_checkbox_inner);
var new_answer = document.createElement('textarea');
new_answer.setAttribute('name' , 'textareaopt');
new_answer.setAttribute('id' , 'opt'+ (parseInt(lastChildString) + 1));
new_answer.setAttribute('class' , 'create-answer-textarea');
new_answer.setAttribute('placeholder' , 'opt'+ (parseInt(lastChildString) + 1))
new_answer.style.fontSize = "14pt";
new_option_N_text_area_wrapper.appendChild(new_checkbox);
new_option_N_text_area_wrapper.appendChild(new_answer);
new_option_text_area_wrapper.appendChild(new_option_N_text_area_wrapper);
new_div_fr_answer_container_id.appendChild(new_textarea_fr_create_question_textarea_id);
new_div_fr_answer_container_id.appendChild(new_option_text_area_wrapper);
all_question_asnwer_container.appendChild(new_div_fr_answer_container_id);
}
All of them are just the repetitive methods. So my question is, is there a more efficient way of doing this or is there like a class that I can use to make it more manageable.
Upvotes: 1
Views: 74
Reputation: 22355
const
btAdd = document.querySelector('button#bt-add')
, container = document.querySelector('div#container')
, builder =
{ ref_id : 0
, newDiv()
{
let sub_id = 0
, div = document.createElement('div')
;
div.id = ++this.ref_id
div.innerHTML = `
<div id="bla-bla-id_${this.ref_id}" class="xxzw">
<em> text areas: </em><br>
<textarea id="opt${this.ref_id}-${++sub_id}" placeholder="txt-area ${this.ref_id}-${sub_id} "></textarea><br>
<textarea id="opt${this.ref_id}-${++sub_id}" placeholder="txt-area ${this.ref_id}-${sub_id} "></textarea>
</div>`
container.appendChild(div)
}
}
btAdd.onclick = e =>
{
builder.newDiv()
}
div#container {
margin : 1em;
width : 20em;
}
div#container > div {
margin : .8em 0;
padding : .2em;
border : 1px solid lightblue;
}
em {
font-size : .7em;
font-weight : bold;
}
textarea {
width : 90%;
}
<button id="bt-add">add</button>
<div id="container"> </div>
Upvotes: 0
Reputation: 1075129
You have several options, two of which are:
If you don't mind parsing HTML each time (and parsing HTML is really fast on modern browser), you can use insertAdjacentHTML
instead, perhaps with a template literal so you can embed newlines easily and use ${x}
syntax for embedded values:
all_question_asnwer_container.insertAdjacentHTML("beforeend", `<div>
(etc.)
</div>`);
You can use a template
element in your HTML that you clone (via cloneNode
) as needed. Here's the cloning part of MDN's example from the linked page
var tbody = document.querySelector("tbody");
var template = document.querySelector('#productrow'); // The template element
// Clone the new row and insert it into the table
var clone = template.content.cloneNode(true);
var td = clone.querySelectorAll("td");
td[0].textContent = "1235646565";
td[1].textContent = "Stuff";
tbody.appendChild(clone);
Upvotes: 1