Add onClick to an input being built by JavaScript - javascript

I have a file type input button that I am needing to clear completely if the user chooses to and the only safe solution I have found is to completely destroy the input and rebuild it. What I have right now works but it is a "Harp Gun" solution in that it only works once.
Basically, the user has a file input like so:
<input type="file" name="filesToUpload" id="filesToUpload" onChange="makeFileList();" />
<ul id="fileList"><li>No Files Selected</li></ul>
And when they select a file, they may need to clear that completely.
So I have this being built up via appending it on to the filelist:
function makeFileList() {
var input = document.getElementById("filesToUpload");
var ul = document.getElementById("fileList");
while (ul.hasChildNodes()) {
ul.removeChild(ul.firstChild);
}
for (var i = 0; i < input.files.length; i++) {
var li = document.createElement("li");
var fileSize = input.files[i].size;
li.innerHTML = input.files[i].name +" "+ "<span id=\"lblSize\"></span><input onclick=\"clearFileInput()\" type=\"button\" value=\"Clear\" \/>";
ul.appendChild(li);
}
if(!ul.hasChildNodes()) {
var li = document.createElement("li");
li.innerHTML = 'No Files Selected';
ul.appendChild(li);
}
};
And to completely destroy the file, the function rebuilds the input like so:
function clearFileInput(){
var oldInput = document.getElementById("filesToUpload");
var newInput = document.createElement("input");
newInput.type = "file";
newInput.id = oldInput.id;
newInput.name = oldInput.name;
newInput.className = oldInput.className;
newInput.style.cssText = oldInput.style.cssText;
// copy any other relevant attributes
oldInput.parentNode.replaceChild(newInput, oldInput);
};
So I can create the element, add the file type, and use the old input ID, class and name. But I need it to have the same onChange="makeFileList(); behavior as well.
Here is a FIDDLE. Any help is appreciated.

Simply add the attribute.
function clearFileInput(){
var oldInput = document.getElementById("filesToUpload");
var newInput = document.createElement("input");
newInput.type = "file";
newInput.id = oldInput.id;
newInput.name = oldInput.name;
newInput.className = oldInput.className;
newInput.style.cssText = oldInput.style.cssText;
newInput.setAttribute("onclick", "makeFileList()");
// copy any other relevant attributes
oldInput.parentNode.replaceChild(newInput, oldInput);
};

How about this:
function clearFileInput(){
var oldInput = document.getElementById("filesToUpload"),
newInput = document.createElement("input"),
eventHandler = oldInput.onchange;
newInput.type = "file";
newInput.id = oldInput.id;
newInput.name = oldInput.name;
newInput.className = oldInput.className;
newInput.style.cssText = oldInput.style.cssText;
// copy any other relevant attributes
oldInput.parentNode.replaceChild(newInput, oldInput);
newInput.onclick = eventHandler ;
};

Since you've tagged it jquery, you can use event-delegation.
$(document).on('change', '[name="filesToUpload"]', makeFileList);

Related

Using button in table and passing data from a cell in JavaScript

