how to run JavaScript code when checkbox is checked - javascript

There is a button that passes value to another input field. but now I want to pass value if checkbox is checked.
const copy = (id) => {
var value = document.getElementById("col" + id + "-input").value
var list = document.getElementsByClassName("col" + id + "-input")
for (i = 0; i < list.length; i++)
list[i].value = value
}
document.getElementById("col1-button").addEventListener("click", () => copy(1))
<a type="button" id="col1-button">OK</a>

a does not have a type.
Pass the number in a data-attribute then you can reuse the script for more than one button
I guessed the HTML. Next time post a complete example please
const copy = e => {
const tgt = e.target;
if (tgt.type !=="checkbox" || !tgt.checked) return;
const id = e.target.dataset.id;
var value = document.getElementById("col" + id + "-input").value
document.querySelectorAll(".col" + id + "-input").forEach(inp => inp.value = value);
};
document.getElementById("col1-button").addEventListener("click",copy)
<input type="text" id="col1-input" />
<input type="text" class="col1-input" />
<input type="text" class="col1-input" />
<input type="text" class="col1-input" />
<label><input type="checkbox" id="col1-button" data-id="1" />OK</label>

Related

Javascript loop array for form validation

I have a table form with some rows, that are controlled by user. Meaning they can add as more as they want. Let's pretend user requested 5 rows and i need to check if they all have values.
function validateForm() {
var lastRowInserted = $("#packageAdd tr:last input").attr("name"); // gives me "packageItemName5"
var lastCharRow = lastRowInserted.substr(lastRowInserted.length - 1); // gives me 5
var i;
for (i = 1; i <= lastCharRow; i++) {
var nameValidate[] = document.forms["packageForm"]["packageItemName"].value;
if(nameValidate[i].length<1){
alert('Please fill: '+nameValidate[i]);
return false;
}
}
}
How can i receive packageItemName1 to 5 values in a loop so then I can use to validate them. Want the loop to process this code
var nameValidate[] = document.forms["packageForm"]["packageItemName1"].value;
var nameValidate[] = document.forms["packageForm"]["packageItemName2"].value;
var nameValidate[] = document.forms["packageForm"]["packageItemName3"].value;
var nameValidate[] = document.forms["packageForm"]["packageItemName4"].value;
var nameValidate[] = document.forms["packageForm"]["packageItemName5"].value;
Like this
const validatePackageItems = () => {
const nameValidate = $("form[name=packageForm] input[name^=packageItemName]"); // all fields with name starting with packageItemName
const vals = nameValidate.map(function() { return this.value }).get(); // all values
const filled = vals.filter(val => val.trim() !== ""); // all values not empty
console.log("Filled", filled, "= ", filled.length, "filled of", vals.length)
return filled.length === vals.length
};
$("[name=packageForm]").on("submit",(e) => {
if (!validatePackageItems()) {
alert("not valid");
e.preventDefault();
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<form name="packageForm">
<input type="text" name="packageItemName1" value="one" /><br/>
<input type="text" name="packageItemName2" value="two" /><br/>
<input type="text" name="packageItemName3" value="" /><br/>
<input type="text" name="packageItemName4" value="four" /><br/>
<input type="submit">
</form>
You can use string interpolation to get the key dynamically:
for (let i = 1; i < 6; i++) {
const currentValue = document.forms.packageForm[`packageItemName${i}`]
console.log('current value:', currentValue)
}

Create an array of selected radio button values

I have few radio buttons:
<input type="radio" value="####.###/resources/videos/7.mp4">
<input type="radio" value="####.###/resources/videos/8.mp4">
<input type="radio" value="####.###/resources/videos/9.mp4">
How can I make an array containing the selected values like following:
var videos = ["./resources/videos/7.mp4",
"./resources/videos/1.mp4",
"./resources/videos/2.mp4",
"./resources/videos/3.mp4"];
Onclick push the value of radio in array
var arr=[];
$('input').click(function(){
arr.push("."+$(this).val().split('####.###')[1])
console.log(arr);
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input type="radio" value="####.###/resources/videos/7.mp4">Video1
<input type="radio" value="####.###/resources/videos/8.mp4">Video2
<input type="radio" value="####.###/resources/videos/9.mp4">Video3
I would add a change event listener, that checks if the input got checked or unchecked and would add it or remove it from the list.
var originalVideoList = ["./resources/videos/7.mp4",
"./resources/videos/1.mp4",
"./resources/videos/2.mp4",
"./resources/videos/3.mp4"
];
var videos = document.querySelector("#videos");
var result = document.querySelector("#result");
var template = "<li><label for='{0}'>Video {1}</label><input id='{0}' type='checkbox' onchange='onChange()'/></li>";
var selectedArray = [];
// Set up html
videos.innerHTML = originalVideoList.map(function(video) {
return template.replace(/\{0\}/g, video).replace(/\{1\}/g, video.split("/").pop());
}).join("");
// triggered on input change
function onChange() {
selectedArray = toArray(document.querySelectorAll("li>input:checked")).map(function(item) {
return item.id.replace("####.###", ".");
});
result.innerHTML = selectedArray.map(function(video) {
return "<li>" + video + "</li>";
}).join("");
}
// Same as [...input]
function toArray(input) {
var result = [];
for (var index = 0; index < input.length; index++) result[index] = input[index];
return result;
}
<ul id="videos"></ul>
<ul id="result"></ul>

mergeMap() RXJS 3 observables

I watched a tutorial on how to use mergeMap() on 2 observables but I'm still very unclear on how to use it with more than 2 observables.
Here is the link to the tutorial:
https://www.youtube.com/watch?v=b59tcUwfpWU&t=1s
Here is the code for 3 observables to concatenate three inputs and display dynamically on html.
var input1 = document.querySelector('#input1');
var input2 = document.querySelector('#input2');
var input3 = document.querySelector('#input3');
var span = document.querySelector('span');
var obs1 = Rx.Observable.fromEvent(input1, 'input');
var obs2 = Rx.Observable.fromEvent(input2, 'input');
var obs3 = Rx.Observable.fromEvent(input3, 'input');
obs1.mergeMap((event1) => {
return obs2.map((event2) => {
return event1.target.value + ' ' + event2.target.value;
});
}).mergeMap((result) => {
return obs3.map((event3) => {
return result + ' ' + event3.target.value;
});
}).subscribe((combinedValue) => {
console.log(combinedValue);
return span.textContent = combinedValue;
})
<script src="https://unpkg.com/#reactivex/rxjs#5.3.0/dist/global/Rx.js"></script>
<input type="text" id="input1">
<input type="text" id="input2">
<input type="text" id="input3">
<p>Combined value: <span></span></p>
My problem here is that when i type in the first and second inputs, the display does not dynamically show the changes until I enter something into the third input.
My current understanding of mergeMap() is that it flattens a sequence of sequence of observables into a sequence of observables.
I think you want the operator combineLatest().
To make things simpler, I would map the event.target.value after each fromEvent, and perhaps throw in the startWith('') since nothing is happening until the user types.
console.clear()
var input1 = document.querySelector('#input1')
var input2 = document.querySelector('#input2');
var input3 = document.querySelector('#input3');
var span = document.querySelector('span');
var obs1 = Rx.Observable.fromEvent(input1, 'input')
.map(e=>e.target.value)
.startWith('')
var obs2 = Rx.Observable.fromEvent(input2, 'input')
.map(e=>e.target.value)
.startWith('')
var obs3 = Rx.Observable.fromEvent(input3, 'input')
.map(e=>e.target.value)
.startWith('')
Rx.Observable.combineLatest(obs1,obs2,obs3)
.map(([val1,val2,val3]) => val1 + ' ' + val2 + ' ' + val3)
.subscribe((combinedValue) => {
console.log(combinedValue);
return span.textContent = combinedValue;
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/5.5.7/Rx.js"></script>
<input type="text" id="input1">
<input type="text" id="input2">
<input type="text" id="input3">
<p>Combined value: <span></span></p>

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.

How to seperate the values of textbox so that I can sort by each value

I have a textbox where the user can input a value into a listbox. Then, I have buttons to either Delete that value, or Sort the value.
My problem is that I want the value to be sorted by those 2 separated values. For example, the user would enter City=Chicago in the textbox. And there would be 2 sort buttons, to 'Sort by City' and 'Sort by Value' where value in this case is Chicago.
So after hours of trying I can't figure out how to:
1. Restrict the user to only be able to enter a value like %=% (e.g. City=Chicago)
2. Have separate sort buttons for the values on either side of the equal sign
http://jsfiddle.net/uudff585/6/
<div class='teststyles'>
<h3>Test</h3>
Name/Value Pair
<br />
<input id="PairTextbox" type="text" value="city" />=<input id="PairTextbox1" type="text" />
<input type="button" value="Add" id="addButton" />
<br />
<br />Name/Value Pair List
<br />
<select multiple="multiple" id="PairListbox"></select>
<input type="button" value="Sort By Name" sort-type="0" id="sortName">
<input type="button" value="Sort By Value" sort-type="1" id="sortValue"><br>
<input type="button" value="Delete" id="deleteButton" />
Script:
var listArray = [];
function addNewItem() {
console.log("ok2");
var textbox = document.getElementById('PairTextbox');
var textbox1 = document.getElementById('PairTextbox1');
var listbox = document.getElementById('PairListbox');
var newOption = document.createElement('option');
newOption.value = listArray.length-1; // The value that this option will have
newOption.innerHTML = textbox.value + "=" + textbox1.value; // The displayed text inside of the <option> tags
listbox.appendChild(newOption);
listArray.push([textbox.value, textbox1.value, ]);
}
function deleteItem() {
var listbox = document.getElementById('PairListbox');
if (listbox.selectedIndex != -1) {
console.log(listbox.selectedIndex);
delete listArray[listbox.value];
listbox.remove(listbox.selectedIndex);
}
}
function sortItems(e) {
var sorttype = e.target.getAttribute("sort-type");
var $listbox = document.getElementById('PairListbox');
var $options = listArray.map(function (option) {
return option;
});;
$options.sort(function (a, b) {
var an = a[sorttype],
bn = b[sorttype];
if (an > bn) {
return 1;
}
if (an < bn) {
return -1;
}
return 0;
});
$listbox.innerHTML = "";
$options.forEach(function ($option, index) {
var newOption = document.createElement('option');
newOption.value = index; // The value that this option will have
newOption.innerHTML = $option[0] + "=" + $option[1]; // The displayed text inside of the
$listbox.appendChild(newOption);
});
}
document.getElementById('addButton').addEventListener('click', addNewItem);
document.getElementById('sortName').addEventListener('click', sortItems);
document.getElementById('sortValue').addEventListener('click', sortItems);
document.getElementById('deleteButton').addEventListener('click', deleteItem);
For those who would like to use jQuery, validation and auto-sorting this FIDDLE. The HTML is:
<div class='teststyles'>
<h3>Test</h3>
<p>Name/Value Pair</p>
<p><input id="PairTextbox" type="text" /> <input type="button" value="Add" id="addButton" /></p>
<p>Name/Value Pair List</p>
<p><select multiple="multiple" id="PairListbox"></select></p>
<p>
<input id="byname" type="radio" name="sortby" value="name" checked="checked" /> <label for="byname">sort by name</label><br />
<input id="byvalue" type="radio" name="sortby" value="value" /> <label for="byvalue">sort by value</label>
</p>
<p><input type="button" value="Delete selected" id="deleteButton" /></p>
</div>
and the script:
// Keep your pairs in memory
var pairs = [];
// Keep record of dynamic elements
var listbox = $('#PairListbox');
var textbox = $('#PairTextbox');
var sortInput = $('input[name=sortby]');
function sortItems() {
sortType = sortInput.filter(':checked').val();
if ( sortType=='name' ) {
// Sort by key
console.log( 'sort by key' );
pairs = pairs.sort(function (a, b) {
return a.k.localeCompare(b.k);
});
} else {
// Sort by value
console.log( 'sort by val' );
pairs = pairs.sort(function (a, b) {
return a.v.localeCompare(b.v);
});
};
console.log( pairs );
console.log( '----------' );
};
function printItems() {
var optionsHtml = '';
$.each(pairs, function(i, item) {
optionsHtml += '<option value="' + item.k + '=' + item.v + '">' + item.k + '=' + item.v + '</option>';
});
listbox.html(optionsHtml);
};
// Customize validation of new input
function validateInput() {
var str = textbox.val().replace(/\s+/g, '_');
var splited = str.split('=');
if (splited.length == 2 && splited[0] && splited[1]) {
// Maybe also check if pair already exists in array?
pairs.push({
k: splited[0],
v: splited[1]
});
return true;
} else {
false;
};
}
function addNewItem() {
if (validateInput()) {
sortItems();
printItems();
} else {
alert('Wrong input value!');
}
}
function deleteItem() {
var selectedItems = listbox.find('option:selected');
selectedItems.each(function(i) {
var thisItem = $(this);
var thisValueSplit = thisItem.val().split('=');
pairs = pairs.filter(function (el) {
return !(el.k==thisValueSplit[0] && el.v==thisValueSplit[1]);
});
printItems();
});
}
$('#addButton').on('click', addNewItem);
$('#deleteButton').on('click', deleteItem);
sortInput.on('change', function(e) {
sortItems();
printItems();
});

Categories

Resources