Generate JSON string from form on change to populate business-hours - javascript

I have the following html input's
<form id="test" role="form">
<input class="form-control" data-day="monday" type="time" name="open" value="12:00">
<input class="form-control" data-day="monday" type="time" name="close" value="20:00">
<!-- Rest of the weekdays -->
<input class="form-control" data-day="sunday" type="time" name="open" value="12:00">
<input class="form-control" data-day="sunday" type="time" name="close" value="23:00">
</form>
<pre id="output"></pre>
i try to generate a JSON string based on the input (on change)..
The problem with my code is that it update (and only) al the values of the other days when i change sunday.
if i make a change on the other day's nothing happens, i kinda get it why it fails, but breaking my head to long on it now.
function toJSONString(form) {
var daysObj = {}
var hoursObj = {};
var elements = form.querySelectorAll("input[type='time']");
for (var i = 0; i < elements.length; ++i) {
var element = elements[i];
var days = element.dataset.day;
var name = element.name;
var value = element.value;
//if (days) {
//if (name) {
hoursObj[name] = value;
//}
daysObj[days] = hoursObj;
//}
}
return JSON.stringify(daysObj, null, 2);
}
document.addEventListener("DOMContentLoaded", function() {
var form = document.getElementById("test");
var output = document.getElementById("output");
form.addEventListener("change", function(e) {
e.preventDefault();
var json = toJSONString(this);
output.innerHTML = json;
}, false);
});
<form id="test" role="form">
<input class="form-control" data-day="monday" type="time" name="open" value="12:00">
<input class="form-control" data-day="monday" type="time" name="close" value="20:00">
<!-- Rest of the weekdays -->
<input class="form-control" data-day="sunday" type="time" name="open" value="12:00">
<input class="form-control" data-day="sunday" type="time" name="close" value="23:00">
</form>
<pre id="output"></pre>

Use the input event instead of change as a change event only occurs after an input loses focus. input events are triggered every time the input's value changes
form.addEventListener("input",function(){})
You are also using the same hours object for each day. And thus each iteration you are just changing the same object's open and close property.
You need to create a new object for hoursObj after you have set the last property for that object for that day, in your case after setting close
for (var i = 0; i < elements.length; ++i) {
//previous code
//...
if(name=="close"){
hoursObj = {};
}
}
Demo
function toJSONString(form) {
var daysObj = {}
var hoursObj = {}
var elements = form.querySelectorAll("input[type='time']");
for (var i = 0; i < elements.length; ++i) {
var element = elements[i];
var days = element.dataset.day;
var name = element.name;
var value = element.value;
hoursObj[name] = value;
daysObj[days] = hoursObj;
if(name=="close"){
hoursObj = {};
}
}
return JSON.stringify(daysObj);
}
document.addEventListener("DOMContentLoaded", function() {
var form = document.getElementById("test");
var output = document.getElementById("output");
form.addEventListener("input", function(e) {
e.preventDefault();
var json = toJSONString(this);
output.innerHTML = json;
}, false);
});
<form id="test" role="form">
<input class="form-control" data-day="monday" type="time" name="open" value="12:00">
<input class="form-control" data-day="monday" type="time" name="close" value="20:00">
<!-- Rest of the weekdays -->
<input class="form-control" data-day="sunday" type="time" name="open" value="12:00">
<input class="form-control" data-day="sunday" type="time" name="close" value="23:00">
</form>
<pre><code id="output"></code></pre>

Related

How correctly check if input is not equal zero