I'm trying to use javascript to retrieve the data from row.insertCell(0) unfortunately I don't believe I am setting up my this statement correctly so I am getting nothing back. I would appreciate some advice on this.
var cardTable = document.getElementById("cardBody");
card.forEach(item => {
let row = cardTable.insertRow();
let refNum = row.insertCell(0);
refNum.innerHTML = item.G1_Card_Ref;
let select = row.insertCell(1);
var sBtn = document.createElement('input');
sBtn.type = "button";
sBtn.className = "btn";
sBtn.style.color = "blue";
sBtn.setAttribute('onclick', 'editCard('this')');
sBtn.value = "Select";
select.appendChild(sBtn);
This is a temporary function I created to look at the data coming back from the table.
function editCard(CardRefNo) {
document.getElementById("ecForm").style.display = "block";
}
Try setting the onclick listener like this
sBtn.onclick = function() {
// do stuff with sBtn here, this is the new editCard function
console.log(sBtn)
document.getElementById("ecForm").style.display = "block";
}

How to loop over dynamically generated input fields?

I am generating some input fields dynamically on my page, and I want to grab inputs from them to store in localStorage if this way works if not? suggest a way around, how can this be done? also how can i add a event listener to submit button ? followings are code have a look at it and give some suggestions/improvisations.
..
HTML
<div id="warnMessage"></div>
<div class="add"></div>
<div class="inputs">
<input
type="text"
maxlength="1"
id="inputValue"
/>
<button class="btn" type="button">+</button>
</div>
javascript
const div = document.querySelector(".add");
const add = document
.querySelector(".btn")
.addEventListener("click", addingInps);
function addingInps() {
const inputValue = parseInt(document.getElementById("inputValue").value);
if (isNaN(inputValue)) {
document.getElementById("warnMessage").innerText = "Enter Again";
document.getElementById("inputValue").value = "";
} else {
const form = document.createElement("form");
form.method = "post";
form.action = "#";
for (let i = 0; i < inputValue; i++) {
const inp = document.createElement("input");
inp.type = "text";
inp.maxLength = "12";
inp.required = true;
inp.className = "inp";
const br = document.createElement("br");
form.appendChild(br.cloneNode());
form.appendChild(inp);
form.appendChild(br.cloneNode());
div.appendChild(form);
document.querySelector("#inputValue").style.display = "none";
}
const sub = document.createElement("button");
sub.className = "subButton";
sub.type = "button";
sub.value = "button";
sub.textContent = "Submit"
form.appendChild(sub);
}
}
You are loop through an input ...not an array or nodelist.
It cant work
I think it would be easier if you appended an ID with every new input field you made
for(let i=0;i < inputValue;i++){
// create your element ipt
ipt.setAttribute("id","autogenerated_" + i);
}
and grab value based on id
document.getElementById("autogenerated_x").value();
about setting an event listener, I can't think any other way of the classic
btn.addEventListener("click", function(e){
// your functionality
});

Using JS to generate a list of HTML elements. addEventListener only applying to last element [duplicate]

This question already has answers here:
JavaScript closure inside loops – simple practical example
(44 answers)
Closed 3 years ago.
I have the following HTML written. The idea is that I can add items to the list at the top, and then generate a field which includes a name, checkbox, and text field. The text field is to be enabled/disabled depending on the checkbox. In my javascript, the toggle function is assigned to the onclick attribute of the checkbox field, but it only works on the last item on the list. Can anyone tell why this functionality isn't being assigned to all the checkboxes? If you open the resulting html code in a browser, it shows no onclick events for any checkboxes except the last one, so it appears it isn't being added. Does it somehow get removed from the previous one when I assign it to the next? How would I fix it? Thank you.
<!DOCTYPE html>
<html>
<body onload="loadAllSettings()" }>
<script>
var genOptFields = ["genField1", "genField2"];
function loadAllSettings() {
loadSettingsList("genSet", genOptFields);
}
</script>
<h2>Options</h2>
<form>
<fieldset id="genSet">
<legend>General</legend>
</fieldset>
</form>
<script>
function loadSettingsList(parentId, optionalFields) {
var fieldset = document.getElementById(parentId);
for (fieldId of optionalFields) {
var p = document.createElement('p');
p.append(fieldId + ":");
var input = document.createElement('input');
input.type = "text";
input.disabled = true;
input.id = fieldId;
var cb = document.createElement('input');
cb.type = "checkbox";
cb.id = "cb_" + fieldId;
cb.addEventListener("click", function () {
toggleCheck(fieldId);
});
p.appendChild(cb);
p.appendChild(input);
fieldset.appendChild(p);
}
}
function toggleCheck(fieldId) {
document.getElementById(fieldId).disabled = !document.getElementById("cb_" +
fieldId).checked;
}
</script>
</body>
</html>
As explained below, your fieldId reference isnt static. As a result when calling toggle check it was always passing the last value that fieldId contained no matter what (double check this by console.logging your fieldId passed to toggle check)
function loadAllSettings() {
const genOptFields = ["genField1", "genField2"];
loadSettingsList("genSet", genOptFields);
}
function loadSettingsList(parentId, optionalFields) {
const fieldset = document.getElementById(parentId);
optionalFields.forEach(function (fieldId) {
createParagraph(fieldId, fieldset);
});
}
function createParagraph(fieldId, fieldset) {
const p = document.createElement('p');
p.append(fieldId + ":");
createCheckbox(p, fieldId);
createInputField(p, fieldId);
fieldset.appendChild(p);
}
function createInputField(p, fieldId) {
const input = document.createElement('input');
input.type = "text";
input.disabled = true;
input.id = fieldId;
p.appendChild(input);
}
function createCheckbox(p, fieldId) {
const cb = document.createElement('input');
cb.type = "checkbox";
cb.id = "cb_" + fieldId;
//set this attribute to capture value
cb.setAttribute('data-fieldId', fieldId);
cb.addEventListener("click", function () {
//use static data attribute value instead of fieldId var which isnt static
toggleCheck(this.getAttribute('data-fieldId'));
});
p.appendChild(cb);
}
function toggleCheck(fieldId) {
document.getElementById(fieldId).disabled = !document.getElementById("cb_" + fieldId).checked;
}
<!DOCTYPE html>
<html>
<body onload="loadAllSettings()" }>
<h2>Options</h2>
<form>
<fieldset id="genSet">
<legend>General</legend>
</fieldset>
</form>
</body>
</html>
Since you are generating the element using body on-load event, click event become static. That is why element is always pointing to the last child. You can simply achieve your requirement by passing element scope(this) into the click event.
Here is the working solution:
<body onload="loadAllSettings()" }>
<script>
var genOptFields = ["genField1", "genField2"];
function loadAllSettings() {
loadSettingsList("genSet", genOptFields);
}
</script>
<h2>Options</h2>
<form>
<fieldset id="genSet">
<legend>General</legend>
</fieldset>
</form>
<script>
function loadSettingsList(parentId, optionalFields) {
var fieldset = document.getElementById(parentId);
for (fieldId of optionalFields) {
var p = document.createElement('p');
p.append(fieldId + ":");
var input = document.createElement('input');
input.type = "text";
input.disabled = true;
input.id = fieldId;
var cb = document.createElement('input');
cb.type = "checkbox";
cb.id = "cb_" + fieldId;
cb.addEventListener("click", function () {
toggleCheck(this);
});
p.appendChild(cb);
p.appendChild(input);
fieldset.appendChild(p);
}
}
function toggleCheck(ele) {
ele.nextElementSibling.disabled = !ele.checked;
}
</script>
</body>

