I have a function which dynamically adds div, what i need is a button inside, which deletes this div. Eg: on click of a button, a div is added, with a button inside. On click of that button, the div is removed. Here's my code for addition of divs:
function newTextQuestion() {
var div = document.createElement('div');
div.style.borderLeft = "3px solid #00897b";
div.style.marginBottom = "20px";
div.style.paddingLeft = "10px";
div.style.backgroundColor = "white";
div.className = 'q';
div.setAttribute('data-type', '0');
var name = "random-" + parseInt(Math.random() * 1000000000);
div.innerHTML = '<h5>Tekstiküsimus:</h5><input class="text" name="' + name + '" type="text" placeholder="Küsimuse tekst..." oninvalid="this.setCustomValidity(\'\See väli on kohustuslik!\'\)" oninput="setCustomValidity(\'\'\)" required>';
document.getElementById('questionnaireDiv').appendChild(div);
}
--- EDIT ---
What i've tried so far:
function newTextQuestion() {
var div = document.createElement('div');
div.style.borderLeft = "3px solid #00897b";
div.style.marginBottom = "20px";
div.style.paddingLeft = "10px";
div.style.backgroundColor = "white";
var delbutton = document.createElement('button');
var delbuttontext = document.createElement('X');
delbutton.appendChild(delbuttontext);
delbutton.setAttribute("onclick", function() { $(this).parent().remove(); });
div.appendChild(delbutton);
div.className = 'q';
div.setAttribute('data-type', '0');
var name = "random-" + parseInt(Math.random() * 1000000000);
div.innerHTML = '<h5>Tekstiküsimus:</h5><input class="text" name="' + name + '" type="text" placeholder="Küsimuse tekst..." oninvalid="this.setCustomValidity(\'\See väli on kohustuslik!\'\)" oninput="setCustomValidity(\'\'\)" required>';
document.getElementById('questionnaireDiv').appendChild(div);
}
When you need event handling capabilities, don't create an element via .innerHTML, use the document.createElement() technique. To create the button, just follow the same technique that you had already started.
Also, it's best to work with CSS classes when you can instead of setting individual properties.
var parent = document.getElementById('questionnaireDiv');
function newTextQuestion() {
var div = document.createElement('div');
div.classList.add("newDiv");
div.classList.add("q");
div.setAttribute('data-type', '0');
var name = "random-" + parseInt(Math.random() * 1000000000);
var h5 = document.createElement("h5");
var input = document.createElement("input");
input.type = "text";
input.classList.add("text");
input.placeholder = "Küsimuse tekst...";
input.required = true;
input.addEventListener("invalid", function(){
this.setCustomValidity("\'See väli on kohustuslik!\'");
});
input.addEventListener("input", function(){
this.setCustomValidity("");
});
var btn = document.createElement("button");
btn.textContent = "Delete";
div.appendChild(h5);
div.appendChild(input);
div.appendChild(btn);
btn.addEventListener("click", function(){
parent.removeChild(div);
});
parent.appendChild(div);
}
newTextQuestion();
.newDiv {
border-left: 3px solid #00897b;
margin-bottom: 20px;
padding-left: 10px;
background-color:"white";
}
<div id="questionnaireDiv"></div>
Related
I Have a form that includes a label, slider and an output.
Different sizes of labels can mess the vertical organization of the slider (like in the link below).
dist
This is my code:
function slider(name,item){
var label=document.createElement("label");
label.innerHTML = name+" rate for "+item;
var form=document.createElement("form");
form.name="registrationForm";
form.className ="mainForm";
var input = document.createElement("input");
input.type="range";
input.name="ageInputName";
input.id="input"+name+item;
input.value="50";
input.min="0";
var output = document.createElement("output");
output.name="ageOutputName";
output.id="output"+name+item;
input.oninput=()=>updateTextInput(input.id,output.id);
form.appendChild(label);
form.appendChild(input);
form.appendChild(output);
output.value="50";
document.getElementById("container").appendChild(form);
}
How can I fix this?
You can use css classes with attributes width and display:inline-block to achieve what you are looking for. Example
In your javascript you can use input.classList.add('input');
HTML
.label {
width:150px;
background:#f7f7f7;
display:inline-block;
text-align:center;
}
.input {
width:200px;
display:inline-block;
}
.output {
width:50px;
background:#d7d7d7;
display:inline-block;
}
-- if it has to be done in js you can always add styles in js to your elements
JS
slider('first', 'bag');
slider('second', 'box');
slider('third', 'floor');
function slider(name, item) {
var label = document.createElement("label");
label.innerHTML = name + " rate for " + item;
label.classList.add("label");
var form = document.createElement("form");
form.name = "registrationForm";
form.className = "mainForm";
var input = document.createElement("input");
input.type = "range";
input.name = "ageInputName";
input.id = "input" + name + item;
input.value = "50";
input.min = "0";
input.classList.add('input');
var output = document.createElement("output");
output.name = "ageOutputName";
output.id = "output" + name + item;
output.classList.add('output');
input.oninput = () => updateTextInput(input.id, output.id);
form.appendChild(label);
form.appendChild(input);
form.appendChild(output);
output.value = "50";
document.getElementById("container").appendChild(form);
}
For a slightly more advanced method you could learn about css grid and flexbox.
I have the following code:
JS :
i.addEventListener("click", function () {
var br1 = document.createElement("br");
var div1 = document.createElement("div");
div1.className = "input-group";
var ipt1 = document.createElement("input");
ipt1.type = "text";
ipt1.className = "form-control";
var span = document.createElement("span");
span.className = "input-group-addon";
var ipt2 = document.createElement("input");
ipt2.type = "text";
ipt2.className = "form-control";
div1.appendChild(ipt1);
div1.appendChild(span);
div1.appendChild(ipt2);
divdiv.appendChild(div1);
divdiv.appendChild(br1);
});
document.getElementById('modal2body').appendChild(divdiv);
However, when there are multiple <i>s, the divdiv is appended to the last one.
This is all in a for loop, which adds an <i> for each element in a list.
The list might look like ['customers','employees','managers','night-shifts']
There needs to be an option to add the input-group to each one of these. (the i is a FontAwesome 'plus' icon).
The problem I have, is that clicking any of the icons, it will add the input-group to the night-shift list.
I thought I might need to use dynamic variables to fix this.
If it happens that this is the most effective solution, how can I achieve this?
Or is there a better way to do this ?
Screenshot :
In this screenshot, I clicked the + to the right of Customers
This code creates the original 4 input-groups (1 for each section) :
var divdiv = document.createElement('div');
divdiv.id = 'd' + d;
var div1 = document.createElement('div')
div1.className = 'input-group';
var ipt1 = document.createElement('input');
ipt1.type = 'text';
ipt1.className = 'form-control'
var span = document.createElement('span');
span.className = 'input-group-addon';
var ipt2 = document.createElement('input');
ipt2.type = 'text';
ipt2.className = 'form-control'
var div2 = document.createElement('div');
var t = document.createElement('t');
t.className = 'helv-b grey'
t.style.fontSize = '15px';
t.textContent = inputstext[d];
div2.appendChild(t);
var i = document.createElement('i');
i.className = 'fa fa-plus';
i.style.float = 'right'
i.style.fontSize = '20px';
i.style.marginTop= '5px'
i.onmouseenter = i.style.opacity = "60%";
i.onmouseleave = i.style.opacity = "100%";
div2.appendChild(i);
var br1 = document.createElement('br');
var br2 = document.createElement('br');
divdiv.appendChild(div2);
divdiv.appendChild(br1);
div1.appendChild(ipt1);
div1.appendChild(span);
div1.appendChild(ipt2);
divdiv.appendChild(div1);
divdiv.appendChild(br2);
divdiv.id = 'f' + d;
(inputstext = ['Customers','Employees','Managers','Night-Shifts'])
HTML :
<div class="modal-body" id="modal2body">
</div>
###Update
Screenshots :
I can't figure out how to fix these alignment issues and make them look like my original screenshot.
Also, how do I have 1 input-group already displayed for each section ?
The problem is that the code which adds is event-driven, which means that it will run when the user clicks the add icon. So when the add icon is click the value of divdiv will be the last element of array "Night-Shifts".
Here is a way of doing it using arrays.
var inputstext = ['customers', 'employees', 'managers', 'night-shifts']
var divdivArray = [];
var mainDiv = document.getElementById("modal2body");
for (var d = 0; d < inputstext.length; d++) {
var divdiv = document.createElement('div');
divdiv.id = 'd' + d;
var div1 = document.createElement('div')
div1.className = 'input-group';
var ipt1 = document.createElement('input');
ipt1.type = 'text';
ipt1.className = 'form-control'
var span = document.createElement('span');
span.className = 'input-group-addon';
var ipt2 = document.createElement('input');
ipt2.type = 'text';
ipt2.className = 'form-control'
var div2 = document.createElement('div');
var t = document.createElement('t');
t.className = 'helv-b grey'
t.style.fontSize = '15px';
t.textContent = inputstext[d];
div2.appendChild(t);
var i = document.createElement('i');
i.className = 'fa fa-plus';
i.style.float = 'right'
i.style.fontSize = '20px';
i.style.marginTop = '5px'
i.onmouseenter = i.style.opacity = "60%";
i.onmouseleave = i.style.opacity = "100%";
i.setAttribute("index", d)
div2.appendChild(i);
var br1 = document.createElement('br');
var br2 = document.createElement('br');
divdiv.appendChild(div2);
divdiv.appendChild(br1);
div1.appendChild(ipt1);
div1.appendChild(span);
div1.appendChild(ipt2);
divdiv.appendChild(div1);
divdiv.appendChild(br2);
divdiv.id = 'f' + d;
mainDiv.appendChild(divdiv)
divdivArray.push(divdiv);
i.addEventListener("click", function() {
var br1 = document.createElement("br");
var div1 = document.createElement("div");
div1.className = "input-group";
var ipt1 = document.createElement("input");
ipt1.type = "text";
ipt1.className = "form-control";
var span = document.createElement("span");
span.className = "input-group-addon";
var ipt2 = document.createElement("input");
ipt2.type = "text";
ipt2.className = "form-control";
div1.appendChild(ipt1);
div1.appendChild(span);
div1.appendChild(ipt2);
var index = this.getAttribute("index");
divdivArray[index].appendChild(div1);
divdivArray[index].appendChild(br1);
});
}
<html>
<head>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css">
</head>
<div class="modal-body" id="modal2body" style="display: inline-block;">
</div>
<html>
Here I save every divdiv inside the array. And also add an index attribute to the <i> element so when it is clicked you can know which divdiv you want to edit.
I Have created a modal inside the listview having input fields and select element. This list is shown up in webview of android. When I am clicking the input field, I am able to change the value inside it but when I am clicking the select field nothing happens even though I have the data inside that select list and even it is focussed by click listener. Can anyone please help me with it?
I am sharing the sample code:-
var modalInList = function(){
var originalList = document.getElementsByClassName("tt-menu");
var divElement = document.createElement("div")
divElement.id = "divToAdd";
var listElement = document.createElement("li");
listElement.id = "listToAdd";
var inputFieldForDose = document.createElement("input");
var inputFieldForFrequency = document.createElement("select");
var inputFieldForDays = document.createElement("input");
var take = document.createElement("span");
var tablet = document.createElement("span");
var forData = document.createElement("span");
var days = document.createElement("span");
take.innerHTML = "Take"
tablet.innerHTML = "Tablet"
forData.innerHTML = "for"
days.innerHTML = "Days"
divElement.appendChild(take);
inputFieldForDose.id = "doseList";
inputFieldForFrequency.id = "frequencyList";
inputFieldForDays.id = "daysList";
inputFieldForDose.contentEditable = 'true'
inputFieldForFrequency.contentEditable = 'true'
inputFieldForDays.contentEditable = 'true'
inputFieldForDose.style.color = "black";
inputFieldForDose.style.width = "45px";
inputFieldForDose.style.marginLeft = "1px";
inputFieldForDose.style.marginRight = "1px";
inputFieldForDose.style.textAlign = "center";
inputFieldForDose.style.padding = "1px";
inputFieldForDose.style.border = "solid 1px #c9c9c9";
inputFieldForFrequency.style.color = "black";
inputFieldForFrequency.style.width = "auto";
inputFieldForFrequency.style.marginLeft = "1px";
inputFieldForFrequency.style.marginRight = "1px";
inputFieldForFrequency.style.padding = "1px";
inputFieldForFrequency.style.border = "solid 1px #c9c9c9";
inputFieldForDays.style.color = "black";
inputFieldForDays.style.width = "45px";
inputFieldForDays.style.marginLeft = "1px";
inputFieldForDays.style.marginRight = "1px";
inputFieldForDays.style.marginTop = "2px";
inputFieldForDays.style.textAlign = "center";
inputFieldForDays.style.padding = "1px";
inputFieldForDays.style.border = "solid 1px #c9c9c9";
inputFieldForDose.setAttribute('type', 'number');
inputFieldForDays.setAttribute('type', 'number');
if (inputFieldForFrequency.selectedIndex == -1) {
var start = '';
var len = prescriptionFrequenciesData.length;
for (var i = 0; i < len; i++) {
start += '<option value="' + prescriptionFrequenciesData[i].value + '">' + prescriptionFrequenciesData[i].title;
}
inputFieldForFrequency.innerHTML = start;
}
inputFieldForFrequency.required = true;
divElement.appendChild(inputFieldForDose);
divElement.appendChild(tablet);
divElement.appendChild(inputFieldForFrequency);
divElement.appendChild(forData);
divElement.appendChild(inputFieldForDays);
divElement.appendChild(days);
listElement.appendChild(divElement);
originalList[0].prepend(listElement);
inputFieldForDose.addEventListener('click', function(){
editFieldCheck = true;
console.log("clicked");
inputFieldForDose.focus();
$(".tt-menu").show();
inputFieldForDose.focus();
})
inputFieldForFrequency.addEventListener('click', function(){
editFieldCheck = true;
console.log("clicked");
inputFieldForFrequency.focus();
$(".tt-menu").show();
inputFieldForFrequency.focus();
})
inputFieldForDays.addEventListener('click', function(){
editFieldCheck = true;
console.log("clicked");
inputFieldForDays.focus();
$(".tt-menu").show();
inputFieldForDays.focus();
})
}
Here inputFieldForDays is the element for element. and $(".tt-menu") is used for bloodhound.js list
I want to build dynamically a div element in the DataList, in item template, by javascript.
I thought about building a panel and then using panel.appendChild(div), but I have no idea how to get it.
Is it possible to do it in javascript? Is it ever right to call the controls in datalist 'children'?
If yes, I would be happy for some help.
var but2 = document.getElementById("Button2");
var dl = document.getElementById("DataList1");
var p = dl.children[0];
but2.onclick = function CopyDiv() {
var iDiv = document.createElement('div');
iDiv.style.width = "200px";
iDiv.style.height = "200px";
iDiv.style.position = "absolute";
iDiv.style.top = "10px";
iDiv.style.left = "10px";
iDiv.style.border = '1px solid black';
p.appendChild(iDiv);
}
this is the wrong code, I guess because I didn't have any reference to the ItemTemplate.
i see one problem in your code first if DataList is a div and btn is a button do this :
<input type="button" id="Button2" onclick="CopyDiv()" val="append" />
<script type="text/javascript">
var dl = document.getElementById("DataList1");
var p = dl.children[0];
function CopyDiv() {
var iDiv = document.createElement('div');
iDiv.style.width = "200px";
iDiv.style.height = "200px";
iDiv.style.position = "absolute";
iDiv.style.top = "10px";
iDiv.style.left = "10px";
iDiv.style.border = '1px solid black';
p.appendChild(iDiv);
}
</script>
I have the following code:
window.onload = function createDivs() {
for(var i = 1;i<29;i++) {
var div = document.createElement("div");
var body = document.getElementsByTagName("body")[0];
var n1 = document.createTextNode("Cell " + i);
var n2 = document.createTextNode(i + " Cell");
div.style.width = "100px";
div.style.height = "100px";
div.style.border = "1px solid red";
div.style.cssFloat = "left";
div.style.margin = "1px"
div.className = i;
body.appendChild(div);
}
div.onmouseover = function() {
this.appendChild(n1);
},
div.onmouseout = function() {
this.appendChild(n2);
}
}
what I want to acheive
on mouseover of each div, the div should have a text of cell 1, cell 2, ..... upto cel 28. But I am just getting Cell 28 on hover for each cell.
2. I also want to achieve that onmouseout, the cell should have "1 cell" as text, but its not working.
Any help is appreciated.
http://jsbin.com/iXuLEDE/7/edit?html,output
Your problem is coming from your closure over n1 and n2. The simplest solution to that is the following.
From this:
div.onmouseover = function() {
this.appendChild(n1);
}
To this:
div.onmouseover = (function(text) {
return function () {
this.innerHTML = text;
}
}(n1.textContent));
This way you are using a copy of the text node (by using it as a parameter to a function) rather than as a closure later on.
UPDATE
Just read the second part of your question, this should work:
div.onmouseover = (function(text) {
return function() {
this.innerHTML = text;
};
}("Cell " + i));
div.onmouseout = (function(text) {
return function() {
this.innerHTML = text;
};
}(i + " Cell"));
USING TEXT NODES
function createDivs() {
for(var i = 1;i<29;i++) {
var div = document.createElement("div");
var body = document.getElementsByTagName("body")[0];
div.style.width = "100px";
div.style.height = "100px";
div.style.border = "1px solid red";
div.style.cssFloat = "left";
div.style.margin = "1px"
div.className = i;
var n1 = document.createTextNode("Cell " + i);
var n2 = document.createTextNode(i + " Cell");
body.appendChild(div);
div.onmouseover = (function(n_text1, n_text2) {
return function() {
if (n_text2.parentNode == this) {
this.removeChild(n_text2);
}
this.appendChild(n_text1);
};
}(n1, n2));
div.onmouseout = (function(n_text1, n_text2) {
return function() {
if (n_text1.parentNode == this) {
this.removeChild(n_text1);
}
this.appendChild(n_text2);
};
}(n1, n2));
}
}
Fiddle here: http://jsfiddle.net/Mk5e5/
Please change the code like this
window.onload = function createDivs() {
for(var i = 1;i<29;i++) {
var div = document.createElement("div");
div.setAttribute("index", i);
var body = document.getElementsByTagName("body")[0];
div.style.width = "100px";
div.style.height = "100px";
div.style.border = "1px solid red";
div.style.cssFloat = "left";
div.style.margin = "1px"
div.className = i;
body.appendChild(div);
div.onmouseover = function() {
var n1 = document.createTextNode("Cell " + this.getAttribute("index"));
this.appendChild(n1);
} ,
div.onmouseout = function() {
var n2 = document.createTextNode(this.getAttribute("index") + " Cell");
this.appendChild(n2);
}
}
}
You should add event for each div in loop
Try to understand javascript closures, specially inside for loops. Check this excellent explanation in this blog post: http://www.mennovanslooten.nl/blog/post/62
Change your createDivs function to:
function createDivs() {
for(var i = 1;i<29;i++) {
var div = document.createElement("div");
var body = document.getElementsByTagName("body")[0];
div.style.width = "100px";
div.style.height = "100px";
div.style.border = "1px solid red";
div.style.cssFloat = "left";
div.style.margin = "1px"
div.className = i;
body.appendChild(div);
div.onmouseover = (function(value) {
return function() {
var n1 = document.createTextNode("Cell " + value);
this.appendChild(n1);
}
})(i);
div.onmouseout = (function(value) {
return function() {
var n2 = document.createTextNode(value + " Cell");
this.appendChild(n2);
}
})(i);
};
};
Your code doesn't work because when your onmouseover and onmouseout functions are executed, the value of your text variables is "cell 28." Also, your child removal was a little off, if I interpret your intentions correctly.
<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8 />
<title>JS Bin</title>
</head>
<body>
<script type="text/javascript">
function createDivs(n) {
for(var i = 1; i <= n; i++) {
var div = document.createElement("div");
var body = document.getElementsByTagName("body")[0];
div.style.width = "100px";
div.style.height = "100px";
div.style.border = "1px solid red";
div.style.cssFloat = "left";
div.style.margin = "1px"
div.className = i;
body.appendChild(div);
div.onmouseover = function() {
if (this.childNodes.length > 0) this.removeChild(this.childNodes[0]);
var n_text = document.createTextNode("Cell " + this.className);
this.appendChild(n_text);
},
div.onmouseout = function() {
if (this.childNodes.length > 0) this.removeChild(this.childNodes[0]);
var n_text = document.createTextNode(this.className + " Cell");
this.appendChild(n_text);
}
}
}
createDivs(28)
</script>
</body>
</html>
I also changed your if statement so you pass the number of cells you want instead of the number of cells +1.