I have simple code, in input user inputs number and it must print the numbers until the input is not equal to zero.
And the problem is when i submit value, page stops responding
Here is how my code looks like:
window.onload = function() {
var btn = document.getElementsByClassName('btn')[0];
function printInput() {
var output = document.getElementsByClassName('output')[0];
var input = document.getElementsByClassName('input')[0].value;
while(input !== 0) {
var input = document.getElementsByClassName('input')[0].value;
output.innerHTML += input+'<br>';
}
}
btn.addEventListener('click', printInput);
}
<input type="text" class="input" maxlength="1">
<button class="btn">Submit</button>
<div class="output"></div>
The value property of input is a string.
You must compare with the correct type:
while (input !== '0')
or
while (input != 0)
----- edit -----
Consider changing the while to an if, otherwise it will print any number different of 0 indefinitely.
window.onload = function() {
var btn = document.getElementsByClassName('btn')[0];
function printInput() {
var output = document.getElementsByClassName('output')[0];
var input = document.getElementsByClassName('input')[0].value;
if(input !== '0') {
var input = document.getElementsByClassName('input')[0].value;
output.innerHTML += input+'<br>';
}
}
btn.addEventListener('click', printInput);
}
<input type="text" class="input" maxlength="1">
<button class="btn">Submit</button>
<div class="output"></div>
You need to make two changes
Change type attribute from text to number
Change from while to if
Demo
window.onload = function()
{
var btn = document.getElementsByClassName('btn')[0];
function printInput()
{
var output = document.getElementsByClassName('output')[0];
var input = document.getElementsByClassName('input')[0].value;
if (input !== 0)
{
var input = document.getElementsByClassName('input')[0].value;
output.innerHTML += input + '<br>';
}
}
btn.addEventListener('click', printInput);
}
<input type="number" class="input" maxlength="1">
<button class="btn">Submit</button>
<div class="output"></div>

JS add rows to table. Rows appear and then disappear

I want to add a number of rows to a HTML table, and 9 cells to each row using a JS loop. The problem is that I see in the HTML doc for a short instant (miliseconds) what I want, but later it is erased. Why could it be? This is the code with the JS loop and the HTML.
function calcular() {
var cantidad = Number(document.getElementById("cantidad").value);
var numAnos = Number(document.getElementById("numAnos").value);
var numMeses = Number(document.getElementById("numMeses").value);
var fecha = document.getElementById("fecha");
//Meses
var numFilas = numAnos * 12 + numMeses;
var table = document.getElementById("tablaDatos");
alert(Number(numFilas));
for (var i = 0; i < Number(numFilas); i++) {
alert(table.rows.length);
var newTR = table.insertRow(table.rows.length);
//var row = table1.insertRow(table1.rows.length);
//num cuota
var newTD0 = newTR.insertCell(0);
newTD0.innerHTML = i;
var newTD1 = newTR.insertCell(1);
var newTD2 = newTR.insertCell(2);
var newTD3 = newTR.insertCell(3);
var newTD4 = newTR.insertCell(4);
var newTD5 = newTR.insertCell(5);
var newTD6 = newTR.insertCell(6);
var newTD7 = newTR.insertCell(7);
var newTD8 = newTR.insertCell(8);
}
}
<form action="" name="formDatosInicio">
Cantidad: <input type="text" id="cantidad" name="cantidad"><br> Num aƱos: <input type="text" id="numAnos" name="numAnos"><br> Num meses: <input type="text" id="numMeses" name="numMeses"><br> Fecha:
<input type="date" id="fecha" name="fecha"><br>
<input type="submit" value="Calcular" onclick="calcular()">
</form>
<table id="tablaDatos" name="tablaDatos" style="width:100%" style="text-align:center" align="center" border="1">
<tr>
<td>Numero cuota</td>
<td>Fecha emision</td>
<td>Saldo pendiente</td>
<td>Importe cuota</td>
<td>Amortizacion</td>
<td>Suma Amortizacion</td>
<td>Interes</td>
<td>Suma Interes</td>
<td>% Interes</td>
</tr>
</table>
Your button is submitting the form and is refreshing the page. Change your button from type submit to type button.
<input type="button" value="Calcular" onclick="calcular()">

this parameter not passing expected element