How to multipy numbers between a field and a new created field

Please i have a problem here in my work i have an input field and have a button that i use to create new input field with onclick event, but my problem is how to multiply numbers in both input fields and alert the answer.
function create(){
var main_input = document.getElementById("main_input").value,
newinput = document.createElement('input');
newinput.placeholder = "test1";
newinput.value;
document.getElementById("mytest").appendChild(newinput);
}
function multiply(){
var ans = newinput * main_input;
alert(ans);
}
In the absence of clarity, I am posting this solution. Looks like you are not clear on few concepts so let me try to explain them:
You need to move your variables outside the scope of create() so that they are available in the multiply() function.
You cannot just multiply two input fields. You need to take the values from them as shown in the code below.
Hopefully it helps you in moving ahead!
var main_input,newinput;
function create(){
main_input = document.getElementById("main_input");
newinput = document.createElement('INPUT');
newinput.placeholder = "test1";
newinput.value = 10;
document.getElementById("mytest").appendChild(newinput);
}
function multiply(){
var ans = newinput.value * main_input.value;
alert(ans);
}
create();
multiply();
<input id="main_input" value=10 />
<div id="mytest"></div>
Use eval() or you can manually multiply the values like input1.value * input2.value
function create(){
// this is unnecessary, you are creating a new element
// var main_input = document.getElementById("main-input");
var newinput = document.createElement('input');
newinput.placeholder = "test1";
newinput.id = 'test1'; // give the element an id, to access it later by id
// newinput.value; // this too is unnecessary, you'll get the value from the user
if (!document.getElementById('test1')) {
// append the child only if it doesn't exist
document.getElementById("mytest").appendChild(newinput);
}
}
function multiply(){
var newinput = document.getElementById('test1');
var mainInput = document.getElementById("main_input");
alert(eval(newinput.value + '*' + mainInput.value));
// alert(newinput.value * mainInput.value) you can also use this method
}
<div id="mytest">
<input type="text" id="main_input">
</div>
<button onclick="create()">Create</button>
<button onclick="multiply()">Multiply</button>

