So I am trying to create an expense tracker that has a list of dynamically created options.
The user will be able to:
add a new expense
select a category
add a name for the expense, and then
put how much the expense is.
I have everything working, except for I would like to display the categories with the total amount of money budgeted for each category.
Right now I have 9 categories. If a uses has 2 expenses with the same category, for example "Health & Fitness", I would like that Category to show up on the left side in a DIV that displays the total amount budgeted. If there are other categories like "Auto & Transport", I would like that to display as well with the total amount budgeted. I can't seem to figure out how to separate the totals based on the category selected.
var addListItem = document.getElementById("add-more");
addListItem.addEventListener("click", function() {
createNewItem();
});
//Display Month and Day
var today = new Date();
var dd = today.getDate();
var mm = today.getMonth()+1;
today = mm + "/" + dd;
document.getElementById("current-date").innerHTML = today;
//Creates new elements
function createNewItem() {
var u = document.getElementById("full-item-list");
var l = document.createElement("li");
var elinput = document.createElement('input');
var select = document.createElement('select');
var option1 = document.createElement('option');
var option2 = document.createElement('option');
var option3 = document.createElement('option');
var option4 = document.createElement('option');
var option5 = document.createElement('option');
var option6 = document.createElement('option');
var option7 = document.createElement('option');
var option8 = document.createElement('option');
var option9 = document.createElement('option');
var option10 = document.createElement('option');
var o1 = document.createTextNode('Category');
var o2 = document.createTextNode('Auto & Transport');
var o3 = document.createTextNode('Bills & Utilities');
var o4 = document.createTextNode('Health & Fitness');
var o5 = document.createTextNode('Home');
var o6 = document.createTextNode('Personal Care');
var o7 = document.createTextNode('Pets');
var o8 = document.createTextNode('Shopping');
var o9 = document.createTextNode('Entertainment');
var o10 = document.createTextNode('Investments');
var expenseName = document.createElement('input');
var icon = document.createElement('img');
option1.setAttribute('disabled', 'true');
option1.setAttribute('selected', 'true');
option1.appendChild(o1);
option2.appendChild(o2);
option2.setAttribute('name', 'testName');
option3.appendChild(o3);
option3.setAttribute('name', 'testName2');
option4.appendChild(o4);
option5.appendChild(o5);
option6.appendChild(o6);
option7.appendChild(o7);
option8.appendChild(o8);
option9.appendChild(o9);
option10.appendChild(o10);
select.setAttribute('type', 'select');
select.setAttribute('placeholder', 'Select a Category');
select.appendChild(option1);
select.appendChild(option2);
select.appendChild(option3);
select.appendChild(option4);
select.appendChild(option5);
select.appendChild(option6);
select.appendChild(option7);
select.appendChild(option8);
select.appendChild(option9);
select.appendChild(option10);
expenseName.setAttribute('type', 'text');
expenseName.setAttribute('placeholder', 'Expense name');
expenseName.setAttribute('class', 'expense-input-name')
expenseName.setAttribute('name', 'totalExpense');
elinput.setAttribute('type', 'number');
elinput.setAttribute('class', 'li-input');
elinput.setAttribute('placeholder', 'Enter amount');
elinput.setAttribute('name', 'qty');
l.setAttribute('class', 'list-item');
l.setAttribute('name', 'li-name');
icon.setAttribute('class', 'remove-icon');
icon.setAttribute('src', 'https://s3-us-west-2.amazonaws.com/s.cdpn.io/375261/System_Delete.ico');
icon.setAttribute("id", "icon-id");
icon.addEventListener('click', function(e) {
thaticon(e);
}, false);
l.appendChild(select);
l.appendChild(expenseName);
l.appendChild(elinput);
l.appendChild(icon);
u.appendChild(l);
}
//Deletes elements
function thaticon(e) {
console.log("test");
var el = e.target;
var elListItem= el.parentNode;
elFullList = elListItem.parentNode;
elFullList.removeChild(elListItem);
}
//Calculates and displays results
function displayResult() {
var arr = document.getElementsByName("qty");
var wage = document.getElementById("inputWage").value;
var jumboDiv = document.getElementById("jumbo-results").style.display="block";
var tot = 0;
for (var i = 0; i < arr.length; i++) {
if (parseFloat(arr[i].value)) tot += parseFloat(arr[i].value);
}
document.getElementById("result").innerHTML = "Total Expenses: $" + tot.toFixed(2);
document.getElementById("left").innerHTML = "Left Over: $" + ((wage - tot).toFixed(2));
}
//Resets and clears entire entry
function resetForm() {
var jumboDiv = document.getElementById("jumbo-results").style.display="none";
document.getElementById("full-item-list").innerHTML = "";
document.getElementById("inputWage").value = "";
document.getElementById("result").innerHTML = "";
document.getElementById("left").innerHTML = "";
document.getElementById("number-display").innerHTML = "";
}
//Displays the selected categories by user with the total sum for each one
function displayCategory() {
}
//Capture screen shots
/*function captureScreen() {
html2canvas(document.querySelector("#capture")).then(canvas => {
document.body.appendChild(canvas)
});
}*/
You will need to create a data structure to store the category information and use that to construct your HTML elements.
The following code constructs a simple select element without any additional attributes.
var optionsArray = ['Category',
'Auto & Transport',
'Bills & Utilities',
'Health & Fitness',
'Home',
'Personal Care',
'Pets',
'Shopping',
'Entertainment',
'Investments'];
var selectElem = document.createElement('select');
selectElem.setAttribute('placeholder', 'Select a Category');
// iterate through the array of options
optionsArray.forEach(function(text){
var option = document.createElement('option');
var optionText = document.createTextNode(text);
option.appendChild(optionText);
selectElem.appendChild(option);
});
// selectElem is ready to append to the DOM
This can be improved upon by changing the elements in the array to objects and using the attributes if required.
e.g.
var optionsArray = ['Category',
'Auto & Transport',
{
'itemText' : 'Bills & Utilities',
'itemDisabled' : true,
'itemSelected' : true
},
'Health & Fitness',
'Home',
'Personal Care',
'Pets',
'Shopping',
'Entertainment',
'Investments'];
var selectElem = document.createElement('select');
selectElem.setAttribute('placeholder', 'Select a Category');
// iterate through the array of options
optionsArray.forEach(function(item){
var text = (typeof(item) === 'string') ? item : item.itemText;
var option = document.createElement('option');
var optionText = document.createTextNode(text);
option.appendChild(optionText);
if (typeof(item) === 'object') {
// handle custom attributes
Object.keys(item).forEach(function(key){
switch(key) {
case 'itemDisabled' :
if (item[key]) {
option.setAttribute('disabled', true);
}
break;
case 'itemSelected' :
if (item[key]) {
option.setAttribute('selected', true);
}
break;
default:
break;
}
});
}
selectElem.appendChild(option);
});
// selectElem is ready to append to the DOM
The calculations for the category totals would need to be done using a data structure such as an array of objects. Iterate through the array, calculating the totals before adding the desired information to the HTML.
Related
I'm rendering a dynamic input and checkbox from an array object which is fine, however I'm not quite sure how to hide the input when I click on the checkbox relative to the input.
function dynamicStuff () {
var objs = ['Id', 'Name', 'Age'];
for (var i = 0; i < objs.length; i++) {
objs[i];
var cElement = document.createElement("input");
cElement.type = "checkbox";
cElement.name = objs[i];
cElement.id = objs[i];
var cElementInput = document.createElement("input");
cElementInput.type = "text";
cElementInput.name = objs[i];
cElementInput.id = objs[i];
cElementInput.placeholder = objs[i]
document.getElementById('chkBox').appendChild(cElement);
document.getElementById('chkBox').appendChild(cElementInput);
}
}
Live example.
Saving on localStroage:
function chkboxCookie() {
var indexOfItem = checkAllFields.indexOf(this.id);
if (indexOfItem >= 0) {
checkAllFields.splice(indexOfItem, 1);
} else {
checkAllFields.push(this.id);
}
/* it saves paramater name in the localStorage*/
localStorage.setItem("checkedUsers", JSON.stringify(checkAllFields));
}
How do I hide the input that I ticked and potentially save that input name/Id in the localStorage?
You'd add an event handler that does something to the input when the checkbox is checked
function dynamicStuff() {
var objs = ['Id', 'Name', 'Age'];
for (var j = 0; j < objs.length; j++) {
(function(i) {
objs[i];
var cElementInput = document.createElement("input");
cElementInput.type = "text";
cElementInput.name = objs[i];
cElementInput.id = objs[i];
cElementInput.placeholder = objs[i];
var cElement = document.createElement("input");
cElement.type = "checkbox";
cElement.name = objs[i];
cElement.id = objs[i];
cElement.addEventListener('change', function() {
cElementInput.style.display = this.checked ? 'none' : 'inline';
localStorage.setItem(objs[i], this.value);
});
var br = document.createElement('br');
document.getElementById('chkBox').appendChild(cElement);
document.getElementById('chkBox').appendChild(cElementInput);
document.getElementById('chkBox').appendChild(br);
document.getElementById('chkBox').appendChild(br.cloneNode());
})(j);
}
}
dynamicStuff()
<div id="chkBox"></div>
Working fiddle.
The id attribute should be unique in the same page so try to change the id of the input for example :
cElementInput.id = objs[i]+'_input';
And attach change event to the checkbox's where you'll show/hide related inputs:
cElement.addEventListener("change", toggleInput, false);
Then define your toggleInput() function :
function toggleInput(){
var input_id = this.id+'_input';
document.getElementById(input_id).style.display = this.checked ? 'inline' : 'none';
localStorage.setItem(this.id, this.value);
}
To check/uncheck the checkboxe's based on localStorage, get the data first :
var localStorageData = JSON.parse(localStorage.getItem("checkedUsers"));
var data = localStorageData==null?[]:localStorageData;
Then check for the the values presented in the array and check/uncheck checkboxe's :
if(data.indexOf(objs[i]) >= 0)
cElement.checked = true;
else
cElement.checked = false;
Hope this helps.
Trying to get the eventlistener to run, i.e. when I select United Kingdom, another selection box will appear to select county (county() function), but for some reason the addEventListener will not call the function, and I can't fathom how to pass the selected country to the county function? Any ideas please.
function countries() {
xmlRequest("countries.xml");
var country_selector = document.createElement("SELECT");
country_selector.id = "cou n tryselection";
document.getElementById("quiz").appendChild(country_selector);
var t = document.getElementById("countryselection");
var c_opt = document.createElement("option");
c_opt.text = "Please select";
c_opt.selected = true;
t.add(c_opt);
c_opt = document.createElement("option");
c_opt.text = "United Kingdom";
c_opt.value = "1";
t.add(c_opt);
document.getElementById("countryselection").addEventListener("change", count y(this.value), false);
var x = xmlDoc.getElementsByTagName("country");
for (i = 0; i < x.length; i++) {
var opt = document.createElement("option");
opt.text = x[i].getElementsByTagName("country_name ")[0].childNodes[0].nodeValue;
t.add(opt);
}
}
function county(Country) {
if (!document.getElementById("countyselection")) {
if (Country === "1") {
xmlRequest("counties.xml");
document.getElementById("quiz").innerHTML += "<select id='countyselection'></select>";
var t = document.getElementById("countyselection");
var y = xmlDoc.getElementsByTagName("county");
for (j = 0; j < y.length; j++)
{
var opt = document.createElement("option");
var txt = y[j].getElementsByTagName("county_name")[0].childNodes[0].nodeValue;
opt.text = txt;
t.add(opt);
}
}
} else {
var f = document.getElementById("countyselection");
document.getElementById("countyselection").parentNode.removeChild(f);
}
}
Because you're calling the function, not referencing it, and you have a space in the function name.
change
document.getElementById("countryselection").addEventListener("change", count y(this.value), false);
to
document.getElementById("countryselection").addEventListener("change", function() {
county(this.value);
}, false);
Also note that things like this
country_selector.id = "cou n tryselection";
is completely invalid, you can't use random text with spaces as an ID
How to populate drop down value in java script?
<script type="text/javascript">
var creatLimit = 5;
var fCount=0;
function addFileElement()
{
if(fCount <creatLimit )
{
/*var option = document.createElement("option");
option.value = '0'; option.innerHTML = ' -- '; select.appendChild(option);
option.value = '1'; option.innerHTML = 'item 1'; select.appendChild(option);
option.value = '2'; option.innerHTML = 'item 2'; select.appendChild(option);*/
var fObject = document.getElementById("agencySection");
//var addButton = document.createElement(label);
var addButton = document.createElement("select");
var agency = document.getElementById("agencyLabelSection");
var addButton2 = document.createElement("option");
//<label for="firstname">First name:</label>
//<label for="agencyLabelSection">agency:</label>
//<input type="text" name="agencyLabelSection" id="agencyLabelSection" />
addButton.type= "select";
addButton2.type= "option";
//for (var fObject in addButton) {
addButton.name="userRoleBeanList["+fCount+"]";
addButton.setAttribute("class", "normal");
addButton.style.width= "250px";
addButton.onkeydown = function(){
blur();
}; //}
//document.write("<p> Agency:</p>");
addButton2.name="userRoleBeanList["+fCount+"]";
addButton2.setAttribute("class", "normal");
addButton2.onkeydown = function(){
blur();
};
var o2 = document.createElement("br");
var o3 = document.createElement("br");
fObject.appendChild(addButton);
fObject.appendChild(o2);
fObject.appendChild(o3);
agency.appendChild(addButton2);
var fObject1 = document.getElementById("roleSection");
var addButton1 = document.createElement("select");
var role = document.getElementById("roleLabelSection");
var addButton3 = document.createElement("option");
addButton1.type= "select";
addButton3.type= "option";
addButton1.name="userRoleBeanList["+fCount+"]";
addButton1.setAttribute("class", "normal");
addButton1.style.width= "250px";
addButton1.onkeydown = function(){
blur();
};
var o4 = document.createElement("br");
var o5 = document.createElement("br");
fObject1.appendChild(addButton1);
fObject1.appendChild(o4);
fObject1.appendChild(o5);
role.appendChild(addButton3);
fCount++;
}
}
</script>
the same question was asked here and the answer is just
ddl.options[i] = theOption;
this code example show how to add variables to the drop down:
var ddl = document.getElementById( 'myDropdown' );
var theOption = new Option;
var x;
var i;
for(i = 0; i < 999; i++) {
x = i + 1;
theOption.text = x;
theOption.value = x;
ddl.options[i] = theOption;
}
if you'll edit your question so we'll know what's the drop down list name and needed values are then i can help you more
I am extremely new to JavaScript. I am trying to control the options inside one listbox (called Aggregator) using the selected value of another (called Product). Below is the code I have written so far.
Now when I load the HTML page the code I have written to control the text boxes (using txt, txt2, txt3) does not work either now.
Javascript
function pGo() {
var x = document.getElementById("Product").value;
var txt = "";
var txt2 = "";
var txt3 = "";
var list = document.getElementById("Aggregator");
var aggrs = new Array();
aggrs[0] = "h";
aggrs[1] = "e";
aggrs[2] = "l";
aggrs[3] = "l";
aggrs[4] = "l";
aggrs[5] = "o";
aggrs[6] = "o";
var length = aggrs.length;
var element = null;
if (x == "HII") {
txt = "Full ";
txt2 = "/";
txt3 = "/";
for (var i = 0; i < 5; i++)){
element = aggrs[i]
var opt = document.createElement("option");
opt.innerText = element;
opt.setAttribute(element, 'newvalue');
list.appendChild(opt);
}
}
else if (x == "DLG"){
txt = "Full";
txt2 = "/T";
txt3 = "/responses/";
for (var i = 0; i < 1; i++)){
element = aggrs[i]
var opt = document.createElement("option");
opt.innerText = element;
opt.setAttribute(element, 'newvalue');
list.appendChild(opt);
}
}
else if (x == "TBB"){
txt = "Full ";
txt2 = "/Trams";
txt3 = "/respo";
for (var i = 0; i < 1; i++)){
element = aggrs[i]
var opt = document.createElement("option");
opt.innerText = element;
opt.setAttribute(element, 'newvalue');
list.appendChild(opt);
}
element = aggrs[6]
var opt = document.createElement("option");
opt.innerText = element;
opt.setAttribute(element, 'newvalue');
list.appendChild(opt);
}
form.elements.calcType.value = txt;
form.elements.transform.value = txt2;
form.elements.calcResponse.value = txt3;
}
HTML
product
<select id="Product" onchange = "pGo()">
<option>HII</option>
<option>DLG</option>
<option>TBB</option>
</select><div>
<script type = "text/javascript">
aggregator
<select name = "Aggregator">
</select><br/><br/>
Other text boxes emitted
I need the Aggregator to display certain values from the aggrs list depending on the value selected in the Product select:
HII : [0,1,2,3,4,5]
DLG : [0,1]
TBB : [0,1,6]
Don't go learning jQuery if you're having trouble with basic JavaScript. You'll have worse problems with jQuery.
For a start, you're asking for the ID "Aggregator":
var list = document.getElementById("Aggregator");
when you don't have an object with the ID "Aggregator":
<select name = "Aggregator"></select>
First off, there are a LOT of syntax errors in your code. I have added comments where I made those changes.
There was no id element "Aggregator" so I changed your markup:
product
<select id="Product" onchange="pGo();">
<option>Pick one</option>
<option>HII</option>
<option>DLG</option>
<option>TBB</option>
</select>
<div>aggregator
<select id="Aggregator" name="Aggregator"></select>
<br/>
<br/>
</div>
You had a lot of duplicate code (still is some) and other issues (see comments)
// function to remove duplicate code
function addOptions(list, aggrs, limit) {
var i = 0;
// fix issue where option list did not empty on new select
for (; i < list.length; i++) {
list.remove(i);
}
for (i = 0; i < limit; i++) { // fix extra ")"
var opt = document.createElement("option");
element = aggrs[i]; //missing semicolon
opt.text = element; // use standard form not innerHtml
opt.value = element; // you had no value
opt.setAttribute(element, 'newvalue');
list.appendChild(opt);
}
}
function pGo() {
var x = document.getElementById("Product").value;
var txt = "";
var txt2 = "";
var txt3 = "";
var list = document.getElementById("Aggregator");
var aggrs = ["h", "e", "l", "l", "l", "o", "o"]; //simpler array
var length = aggrs.length;
var element = null;
if (x == "HII") {
txt = "Full ";
txt2 = "/";
txt3 = "/";
addOptions(list, aggrs, 5);
} else if (x == "DLG") {
txt = "Full";
txt2 = "/T";
txt3 = "/responses/";
addOptions(list, aggrs, 1);
} else if (x == "TBB") {
txt = "Full ";
txt2 = "/Trams";
txt3 = "/respo";
addOptions(list, aggrs, 1);
// strange additional option added
var oneAggr = [];
oneAggr[0] = aggrs[6];
addOptions(list, oneAggr, 1);
}
// form.elements.calcType.value = txt; // commented out due to not existing
// form.elements.transform.value = txt2;
// form.elements.calcResponse.value = txt3;
}
This is NOT really pretty (OK it is somewhat strange the options you set) even yet but at least it should work.
Sample to work with: http://jsfiddle.net/Qc4yD/
I am building a UI in JavaScript that involves adding a column of checkBoxes:
for (var key in ProcessAndPortList.list)
{
if (ProcessAndPortList.list.hasOwnProperty(key))
{
var dataRow = myTable.insertRow(-1);
var dataCell = dataRow.insertCell(-1);
dataCell.textContent = key;
dataCell = dataRow.insertCell(-1);
dataCell.textContent = ProcessAndPortList.list[key].port;
var terminationCheckbox = document.createElement('input');
terminationCheckbox.type = "checkbox";
terminationCheckbox.id = key;
terminationCheckbox.checked = ProcessAndPortList.list[key].markedForTermination;
terminationCheckbox.onchange = function() {
var isChecked = terminationCheckbox.checked;
markForTermination(key, isChecked);
};
var terminateCell = dataRow.insertCell(-1);
terminateCell.appendChild(terminationCheckbox);
}
}
The problem comes in associating the correct ID to the callback for when the checkbox for each entry is checked. I can't seem to get that checkbox's ID to the function. I only ever get the last checkBox's ID. How can I get the correct ID?
Changing this should work:
terminationCheckbox.onchange = function() {
markForTermination(this.id, this.checked);
};
It seems that you capture the variable key with that closure. But key changes on each iteration of the for loop. Capture some variable that is declared inside the loop instead.
for (var key in ProcessAndPortList.list)
{
if (ProcessAndPortList.list.hasOwnProperty(key))
{
var local_scope_key = key
var dataRow = myTable.insertRow(-1);
var dataCell = dataRow.insertCell(-1);
dataCell.textContent = key;
dataCell = dataRow.insertCell(-1);
dataCell.textContent = ProcessAndPortList.list[key].port;
var terminationCheckbox = document.createElement('input');
terminationCheckbox.type = "checkbox";
terminationCheckbox.id = key;
terminationCheckbox.checked = ProcessAndPortList.list[key].markedForTermination;
terminationCheckbox.onchange = function() {
var isChecked = terminationCheckbox.checked;
markForTermination(local_scope_key, isChecked);
};
var terminateCell = dataRow.insertCell(-1);
terminateCell.appendChild(terminationCheckbox);
}
}