I have a dynamic set of input fields being generated. They all get named sequentially and each has an onFocus() handler. Just before each Input element is a div with a corresponding Id where I grab a dollar value from.
<input type="hidden" name="balance" value="2500.0" />
<div id="invoiceAmount0">$500.00</div>
<input type="text" size="8" id="invoiceBalance0" name="invoiceBalance0" value="" onfocus="setBalance(this)" />
<div id="invoiceAmount1">$500.00</div>
<input type="text" size="8" id="invoiceBalance1" name="invoiceBalance1" value="" onfocus="setBalance(this)" />
<div id="invoiceAmount2">$500.00</div>
<input type="text" size="8" id="invoiceBalance2" name="invoiceBalance2" value="" onfocus="setBalance(this)" />
The JS onFocus handler is as follows:
function setBalance(e) //e should be an input field element
{
var balance = document.PaymentForm.balance.value;
var remainder = balance;
var index = 0;
var paymentField = document.getElementById('invoiceBalance'+index); //get the first input payment element
while (paymentField != null && paymentField != e) //start with the first field and calculate the remaining balance
{
var paymentApplied = paymentField.value.replace(/[^0-9\.]+/g,"");
remainder = remainder - paymentApplied;
index++;
paymentField = document.getElementById('invoiceBalance'+index);
}
while (e == paymentField) //set the selected elements value
{
var invoiceBalance = document.getElementById('in'+index).innerHTML.replace(/[^0-9\.]+/g,"");
if (parseFloat(remainder) > parseFloat(invoiceBalance))
e.value = parseFloat(invoiceBalance).toFixed(2).toLocaleString();
else
e.value = parseFloat(remainder).toFixed(2).toLocaleString();
index++;
paymentField = document.getElementById('invoiceBalance'+index);
}
while (paymentField != null) //blank out the rest of the input fields
{
paymentField.value = '';
index++;
paymentField = document.getElementById('invoiceBalance'+index);
}
e.select();
}
The concept here is to calculate the remaining balance and set the input field's value as the user focuses the fields.
The problem is that The "this" parameter is always set to the first Input element "invoiceBalance0". I'm expecting it to be set to the element referring to it in it's onFocus handler.
What am I not seeing?
I'm unable to duplicate the error you describe, but I did notice what appears to be a typo:
var invoiceBalance = document.getElementById('in'+index).innerHTML.replace(/[^0-9\.]+/g,"");
looks like it should be
var invoiceBalance = document.getElementById('invoiceAmount'+index).innerHTML.replace(/[^0-9\.]+/g,"");
function setBalance(e) //e should be an input field element
{
var balance = document.querySelector('[name="balance"]').value;
var remainder = balance;
var index = 0;
var paymentField = document.getElementById('invoiceBalance' + index); //get the first input payment element
while (paymentField != null && paymentField != e) //start with the first field and calculate the remaining balance
{
var paymentApplied = paymentField.value.replace(/[^0-9\.]+/g, "");
remainder = remainder - paymentApplied;
index++;
paymentField = document.getElementById('invoiceBalance' + index);
}
while (e == paymentField) //set the selected elements value
{
var invoiceBalance = document.getElementById('invoiceAmount' + index).innerHTML.replace(/[^0-9\.]+/g, "");
if (parseFloat(remainder) > parseFloat(invoiceBalance))
e.value = parseFloat(invoiceBalance).toFixed(2).toLocaleString();
else
e.value = parseFloat(remainder).toFixed(2).toLocaleString();
index++;
paymentField = document.getElementById('invoiceBalance' + index);
}
while (paymentField != null) //blank out the rest of the input fields
{
paymentField.value = '';
index++;
paymentField = document.getElementById('invoiceBalance' + index);
}
e.select();
}
<input type="hidden" name="balance" value="2500.0" />
<div id="invoiceAmount0">$500.00</div>
<input type="text" size="8" id="invoiceBalance0" name="invoiceBalance0" value="" onfocus="setBalance(this)" />
<div id="invoiceAmount1">$500.00</div>
<input type="text" size="8" id="invoiceBalance1" name="invoiceBalance1" value="" onfocus="setBalance(this)" />
<div id="invoiceAmount2">$500.00</div>
<input type="text" size="8" id="invoiceBalance2" name="invoiceBalance2" value="" onfocus="setBalance(this)" />
It's work after changing this line :
var invoiceBalance = document.getElementById('in'+index).innerHTML.replace(/[^0-9\.]+/g,"")
To :
var invoiceBalance = document.getElementById('invoiceBalance'+index).innerHTML.replace(/[^
0-9\.]+/g,"");
that because you don't have an id like in[index] but this form invoiceBalance[index], hope that will help See
Working Fiddle.