Taking tab example from fiddle ans use in my project

http://jsfiddle.net/738wtmhs/1/
using above example in fiddle in my own project: for the purpose of this exercise I am using DOM methods to create and append the elements.
function GetFeatureProperties(feature) {
//add header to 1st FirstTabContent
var featureHeader = "<center><b> <FONT COLOR='FF6600'> Feature Properties </FONT> </b> </center> </br>";
var FirstTabContent = document.createElement('div');
FirstTabContent.id = "tabs-1";
FirstTabContent.innerHTML = featureHeader;
//Second Tab
var SecondTabContent = document.createElement('div');
SecondTabContent.id = "tabs-2";
var newImage = document.createElement("img");
newImage.src = "http://mintywhite.com/wp-content/uploads/2012/10/fond-ecran-wallpaper-image-arriere-plan-hd-29-HD.jpg";
newImage.width = "100";
newImage.height = "100";
SecondTabContent.appendChild(newImage);
//add li and ul
var DivHolding2Tabs = document.createElement('div');
DivHolding2Tabs.class = "shoptab";
var header2 = document.createElement('h2');
header2.innerHTML = "Feature";
DivHolding2Tabs.appendChild(header2);
var _ul = document.createElement('ul');
var _anchor1 = document.createElement("a");
_anchor1.href = "#tabs-1";
_anchor1.innerHTML = "Info";
var _li1 = document.createElement('li');
_li1.appendChild(_anchor1);
var _anchor2 = document.createElement("a");
_anchor2.href = "#tabs-2";
_anchor2.innerHTML = "Images";
var _li2 = document.createElement('li');
_li2.appendChild(_anchor2);
_ul.appendChild(_li1);
_ul.appendChild(_li2);
DivHolding2Tabs.appendChild(_ul);
DivHolding2Tabs.appendChild(FirstTabContent);
DivHolding2Tabs.appendChild(SecondTabContent);
var jelm = $(DivHolding2Tabs); //convert to jQuery Element
var htmlElm = jelm[0]; //convert to HTML Element
var OuterDiv = document.createElement('div');
OuterDiv.id = "loc-list";
OuterDiv.appendChild(htmlElm);
return OuterDiv.innerHTML;
}
and this looks like the image seen below....if I click on the link 'image' the page jumps a bit but nothing happens and nothing happens when I press 'info' also I have included the CSS in my project so why arnt the tabs showing and yes I am using jquery ui 1.10.3.custom.js
---------------------------------------------------------------------------------------------
UPDATE
<ul id="list"><li><div><h2>Feature</h2><ul><li>Info</li><li>Images</li></ul><div id="tabs-1"><center><b> <font color="FF6600"> Feature Properties </font> </b> </center> <br></div><div id="tabs-2"><img src="http://mintywhite.com/wp-content/uploads/2012/10/fond-ecran-wallpaper-image-arriere-plan-hd-29-HD.jpg" width="100" height="100"></div></div></li></ul>
Also changed from jquery 1.10.3 custom to jquery 1.11.2.custom with all the downloaded tabs selected
If you look at this fiddle, I managed to make it work.
Here's the possible problems
1) I changed return OuterDiv.innerHTML because I needed the <div id="loc-list"> to be part of the code to initialize it. You gave it an id so my guess is you wanted it to be included but by doing innerHTML, you didn't get it.
2) Once your function returns, you need to initialize the tabs with $('#loc-list').tabs();

Categories

Resources