getElementsByName won't loop through entire array - javascript

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.

Related

For loop lasts infinitely javascript

I have a problem in my code:
var row = ["1","2","3","4","5"];
var column = ["1","2","3","4","5"];
var arrayLength = row.length;
var arrayLength2 = column.length;
for (var i = 0; i < arrayLength; i++) {
for (var e = 0; e < arrayLength2; e++) {
var samples = document.querySelectorAll('[data-row-id="'+row[i]+'"][data-column-id="'+column[e]+'"]');
for(var i = 0; i < samples.length; i++) {
var sample = samples[i];
sample.setAttribute('data-sample-id', row);
console.log("Colore cambiato");
}
}
}
When i run it, the cycle lasts infinitely and the console.log is called up a lots of times
Where is the error? Thanks!
The problem is that your inner-most loop uses the same i looping variable as your outer most loop and it's constantly changing i so that the outer loop never finishes.
Change the variable on your inner loop to a different identifier that you aren't already using in the same scope.
Youre using same loop i twice nested so it runs infinitely coz it always resets i in inner loop
use something else instead like k
for(var k = 0; k < samples.length; k++) {
var sample = samples[k];
sample.setAttribute('data-sample-id', row);
console.log("Colore cambiato");
}

How to check the visibility of a datatable row?

Is it possible to check the visibility of the particular datatable row?
I found only isColumnVisible and getVisibleCount, but both of them are irrelevant and as far as I can see, there's no such solution for the rows.
How can I do such thing? For instance, after the filtering I can get all data items, but that's all. It's the only idea I've come up with:
onAfterFilter:function(){
var dataId = this.data.pull;
var keys = Object.keys(dataId);
for (var i = 0; i < keys.length; i++){
console.log(this)
}
}
http://webix.com/snippet/c6ecdcd5
Ok it feels like a long way of doing this. And I've not done anything other than just get it to work.
But you will find all of the ids you need in this.data.order so the following code puts all the filtered items into filteredObjs
var dataId = this.data.pull;
var keys = Object.keys(dataId);
var filteredIds = this.data.order;
var filteredObjs = [];
for (var i = 0; i < filteredIds.length; i++) {
for (var j = 0; j < keys.length; j++) {
if (filteredIds[i] === dataId[keys[j]].id) {
filteredObjs.push(dataId[keys[j]]);
}
}
}
console.log(filteredObjs);
Not saying its perfect. But its a start...
For starters you need to change console.log(this) to console.log(keys[i])
As an alternative to the data-based solution made by #ShaunParsons I found that it's possible to check the visibility through the getItemNode function, as the nodes of the invisible items are undefined.
http://webix.com/snippet/4f31a5b5
onAfterFilter:function(){
var dataId = this.data.pull;
var keys = Object.keys(dataId);
for (var j = 0; j < keys.length; j++) {
console.log(this.getItemNode(keys[j]))
}
}

Javascript for loop without recalculating array's length

In my Javascript reference book, for loops are optimized in the following way:
for( var i = 0, len = keys.length; i < len; i + +) { BODY }
Apparently, doing "len = keys.length" prevents the computer from recalculating keys.length each time it goes through the for loop.
I don't understand why the book doesn't write "var len = keys.length" instead of "len = keys.length"? Isn't the book making "len" a global variable, which isn't good if you're trying to nest two for-loops that loop through two arrays?
E.g.
for( var i = 0, len = keys.length; i < len; i + +) {
for (var i = 0; len = array2.length; i < len; i++) {
}
}
Source: Flanagan, David (2011-04-18). JavaScript: The Definitive Guide: Activate Your Web Pages (Definitive Guides) (Kindle Locations 6992-6998). O'Reilly Media. Kindle Edition.
You can chain variable declarations like this
var i = 0, foo="bar", hello = "world"
Which is close to the same thing as
var i = 0;
var foo = "bar";
var hello = "world";
So this
for(var i = 0, len = keys.length; i < len; i++)
Is the same as
var len = keys.length;
for(var i = 0; i < len; i++)
I like to avoid .length altogether and use something like
var keys = /* array or nodelist */, key, i;
for(i = 0; key = keys[i]; i++)
This will cause the for loop to end as soon as key resolves to undefined.
Now you can use key instead of keys[i]
As a side note, your second example would never work as all of the variables defined in the first for statement would be overwritten by the second, yielding unexpected results. You can nest for loops, but you have to use different variable names.
AS Ankit correctly mentioned in the comments of the question, it is a shorthand. And moreover, if I am correct, javascript is functionally scoped and not block scoped, so you are overwriting the len declared in the outer for loop while re-declaring it in the inner one.
In Javascript each time you instantiate it's a heavy cost. Using one var and short hand commas to create multiple variables is much more efficient.
Your example using only one var to create a variable.
for (var i = 0, len = array2.length; i < len; i++) {
//loop
}
The alternative is to var up the len variable outside the loop.
var len = array2.length;
for (var i = 0; i < len; i++) {
//loop
}
Now you have two separate "var" instances.
I personally like to declare my var at the beginning.
var len = array2.length,
i = 0;
for(i = 0; i < len; i++){
//First loop
}
//So if I use more than one for loop in a routine I can just reuse i
for(i = 0; i < 10; i++){
//Second loop
}
Hope that helps explain.

Populating a select element with comma-separated values using for loop

I have a bunch of comma-separated values stored as strings in a JSON file. My aim is to split these values to populate a select element which is based on Selectize.js. Code (excerpt) looks as follows:
var options = {};
var attr_split = data.attributes['Attribute1'].split(",");
var options_key;
for (var i = 0; i < attr_split.length; i++) {
options_key = attr_split[i]
}
var options_values = {
value: options_key,
text: options_key,
}
if (options_key in options)
options_values = options[options_key];
options[options_key] = options_values;
$('#input').selectize({
options: options,
});
Although this seems to work, the output in the select element only shows the last iterations done by the for loop. As per here
and here, I've tried
for (var i = 0; i < attr_split.length; i++) {
var options_key += attr_split[i]
}
but this throws me undefined plus all concatenated strings without the separator as per the following example:
undefinedAttr1Attr2Attr3
When I simply test the loop using manual input of the array elements everything appears fine:
for (var i = 0; i < attr_split.length; i++) {
var options_key = attr_split[0] || attr_split[1] || attr_split[2]
}
But this is not the way to go, since the number of elements differs per string.
Any idea on what I'm doing wrong here? I have the feeling it's something quite straightforward :)
when you declare 'options_key' ,you are not initializing it.so its value is undefined .when you concatenate options_key += attr_split[i] .in first iteration options_key holds undefined.so only you are getting undefinedAttr1Attr2Attr3.
so declare and initialize options_key like.
var options_key="";
and in your loop
for (var i = 0; i < attr_split.length; i++)
{
options_key = attr_split[i]
}
Everytime you replace options_key with value of attr_split[i].so after the loop it will contain last element value.corrected code is
for (var i = 0; i < attr_split.length; i++)
{
options_key += attr_split[i]
}
Just change var options_key; to var options_key="";
The reason you are getting undefined is because you have not defined the variable properly.
Here is a working example
var attr_split = "1,2,3,4".split(",");
var options_key="";
for (var i = 0; i < attr_split.length; i++) {
options_key += attr_split[i]
}
alert(options_key);
var options_values = {
value: options_key,
text: options_key
}
alert(options_values);

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");

Categories