javascript: changing the name attribute dynamically

I have this script I'm working on and there's no errors on it but I want to add some functions on it like when I click the button it adds but I want the name attribute of the input text to be changed too.
Here's my script:
javascript:
var a = 1;
function add() {
var fContent = document.getElementById('1');
var sContent = document.getElementById('2');
if (a <= 10) {
a++;
var objTo = document.getElementById('m');
var divtest = document.createElement("div");
divtest.innerHTML = (sContent.innerHTML + a + fContent.innerHTML);
alert(divtest.innerHTML);
objTo.appendChild(divtest);
}
}
html:
<input type="button" onclick="add();" value="+" />
<div id="m">
<div id="1">
<input type="text" name="f">
<input type="text" name="l">
<input type="text" name="m">
</div>
<div id="2"></div>
</div>
OUTPUT:
2
<input type="text" name="f">
<input type="text" name="l">
<input type="text" name="m">
EXPECTED OUTPUT:
2
<input type="text" name="f2">
<input type="text" name="l2">
<input type="text" name="m2">
and so on...
You're not doing anything to change the name attributes. Trying to make those changes with html concatenation will get you into trouble. This will get you started:
(function() {
var a = 1;
// get a reference to the container
var container = document.getElementById("m");
// get a reference to the first row of input
var base = container.children[0];
document.querySelector("button").addEventListener("click", function(e) {
if(++a > 10) return;
// clone the first row of input
var clone = base.cloneNode(1);
// change the number text by setting the span's textContent
clone.children[0].textContent = a;
// set the names of the input fields
clone.children[1].name = "f" + a;
clone.children[2].name = "l" + a;
clone.children[3].name = "m" + a;
// add the new row to the container
container.appendChild(clone);
console.log(clone);
});
})();
<button type="button">+</button>
<div id="m">
<div><span>1</span><input type="text" name="f1"><input type="text" name="l1"><input type="text" name="m1"></div>
</div>
If you'd rather create the elements from scratch...
(function() {
var a = 1;
// get a reference to the container
var container = document.getElementById("m");
var input;
var span;
var div;
document.querySelector("button").addEventListener("click", function(e) {
if(++a > 10) return;
// create our div
div = document.createElement("div");
// create and append our span
span = document.createElement("span");
span.textContent = a;
div.appendChild(span);
// create and append inputs
["f","l","m"].forEach(function(n){
input = document.createElement("input");
input.name = n + a;
div.appendChild(input);
});
// append our div
container.appendChild(div);
console.log(div);
});
})();
<button type="button">+</button>
<div id="m">
<div><span>1</span><input type="text" name="f1"><input type="text" name="l1"><input type="text" name="m1"></div>
</div>

How to apply a class attribute to an HTML string (not rendered on the document)

