why is Object.keys show id as key? - javascript

HTML
<input type="checkbox"/>
<input type="button" id="btn" value="Click">
JS
var a = document.getElementsByTagName('input');
console.log(Object.keys(a));
for (var i = 0; i < Object.keys(a).length; i++) {
console.log(a[i]);
}
in console there are three keys is showing 0,1,'btn' . why is id showing in this object and how can i avoid this .

When you have a collection from getElementsByTagName() you can refer to an item either by its index or its ID.
So a[0] or a.btn.
I suspect you just want to iterate over all of them, which is just your basic for loop from Programming 101:
for(var i = 0; i < a.length; i++) {
// a[i]
}
That's what .length is there for!

Related

JavaScript Loop Inside Loop Issue

I have loop inside loop like this:
var len = bolumlerUnique.length;
function bolumleriGonder() {
for (i = 0; i < bolumlerUnique.length; i++) {
elementBolumler = $("[bolumid=" + bolumlerUnique[i] + "]:checked");
console.log(elementBolumler);
for (j = 0; j < len; j++) {
console.log(elementBolumler[j])
}
}
}
bolumlerUnique is an array --> ["1", "2", "3", "4"]I have radio inputs and find elements with this code
$("[bolumid=" + bolumlerUnique[i] + "]:checked");
But in the second loop console.log writes undefined.
But elementBolumler is defined global variable.
Check your len variable is have a value it must work with your codes.
in the second loop console.log writes undefined.
To answer the question as (almost) presented: "why do I get undefined with $()[j]?"
Within jquery, if you attempt to get an element by index that's larger than the number of items in the jquery collection, you get undefined (not array out of bounds as it's not an array), ie:
var divs = $(".d");
console.log(divs[0])
console.log(divs[1]) // undefined
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="d">d1</div>
The issue is with:
var len = bolumlerUnique.length;
for (j = 0; j < len; j++) {
When you iterate over
$("[bolumid=" + bolumlerUnique[i] + "]:checked")
it will only have as many items as are checked that match the one id. So it's highly likely that
elementBolumler.length !== len
As noted in the comments to the question, [bolumid=" + bolumlerUnique[i] + "] is a radio so it will only ever return one item.
Your logic for the inner loop index len is incorrect, but it's not clear what it should be - possibly:
elementBolumler.length
as in:
function bolumleriGonder() {
for (i = 0; i < bolumlerUnique.length; i++) {
elementBolumler = $("[bolumid=" + bolumlerUnique[i] + "]:checked");
console.log(elementBolumler);
for (j = 0; j < elementBolumler.length; j++) {
console.log(elementBolumler[j])
}
}
}
const checkboxesIWantToMessWith = [2, 4, 6]
checkboxesIWantToMessWith.forEach(id => {
const checkbox = document.querySelector(`input[bolumid="${id}"]`)
if (checkbox.checked) {
// Do my stuff
console.log(`checkbox bolumid="${id}" is checked`)
} else {
// Do other stuff
console.log(`checkbox bolumid="${id}" is NOT checked`)
}
})
<input type="checkbox" bolumid="1" checked />
<input type="checkbox" bolumid="2" checked />
<input type="checkbox" bolumid="3" checked />
<input type="checkbox" bolumid="4" />
<input type="checkbox" bolumid="5" checked />
<input type="checkbox" bolumid="6" checked />

How can i set the attribute of an element in MVC

my view:
<........id="S" labelPos="1" labelText=""/>
I want to set the value for labelText dynalically from the controller. i have tried the following but it did not work:
for (var i = 0; i < keys.length; i++) {
var c = labelText[keys[i]].StreetName;
var d = document.getElementsByTagName("S");
d.setAttribute("labelText", c);
}
Please change your document.getElementsByTagName("S");to document.getElementById("S") see if it works.
for (var i = 0; i < keys.length; i++) {
var c = labelText[keys[i]].StreetName;
var d = document.getElementById("S");
d.setAttribute("labelText", c);
}
First query your elements in DOM, querying in loop is not good practice, so:
var elements = document.getElementsByTagName("span");//span is example element
Or:
var elements = document.quertSelectorAll("selector");//your elements by selector
Use it in loop
for (var i = 0; i < elements.length; i++) {
elements[i].setAttribute("labelText", labelText[elements[i].getAttribute("labelPos")].StreetName);
}
I came to the conclusion that Your labelPos attribute is index of labelText array, this would be logical. So in above code I set attrbute from labelText array by labelPos value as key.
Second possibility if DOM elements are in the same order as labelText array:
for (var i = 0; i < elements.length; i++) {
//we take i element in DOM and set it StreetName from i element in labelText array
elements[i].setAttribute("labelText", labelText[i].StreetName);
}

Adding up all combinations of number in an array

I am trying to write a program in javascript that gets an unspecified number of numbers out of a html textarea and tries all combinations (adding all numbers with eachother) to see if it mathches a number you specified.
Now I can make an array out of the string in the textarea and using for loops I add these up (see below code). The problem how can you do this for an unspecified number of numbers that are to be added up (e.g. adding up 7 different number if you enter 7 numbers in textarea)? I was thinking of using a second array and, which gets the numbers to add up out of the first loop. And then make te lenght of the loop variable by using a for loop with the lenght of the array containing all numbers (lines in my example) as endvalue.
How can I fill in the values of this 2nd array, making sure all combinations are used?
By the way, I wanted this code because I am a auditor. Sometimes a client reverses a couple of amounts in one booking, without any comment. This code will make it a lot easier to check what bookings have been reversed
edit: The awnser of cheeken seems to be working I only have one remark. What if multiple sub sets of your power set added up result in the number you are looking for? e.g.:findSum([1,2,3,4,5],6) can result [1,2,3] but also [2,4] or [1,5]. is it possible to let the function return multiple sub sets?
Found the answer my self :)
I replaced code
return numberSet;
By
document.getElementById("outp").value=document.getElementById("outp").value+ numberSet +"\n";
Thank you very much Cheeken
One more additional question. How do i format the input for parsing that function? The code below doesn't seem to work. inp is the ID of the textarea where the input is (the numbers are seperated with a semicolumn. The variable ge works so there is no problem there (tested it with [1,2,3,4] and it worked. What is wrong with this code?
re edit:
found the solution. The array needed to be parsed as a floating number added this code.`
for (var i=0; i < lines.length; i++) {
lines[i]= parseFloat(lines[i]);
}
findSum(document.getElementById("inp").value.split(";"), ge);
Code:
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript">
function powerset(arr) {
var ps = [[]];
for (var i=0; i < arr.length; i++) {
for (var j = 0, len = ps.length; j < len; j++) {
ps.push(ps[j].concat(arr[i]));
}
}
return ps;
}
function sum(arr) {
var total = 0;
for (var i = 0; i < arr.length; i++)
total += arr[i];
return total
}
function findSum(numbers, targetSum) {
var numberSets = powerset(numbers);
for (var i=0; i < numberSets.length; i++) {
var numberSet = numberSets[i];
if (sum(numberSet) == targetSum)
document.getElementById("outp").value=document.getElementById("outp").value+ numberSet +"\n";
}
}
function main()
{
ge= document.getElementById("getal").value;
findSum([1,1,0.5,0.1,0.2,0.2], ge);
}
</script>
</head>
<body>
<input type="button" onclick="main()" value="tel" /><input type="text" id="getal" /><br>
input<br><textarea id="inp" ></textarea><br>
output<br><textarea id="outp" ></textarea><br>
document.getElementById("inp").value.split(";")
</body>
</html>
More concretely, you're looking for a particular sum of each set in the power set of your collection of numbers.
You can accomplish this with the following bit of code.
function powerset(arr) {
var ps = [[]];
for (var i=0; i < arr.length; i++) {
for (var j = 0, len = ps.length; j < len; j++) {
ps.push(ps[j].concat(arr[i]));
}
}
return ps;
}
function sum(arr) {
var total = 0;
for (var i = 0; i < arr.length; i++)
total += arr[i];
return total
}
function findSum(numbers, targetSum) {
var numberSets = powerset(numbers);
for (var i=0; i < numberSets.length; i++) {
var numberSet = numberSets[i];
if (sum(numberSet) == targetSum)
return numberSet;
}
}
Example invocation:
>> findSum([1,2,3,4,5],6)
[1, 2, 3]
>> findSum([1,2,3,4,5],0)
[]
>> findSum([1,2,3,4,5],11)
[1, 2, 3, 5]
If you'd like to collect all of the subsets whose sum is the value (rather than the first one, as implemented above) you can use the following method.
function findSums(numbers, targetSum) {
var sumSets = [];
var numberSets = powerset(numbers);
for (var i=0; i < numberSets.length; i++) {
var numberSet = numberSets[i];
if (sum(numberSet) == targetSum)
sumSets.push(numberSet);
}
return sumSets;
}
Example invocation:
>> findSums([1,2,3,4,5],5);
[[2,3],[1,4],[5]]
>> findSums([1,2,3,4,5],0);
[[]]

javascript trying to remove all things with certain tags

I'm trying to use javascript to remove everyhting with button or input tags from a page... So far my code removes some of them and I dont know why. It only removes one checkbox out of many, and 2 buttons (there are 3 buttons)
var buttons = document.getElementsByTagName("button");
for (var j = 0; j < buttons.length ; j++)
{
buttons[j].parentNode.removeChild(buttons[j]);
}
var checkboxes = document.getElementsByTagName("input");
for (var j = 0; j < buttons.length ; j++)
{
checkboxes[j].parentNode.removeChild(checkboxes[j]);
}
var checkboxes = document.getElementsByTagName("input");
for (var j = 0; j < buttons.length ; j++) // You use the wrong variable here
{
checkboxes[j].parentNode.removeChild(checkboxes[j]);
}
Should be;
for (var j = 0; j < checkboxes.length ; j++)
Regarding to the undeleted button, maybe it's because it's an input type="button" and not a <button>?
Note that document.getElementsByTagName("input"); will get and delete later all the inputs, not just the checkboxes!
May I suggest you using a javascript library like jQuery? you could have done this will one line of code with no problems:
$('input[type="button"], input[type="checkbox"], button').remove();
document.getElementsByTagName returns a live NodeList. That means, when you remove the first element, a) the length decreases and b) the (first) item of the list is shifted.
There are two possibilities to work around that:
always remove the last element. The NodeList is in document order, so that will work:
for (var i=buttons.length-1; i>=0; i--) // var i=buttons.length; while(i--)
buttons[i].parentNode.removeChild(buttons[i]);
always remove the first element, and don't run an index until the length:
while (buttons.length) // > 0
buttons[0].parentNode.removeChild(buttons[0]);
It also would work with jQuery and co, because they copy the NodeList items in a static array. You can do that yourself as well:
var staticButtons = Array.prototype.slice.call(buttons);
for (var i=0; i<staticButtons.length; i++)
staticButtons[i].parentNode.removeChild(staticButtons[i]);
or you use a document selection method that returns a static NodeList right away, like querySelector:
var staticList = document.querySelectorAll("button, input");

getElementsByName won't loop through entire array

The following code executes on the press of a button. It works fine alerting one string of the getElementsByName array, but when introduced to a loop, it still only alerts the first string value, and nothing more:
function checkvals() {
var input = document.getElementsByName('ModuleTitle', 'ModuleCode', 'BuildingName', 'Day');
var i = 0;
for (i = 0; i <= input.length; i++){
alert(input[i].value);
}
}
That's because getElementsByName only accepts one argument, so it's only fetching the first name.
You can build a full collection like this...
var names = ['ModuleTitle', 'ModuleCode', 'BuildingName', 'Day'];
var input = [];
for(var i = 0; i < names.length; i++) {
var name_els = document.getElementsByName(names[i]);
for(var j = 0; j < name_els.length; j++) {
input.push(name_els[j]);
}
}
Then loop over the input Array, (or just do your work in the inner loop).
Additionally, you have a bug.
This...
for (i = 0; i <= input.length; i++){
should be this...
for (i = 0; i < input.length; i++){
...otherwise, you'll go one past the last index.
That's because getElementsByName only takes a single name argument, and returns all elements with that value for their name attribute. (See https://developer.mozilla.org/en/DOM/document.getElementsByName.) If you have multiple names to look up, you'll have to call it multiple times.

Categories