Javascript issue on getelementbytagname - javascript

I'm having some trouble with this code:
var lista_input = document.getElementsByTagName("input");
console.log(lista_input);
console.log(lista_input[0]);
The first log correctly show me:
[item: function]
0: input
1: input
length: 2
__proto__: NodeList
but the second log show me:
undefined
I don't understand the reason,it could show me the first element input in dom!

The problem occurs from the fact that the return value of document.getElementsByTagName is a live NodeList:
var l = document.getElementsByTagName('div');
console.log(l[0]); // undefined
var d = document.createElement('div');
document.body.appendChild(d);
console.log(l[0]); // div
Combine that with the fact that you call the code before the document is ready (so before there are items in the list) and the known bug in the Console code that can show objects in a state after the call to console.log is made and you have the exact behavior you are experiencing.
To reiterate:
var lista_input = document.getElementsByTagName("input");
// lista_input is a live NodeList with 0 elements
console.log(lista_input); // will print the lista_input object at a later point
console.log(lista_input[0]); // will print undefined at a later point
/* time passes, dom is loaded */
// lista_input now has the inputs you expect it to have
/* time passes */
// logs are now shown in Console
EDIT: To get a good log, you can stringify the object when logging it, turning it into a primitive value that gets logged correctly:
var lista_input = document.getElementsByTagName("input");
console.log(JSON.stringify(lista_input)); // {"length":0} - empty list
console.log(JSON.stringify(lista_input[0])); // undefined
PS:
Link to a blog post explaining the Console bug:
http://techblog.appnexus.com/2011/webkit-chrome-safari-console-log-bug/
Link to a question requesting a fix to the Console bug:
How can I change the default behavior of console.log? (*Error console in safari, no add-on*)

Related

Array.from() with HTMLcollection does not seem to work in Chrome browser

I have a JavaScript piece of code that works on all browsers (even IE) but fail with Chrome on my HUAWEI P8 Lite with Android 6.
Chrome is version 71.0.3578.99.
The faulty code is var class_arr = Array.from(class); where class is a HTMLcollection.
It seems like Array.from() is failing although it should be supported by Chrome on mobile.
Also, I've noticed that this same code used to work one update ago, and not two updates ago strangely.
You can test the problem with this URL (of course this won't be valid as long as if I'll find a solution to my problem). You need to open the sidebar on the left and try to zoom in the map with the Plus or Minus button.
EDIT
Here is the code where I use Array.from():
export function updateSlider(all_sliders, ol_layers, class_layers) {
// updates slider with the actual opacity of the layers
for (var i = 0, len_i = all_sliders.length; i < len_i; ++i) {
var curr_slider = all_sliders[i];
// get layer from ol_layers whose title is equal to current slider id
// Find the value of the first element/object in the array, otherwise undefined is returned
// (https://stackoverflow.com/a/13964186/1979665)
var lyr = ol_layers.find(obj => {
return obj.values_["title"] === curr_slider.getAttribute("id")
});
// get class_layer (layerswitcher) from class_layers whose title is equal to current slider id
// (first we need to convert class_layers from HTMLCollection to array otherwise .find will fail)
var class_layers_arr = Array.from(class_layers);
var class_elem = class_layers_arr.find(obj => {
return obj.innerText.replace('\t','') === curr_slider.getAttribute("id")
});
// get current layer opacity and set it as the value of current slider
var curr_opacity = lyr.values_["opacity"];
curr_slider.setAttribute("value", curr_opacity);
// create new li element
var li_elem = document.createElement("LI");
// add slider input to li elem
li_elem.appendChild(curr_slider);
// add li with layer legend after layer li
insertAfter(li_elem, class_elem);
changeOpacity(curr_slider, ol_layers);
}
}
class_layers is first defined in another script as var class_layers = document.getElementsByClassName("layer");
EDIT 2
Ok, so apparently the problem is related to Chrome in general, not only on mobile. In fact, if you try the above URL in Chrome Desktop, you can reproduce the error by opening the sidebar (on the left), then closing it and pressing the + or - symbol to zoom in the map. I guess it has to do with the way click events are treated by either my code and OpenLayers. I am probably deleting this question as it sounds like I need to dig further in problematic.
SOLUTION
Not deleting because I think it maybe useful for others to see the solution.
Here is the link to the OpenLayers github issue I created and closed: https://github.com/openlayers/openlayers/issues/9105.
The problem was the event "change:resolution" fired by the View class of OL (v5.3.0) that is emitted multiple times during animation (problem also quoted here).
NEW CONSIDERATION
Turns out that I still had the problem on mobile devices.
The real fix was not to use innerText in my code and switch to innerHTML, as it was always empty in (and only in) Chrome, while with the other browsers it was not (I could actually see the string). If you are interested I can try to provide an example, but unfortunately I could not find much on this problem in the web...
It's not Array.from() problem.
Check your class_elem variable
It's undefined (because no element found for your conditions) and then it fails when your trying to get parentNode of undefined in:
export function insertAfter(newNode, referenceNode) {
referenceNode.parentNode.insertBefore(newNode, referenceNode.nextSibling);
}