I am am developing code for am automator to improve the project with several pages.
I have a textarea input where I can enter HTML and it shows me the HTML with the right structure.
HTML:
<textarea name="message">
<input type="text" value="TextTwo" id="texttwo"/>
<input type="text" value="DataOne" id="dataone"/>
<input type="text" value="NumberTwo" id="numbertwo"/>
<input type="text" value="TextOne" id="textone"/>
<input type="text" value="DataTwo" id="datatwo"/>
<input type="text" value="NumberOne" id="numberone"/>
</textarea>
<button>process</button>
JS/JQuery:
$('button').click(function () {
var code = $('textarea[name=message]').val();
if ($('#output').length < 1) {
$("body").append('<h2>Output</h2><textarea id="output" rows="10" cols="100"></textarea>');
}
$('#output').val(code);
});
I would like to apply classes following these rules:
The input that has the word "Text" value in applying the class = "text"
The input that has the word "Data" value in applying the class = "data"
The input that has the word "Number" value in applying the class = "number"
An example of how the code would output in textarea
<input type="text" value="TextTwo" id="texttwo" class="text" />
<input type="text" value="DataOne" id="dataone" class="data" />
<input type="text" value="NumberTwo" id="numbertwo" class="number" />
<input type="text" value="TextOne" id="textone" class="text"/>
<input type="text" value="DataTwo" id="datatwo" class="data" />
<input type="text" value="NumberOne" id="numberone" class="number" />
DEMO CODE
What is a good approach to do this using JQuery?
I updated your fiddle and had this code working -- Can't give you a link since I don't actually have a fiddle account:
$('button').click(function () {
var code = $('textarea[name=message]').val();
// The best thing to do here is to turn that string of HTML into
// DOM elements and let the browser do the work.
var elms = jQuery.parseHTML(code);
var result = "";
// Now that we've processed the HTML into an array, work with it.
for (var i = 0; i < elms.length; i++) {
var el = elms[i];
if (el.tagName && el.tagName.toLowerCase() === "input") {
// Great! We we have an 'input' element.
var val = el.value;
if (val.indexOf("Text") !== -1) {
el.className = "text";
}
if (val.indexOf("Data") !== -1) {
el.className = "data";
}
if (val.indexOf("Number") !== -1) {
el.className = "number";
}
}
if (el.nodeType === 3) {
// Handle text nodes
result += el.nodeValue;
} else {
result += el.outerHTML;
}
}
if ($('#output').length < 1) {
$("body").append('<h2>Output</h2><textarea id="output" rows="10" cols="100"></textarea>');
}
$('#output').val(result);
});
Under the assumption that all the html in the textarea is valid, What we can do is just build the html into a div and then format the html with jQuery. After this is done just get the content and put it in the textarea.
$('button').click(function () {
var code = $('textarea[name=message]').val(),
$code = $('<div />').html(code),
classes = {'Text': 'text', 'Data': 'data', 'Number': 'number'};
if ($('#output').length < 1) {
$("body").append('<h2>Output</h2><textarea id="output" rows="10" cols="100"></textarea>');
}
$('input', $code).each(function(){
var t = this,
$t = $(this);
for(key in classes){
if(t.value.indexOf(key) > -1){
$t.addClass(classes[key]);
return;
}
}
});
$('#output').val($code.html());
});
http://jsfiddle.net/LC5y3/4/
DEMO
$('button').click(function () {
var code = $.parseHTML($('textarea[name=message]').val());
console.log(code);
var newCode = "";
code = $.grep(code, function (n, i) {
if (n.nodeValue) {
return n.nodeValue.trim()
} else {
return (n.outerHTML && n.outerHTML.trim())
}
});
for (var i = 0; i < code.length; i++) {
var element=$(code[i]);
element.addClass(element.attr("type"));
newCode += code[i].outerHTML;
}
console.log(newCode);
console.log(code);
if (!$('#output').length) {
$("body").append('<h2>Output</h2><textarea id="output" rows="10" cols="100"></textarea>');
}
$('#output').val(newCode);
});
You can use the attribute contains selector.
jsFiddle
$('input[id*="text"]').addClass('text');
$('input[id*="number"]').addClass('number');
$('input[id*="data"]').addClass('data');
You can dynamically build the elements:
$('input').addClass('className').attr('value','number');

Categories

Resources