On Firefox, when hovering the mouse over a certain table in my webpage a strange [object HTMLTableCellElement] tooltip appears:
What needs to happen for this to occur? I am having a hard time narrowing what part of my code is the culprit because I don't even know what to look for.
Edit, solved the problem:
This table belongs to a Dojo Dijit template. I accidentaly gave one of the template's nodes the dojo-attach-point "title", causing Dojo to, during the rendering of the Widget, do a
this.title = the_node_with_the_bad_attach_point
The node is then converted to a string and that is where the "[object HTMLTableElement]" comes from.
Probably this:
cell.title = cell;
which can be described as a failed attempt to store the reference to the cell inside its own title property (which holds the string that is shown inside the tooltip on mouse-over).
Live demo: http://jsfiddle.net/VwYRP/
Object references - when coerced to strings - usually look like so: '[object Constructor]', where Constructor is the constructor function which the browser uses to instantiate that object.
Install Firebug and inspect the element. Do you see a title in the text? Check the DOM attributes. Maybe you can spot it there? Or maybe some JavaScript does not work properly. You'll get that message if you do an alert(document.createElement('th'));.
Related
Why does Chrome display two differing datasets depending on if you have the object view expanded?
In contracted view, my object has two properties:
In expanded view, my object has three properties:
The object you see in the console is a snapshot of the object at a particular point in time - the time when you logged it. When you expand the object, it will evaluate the properties again.
In the example below, I have created an object with two array properties. I logged it the console, and then I added a third property, c to it.
Only the first two properties are showing still, even though I just added a third property. After expanding the object in the console, I can see the third one. It is the latest state of the object.
If you hover over the little blue i icon, it explains what it has done:
Value below was evaluated just now.
#Gideon Pyzer is right. the properties were caculated and added after expanding the object in the console.
Just add one line code above your debug code and reopen the chrome dev tool, you will see the differences.
obj = Object.freeze(obj); //add this line before your console.log
console.log(obj);
Before:
After:
one similar question of mine:
Why can't I access the attr of the javascript object shown in chrome dev tool
You can clone your object to prevent re-evaluate.
console.log(Object.assign({}, obj));
You can get a real hard copy object by using this module. It will give you the snapshot of the object at moment when you call it.
https://www.npmjs.com/package/nest-object-deep-copy
const nestedHardCopy = require('nest-object-deep-copy');
console.log(nestedHardCopy(obj));
I apologize if the title makes you confused. Let me explain that.
In Chrome dev tool, if I use, for example:
document.getElementsByClassName("login")
I get get an HTMLCollection which As you can see the 0-indexd property represents an typical Element object.
However, if I use
document.getElementsByClassName("login").item(0);
I got something like this:
As you can see this is not an element object. Instead, it is an HTML Div element(correct me if I named it incorrectly).
My question is that why item() method does not return the same object in the HTMLCollection? To my understanding, HTMLCollection is an object, what is retrieved from item() method is a property of the object, so they are supposed to be the same. Why is the result is unexpected?
Thank you!
This is just the Chrome console formatting the object in a "pretty" way:
By default, DOM elements are logged into the console as representation of their HTML
(From https://developers.google.com/web/tools/chrome-devtools/console/console-write#formatting_dom_elements_as_javascript_objects)
If you want to view the actual object, you can obtain a JavaScript representation of it with:
console.dir(document.getElementsByClassName("login").item(0))
(You can optionally drop the console.)
See: https://developers.google.com/web/tools/chrome-devtools/console/console-reference for info on the various console functions that are available.
I have several questions about how Javascript object work.
I understood that Javascript work by inheritance. But there are things that I not able to understand
First, when we digging through some objects in javascript, It happens that we found not all object property. But when we create our own objects, the debug show everything.
For example, a Bootstrap Dropdown object will show this :
$(".dropdown").dropdown()
(9) [li.dropdown.active, li.dropdown.test, a#addConsumption.dropdown.toggle, li.dropdown.dropdown-accordion, a#addConsumption.dropdown.toggle, li.dropdown, a#addTemperature.dropdown.toggle, li.dropdown, a#addPresence.dropdown.toggle, prevObject: r.fn.init(1)]
$(".dropdown").data("bs.dropdown")
Dropdown {}__proto__: Object
When a MyObject object will output the following :
DropdownAccordion {accordions: Array(0), component: r.fn.init(1), dropdown_menu: r.fn.init(1), menu_panel_group: r.fn.init(1)}
property1
:
[]
property2
:
[div.panel-group, prevObject: r.fn.init(1)]
proto
:
Object
So how do this work ?
And, for example in Bootstrap, how DOM with class like ".dropdown" are instantiated? In fact, I dug through the dropdown.js and tried to find when instantiation occurs, but it never happens. So maybe there is another concept of Javascript instantiation that I don't know existed.
// This section appear to never happen, unless we instantiate like "$(selector).dropdown()
function Plugin(option) {
return this.each(function () {
var $this = $(this)
var data = $this.data('bs.dropdown')
if (!data) $this.data('bs.dropdown', (data = new Dropdown(this)))
if (typeof option == 'string') data[option].call($this)
})
}
Your array that gets printed out to the console is a HTMLCollection (or a jQuery Collection), basically a list of HTMLElements. When you put them out in the console, your browser will format the output differently, such that when you hover above the output elements, they will also be marked in the DOM, as if you would inspect them. However, you can still get the prototype methods of the class with $(".dropdown").__proto__ for example.
Regarding your second question: Usually these elements, which produce new html elements in the DOM, get rendered from javascript, so you should find something in the code, maybe not in the dropdown.js.
I'm desesperatly trying to create an Anno object in a JSNI method but I have a strange problem : the code in the jsni method doesn't work but if I do the same in my browser console, it works fine.
Java Part
I'm using a JSONArray in wich I add some JSONObject (with all the elements, according to Anno doc). Here's my JSNI method :
// I'm using the getJavaScriptObject() on my JSONArray
private static native void launch( JavaScriptObject steps )/*-{
var anno = new $wnd.Anno(steps);
anno.chainIndex().show();
}-*/;
Browser Part
Just to be clear, the method is called on a onShow event, so all the ressources are loaded and rendered. So when the element is displayed and the function called, I have this error in my console :
Couldn't find Anno.target 'h1'. --- anno.js:265
NB : In Anno.js, h1 is the dafault value of target.
But my steps value is right and when I do the same commands in the console it works :
var testAnno = new Anno([{
content: "namespinnerFrequencyA",
position: "center-right",
target: ".dataAuto0"
},{
content: "chooseFrequencyB",
position: "top",
target: ".dataAuto1"}]);
testAnno.show();
I don't understand why it works in one case and not in the other. I've also tried to use JSON.stringify then JSON.parse but it doesn't work either.
EDIT :
I figured something out. While debugging anno.js I figured something : when I initialized Anno in the console, the local scope look like this (bigger image here ) :
But when I use the jsni method, the local scope is absolutely different, my parameter is stored as an actual array instead of being processed normally (bigger image here ) :
The problem is that GWT code runs in an iframe (for sandboxing/isolation) and Anno only supports array types from the same browsing context.
See http://perfectionkills.com/instanceof-considered-harmful-or-how-to-write-a-robust-isarray/ and http://web.mit.edu/jwalden/www/isArray.html for descriptions of the problem.
ECMAScript 5.1 added an Array.isArray() function that solves that issue and has wide browser support (back up to IE9): https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/isArray
And jQuery has one too, which makes it incomprehensible (to me) that Anno doesn't use it instead of using the broken if arg.__proto__ is Array.prototype (unless it's by design). So first things first: file an issue on Anno.
As a workaround, it should be possible to use $wnd.Array.apply($wnd.Array, steps) to copy your array into an array from the top window.
It seems to me that the error message says it cant find the target dom element and not that it cant find the target property. Is the element there when your code is fired? make sure it is and get back to me.
I am getting the following error in IE:
'events' is null or not an object -- jquery-latest.js?d=1848173663, line 113 character 467
I am using jQuery 1.4.2, I'm not in a position to upgrade yet as we are on an older version of jQuery UI and have way too many bugs using anything newer than 1.4.2.
I get following error when I run this bit of code the second time:
$.post("page/view.do?undoCache=" + Math.random(), {
pageId: pId
}, function(xmlContent){
console.log('1');//get this one
$('#reloadCenterDiv').empty();
console.log('2');//don't get this one unless line above is commented out, then will run til next line
$('#reloadCenterDiv').html(xmlContent);
console.log('3');//don't get this
});
I'm pretty sure I'm not doing anything else to #reloadCenterDiv between calls.
Googling around for the error "'events' is null or not an object" I found this:
"Sounds like a reference to an event
handler is still there, when the
handler itself is already gone."
That sounds logical. Any other ideas of why and when this error would occur?
I have found where this is happening, but all clues for me end there.
How do I clean things up so I can call empty() or html() on #reloadCenterDiv again?
Here is the HTML for #reloadCenterDiv:
<div id="reloadCenterDiv" style="border:none; margin: 0; overflow:auto; overflow-y:scroll; height: auto;"></div>
Not sure, but it would seem like jQuery.cache is being overwritten.
Since a DOM element has (when necessary) a serial number that maps to jQuery.cache, when you run a function like .empty(), jQuery assumes the related data exists, looks up the data for that element, and deletes it.
In place of your first log, do this:
console.log(jQuery.cache);
And see what it gives you. I'll bet that something is overwriting it. Perhaps you're loading jQuery twice?
Here's an example that intentionally deletes jQuery.cache. It gives a similar error.
EDIT:
Summary of the comments below. During .empty() (or actually cleanData()) jQuery grabs the expando from all descendant elements in order to delete the associated data.
The issue is that when jQuery does so, it assumes that the data was successfully located. In this case, somehow the data is being disassociated from the element, so retrieving the data using the value of the expando is returning undefined.
Because jQuery doesn't (or didn't in 1.4.2) verify that data was found, its attempt to access the events property on the data is causing an error, because again data is undefined.
Updated versions of jQuery fix it with if ( data && data.events ) {, which verifies that there is some object against which to ask for its events property.
If you can't update your jQuery, you can set the HTML instead:
$("#divid").html("");
This is essentially doing the same thing.