How is it possible to have an array with length 0 but has content?

I have the following test code:
console.log('AA',slider);
console.log('AB',slider.length);
it returns the following in chrome console.
AA Array[53]
AB 0
i added test code because slider[5] always came back with undefined even though the console shows there is a value there.
here is a simplified version of initialisation script. entire code is pretty long and Slider is an object. Code for object is working the test script is later on trying to manipulate specific slider positions based on ajax return data.
var slider=[];
for (var uid=1;uid<50;uid++) {
slider[uid]=new Slider(.........);
}
var slider={};
for (var uid=1;uid<50;uid++) {
slider[uid]=new Slider(.........);
}
returns
AA {
1:{m
a: ....,
b: ....,
c: ....,
g: ....,
h: ....
},
2: .....
gets all the way up to 49
Ok i figured out the problem and hopefully this helps others.
After going through the code here is a much better example of initialization
var slider=[];
setInterval(function(){
for (var uid=1;uid<50;uid++) {
slider[uid]=new Slider(.........);
}
},500);
console.log('AA',slider);
console.log('AB',slider.length);
the array is indeed empty at the time the console log commands are executed but apparently the first line records reference to the object and not current state. So when I look at the log which is always going to be more then half a second later it shows data being there.

console.log/console.dir showing last state of object, not current

I want to log how my array/object is changing with new steps of loop. Console.log does this bad. It shows only last state of object everywhere. For example:
var a = {};
console.log(a); // {bob1: 0, bob2: 0}
a.bob1 = 0;
console.log(a); // {bob1: 0, bob2: 0}
a.bob2 = 0;
console.log(a); // {bob1: 0, bob2: 0}
I found there, on so, another command: console.dir. It is working properly in same example. It shows states of object correcly.
Look this example. This command works perfect: http://jsfiddle.net/RLzVV/
Now, look my code pls. All output is in console. http://jsfiddle.net/3BDs7/4/
This is aStar algorithm. Take a look on this part (neighbor 3 loop <--- neighbor 3 start ---> this code is situated here <--- neighbor 3 stop -->) in console. Lanes, which output this to console are 105-113:
new openset length: 2
openset after adding new vertex
**shows 1 element, but length is 2**
It shows length is 2, but shows only 1 element. But! Seems to me algo is working correctly (it is popping another element, which is hidden on this step after). Why this bug appears? Did I did something wrong? Seems to me, everywhere only last state of array shown, not current:( help me please.
That's a known issue -- sounds like you are running under Chrome.
The easiest work-around is to JSON encode the value as you log in.
console.log(JSON.stringify(a));

firebug console.table returning undefined

I am trying to view the contents of a 2 dimensional array. I found out about using console.table() here. Every time I call console.log in the console I get undefined. I have tried running the site's example code
var table1 = new Array(5);
for (var i=0; i<table1.length; i++)
table1[i] = [i+1, i+2, i+3, i+4, i+5, i+6, i+7];
console.table(table1);
as well as calling console.table on my own arrays while paused in the debugger.
Any thoughts on how I can get this to work?
Edit: undefined is also returned when I just type console.log("abc"); in the console.
Edit2: reinstalling firebug seems to have fixed the issue.

Bug in console.log? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Is Chrome's JavaScript console lazy about evaluating arrays?
I try the following code:
var myList = new Object();
var item = new Object();
item.text = "item-1";
myList[3] = item;
console.log(myList);
console.log(myList[3].text);
// Assign another object to the same entry
var item2 = new Object();
item2.text = "item-2";
myList[3] = item2;
console.log(myList);
console.log(myList[3].text);
The result is quite odd:
* Object
* 3: Object
text: "item-2"
item-1
* Object
* 3: Object
text: "item-2"
item-2
BUT - if i execute the second part after some time (using setTimeout), and unfold the first object, I get it right, i.e.:
* Object
* 3: Object
text: "item-1"
item-1
* Object
* 3: Object
text: "item-2"
item-2
I find it important to share it, since I think one can waste a lot of time trying to understand what's wrong in his code.
And if somebody has some reference to an open bug or something - please reply this ticket.
Thanks!
My view is that this is a horrendously irritating 'feature' that I really wish I could turn off, it makes debugging a nightmare, not knowing at which point in time something may have updated an object, whilst trying to establish exact object state at a give point in the code. The feature could be useful for 'watch points' etc, but not in something called a 'LOG' (the clue is in the name).
Consider this code fragment:
var person = {'name':'Tom'};
console.log( person); //output the entire object variable
person.name = 'Thomas';
//the output is an object, whose 'name' value is 'Thomas', even though the log statement was placed before the value was changed to 'Thomas'.
AND THEN:
var person = {'name':'Tom'};
console.log( person.name); //changed to output a string variable
person.name = 'Thomas';
//the output here, however, has not dynamically updated and correctly outputs 'Tom'
this is a known bug (50316) that gets reported again and again because people don't take a look at the bugtracker before reporting:
78325
94887
105559
107828
111020
131124
sadly, theres no information about if/when this will get solved. until that moment, you'll need to clone objects before passing them to console.log().
Sounds to me more like a race condition than anything else. Since you are only passing a reference to console.log(), the value it refers it has likely changed value by the time it is actually logged. Then when you use setTimeout(), the value changes after it has been logged. Instead of passing a reference to console.log(), pass a clone of the value.
This is a known problem/feature with the console log in some browsers.
When you log something, it may not immediately be turned into text format. If the log stores a reference to the object that you log, it will be turned into text format when it's actually shown in the log.
This has the advantage that logging something has a very small impact on performance, until you actually open the log window to show the log.
Even if you have the log window open while you run the code, there is no updates happening while your function is running (as Javascript is single threaded), so the console window will show the values as they are at the end of the function, when the window is updated.
I have done some experiments with this "problem" on the latest version of Chrome 20.0.1132.57 m.To summarize the key points :-
console.log() prints a reference to the object with as "> Object" when the code is executed
The state of the object when you click on the triangle is displayed, irrespective of the line of code where the console.log() is executed
If you want to print the object in its current state, print a clone console.log(JSON.parse(JSON.stringify(obj)));
You could use this bit of code to test this on your own browser:
window.onload = function() {chto = {a : 10, b : 20};
console.log('Open this object after 5 seconds')
console.log(chto);
console.log('Open this object before 5 seconds')
console.log(chto);
console.log('Console of the cloned object')
console.log(JSON.parse(JSON.stringify(chto)));
setTimeout(function(){ console.log('5 seconds up'); chto['b'] = 30; },5000 ) ; };

Categories

Resources