I'm working on an Umbraco site that needs to work in the big browsers, including IE 11, and I've run into a weird issue that I can only replicate on IE 11.
At some point, the script for a TinyMCE plug-in tries to execute this code (about four calls deep) in response to a blur event:
function classTest(cls) { return new RegExp("(^|\\s)" + cls + "(?:$|\\s)\\s*"); }
and it throws a "Object doesn't support this action" exception when trying to create the RegExp object. cls is defined and has the value I expect.
While paused (using Visual Studio debugger) on the unhandled exception, I did a little checking.
It turns out that RegExp was undefined. I found this extremely weird.
A little more investigation revealed that ALL the built-in objects were undefined. Number, Array, Object, Math... all of them. Also, while I could enumerate the global keys, all the values were also undefined.
Weirder, I could use the console or immediate-execution windows, within the problematic scope, to create regular expression objects by using the /pattern/ syntax.
But this condition is true only in the scope of the event handler. As soon as the event handler exits, all the built-in objects and global variable values were restored.
How is it even possible to lose access to the built-in JavaScript objects, without losing access to the basic JavaScript parser and engine?
And, once lost, is it possible to restore them?
I experienced this problem as well, and assuming you're also having trouble with the TinyMCE CodeMirror plugin, the problem is triggered by this line in codemirror.js:
on(window, "blur", function () { return forEachCodeMirror(onBlur); })
where window refers to the iframe containing the CodeMirror editor.
This iframe is inside of a TinyMCE dialog. I've discovered the error only occurs when the iframe (or an element inside it) loses focus at the same time that the dialog is closed, removing the iframe from the DOM. You can test this by first clicking outside the iframe (on the page overlay, for example) before closing the dialog.
IE11 seems to be calling the blur event after it has started destructing the iframe's window object. I would classify this as a bug in IE11, which will never get fixed. Since we probably don't care about the blur event in an iframe that's being removed from the DOM, we can work around the problem by modifying the problem line to skip it in that case:
on(window, "blur", function () { if (window.RegExp) return forEachCodeMirror(onBlur); })
Related
My knowledge of JavaScript is very basic, and I'm somewhat familiar with the Chrome console. I am posting here as being uncertain about the correct terms to use, but hope to keep this question short and focused.
I have a browser page that uses JavaScript as certain elements change values. I know basically which .js file is responsible for this, but I would like to:
a) know which function is initially called when an element changes - i.e. be TOLD by the Chrome console.
b) put a "stop" in that function at a certain point, or add a line of code, or determine the value(s) of a local execution context
Are (a) and (b) possible? Using the Chrome console alone? adding console.log('status here is '+this.status) all over is very time-consuming.
Determine the context values (b)
To know the values of the local execution context, you can attach a hanlder function to the change event in your html element and log the value to the console output (console.log(myValue)). For input elements, for exmaple, a simple way to do it is adding the onchange attribute to the html element passing the handler function.
You can also add a breakpoint in the handler function using the F12 Developer Tools. Read more about it here: Google Chrome - Pause Your Code With Breakpoints
Example:
// This function will be called when you change the value and move the focus
// to a different element or when you click enter
function myHandler(input){
console.log(input.value);
}
<input value="123" onchange="myHandler(this);" />
You could also use onkeydown. For more events you can check: W3Schools - Dom Object Events
Event order (a)
Regarding the event order (a), you can reference to ths other question:
What is the event precedence in JavaScript?
Simplified, what I'm doing is running this in the console:
window.onbeforeunload = function (e) {
console.log(e);
}
In the console, when the event fires (by trying to "leave page" in the middle of writing an SO question) what I see is this:
Event {clipboardData: undefined, cancelBubble: false, returnValue: true, srcElement: document, defaultPrevented: falseā¦}
With a little "i" graphic next to it. When I click the arrow next to it to expand the object in the console, nothing happens. The arrow turns to indicate that it has expanded, but it doesn't expand.
What am I missing here??
This is happening because although you're letting the console persist over page changes, the Object no longer exists - it was destroyed when you left the page. This means it's simply not available to be inspected anymore, so clicking the down triangle is not helpful.
Try this instead, to prevent the page actually changing:
window.onbeforeunload = function (e) {
console.log(e);
return true;
}
Now the page will prompt to ask you what to do. Click 'cancel' in the prompt that comes up in order to remain on the page. Now you can inspect the Event in the console as desired.
The difference is that the onbeforeunload function is now returning a value that isn't null/undefined. The return value could be anything, even '' or false, etc...anything except null and undefined, and it will still cause the page to prompt before navigating away and thus giving you an opportunity to inspect the event. Remember that with no return statement, JavaScript functions return undefined by default.
Whenever you can't inspect something in the Chrome Dev Tools, 90% of the time it's because some action has caused that thing to become unavailable...the page has moved on from when that object existed.
The failure to expand can mean that the object was subsequently removed from memory: possibly deleted or garbage-collected, or (especially if you're using Chrome dev tools on a Node.js script) it could be that the script completed, so all refs now point nowhere.
It's a good practice when inspecting objects that can change later to drop in a debugger instead of console.log:
window.onbeforeunload = function (e) {
debugger; // Now go find `e` in the local variables section
}
This pauses the execution of the code, so you know for sure you're seeing what the variable was at this point, rather than seeing any subsequent changes.
This way, you can access more context and don't need to worry about changes to output caused by what happens later in the code.
Always remember that in JavaScript, any time you deal with a variable that points to an object, you're dealing with a live reference, to the latest state of that object.
console.log logs the reference, not the object's contents, and when you view and expand the logged reference, you're viewing what that reference points to at the time you look at it, not the time you logged it. This might be nothing if it has been removed from memory or reassigned.
Variables pointing to primitives like strings and numbers point to values not references, so you could also:
log a stringified version of the object, like console.log(JSON.stringify(someObject)) (although that output may be harder to read).
if the object's properties are all primitive, log a shallow clone like console.log({ ...someObject }) (though any properties that are objects may face the same problem)
The debugger approach is usually better.
Old question. But this simple solution worked better for me. Use
function(e) {
console.dir(e);
}
I just came across this question with a problem I had where my API PUT request was showing as cancelled in my console tab in chrome dev tools and I was seeing the same behavior where I couldn't expand the object and the little i icon was showing next to the console entry. I decided to post this answer with a link to my question in case it might help anyone else.
Api PUT request showing as "cancelled" with error message "TypeError: failed to fetch"
In a webapplication I came across, there is a javascript line in logout.jsp as:
parent.parent.renderProcessingTextOff();
On debugging the page with IE script debugger, it is breaking on above line with error as:
Object doesn't support this property or method
What is the meaning of this error?
How to solve it?
I am new to javascript, so please explain in simple terms.
Flow of logout is:
on click of logout button, a command is passed and intercepted in interceptor, which directs it to appropriate processor, which forwards the request to logout.jsp.
Its a spring application, if that information is of any help.
Thanks for reading!!
Are there frames or iframes on your page? Or object elements?
parent is a property of the window object (and the window. part of window.parent is assumed if you leave it out).
From MDN:
When a window is loaded in an <iframe>, <object>, or <frame>, its parent is the window with the element embedding the window.
So if from an iframe that is at least two levels down, the line parent.parent.renderProcessingTextOff(); says to call the renderProcessingTextOff() function defined by its grandparent.
Obviously if that line of code appeared where there wasn't a grandparent with that function defined then you'll get the error you quoted.
In this case, it looks like the first word, parent is an object instance. That object has a property called parent, and to access it you use the syntax parent.parent. The property is in turn another object, which is supposed to have a property called renderProcessingTextOff which is called as a function.
If I would venture to guess about your problem, it seems that parent.parent is of the top level Object class, and Object does not have that method.
If you already is using the IE script debugger, put a breakpoint at that line and examine the parent and parent.parent objects.
ive been writing a website for about 3 days and i ran into a problem. i have a textfield that changes a span on the page using javascript, and this works fine on firefox and ie. but on google chrome it just returns "[object DOMWindow]" no mater what i change. the code is way to long to post so i would just like to ask if anyone knows what causes this?
My best guess without seeing code would be you're using the this keyword, which behaves differently in different browsers. this refers to the window element any time that it is not in a different context. Check to make sure you are either using a library that normalizes the this keyword (like jQuery) or are explicitly getting the text field every time.
Before I get into the details of this problem, I'd like to make the situation clear. Our web analytics company works as a consultant for large sites, and (other than adding a single SCRIPT tag) we have no control over the pages themselves.
Our existing script installs handlers using "old" way (a fancy version of element.onclick = blah; that also executes the original handler) which is completely unaware of "new" (addEventListener or attachEvent) handlers on the page. We'd like to fix this to make our script able to run on more sites without requiring as much custom development.
The initial thought here was to have our own script use addEventListener/attachEvent, but this presents a problem: of the client's site sets a handler using the "old" way, it would wipe out the handler we installed the "new" way. Quick and dirty testing shows this happens in both IE7 and FF3, although I didn't test the whole range of browsers. There's also a risk that if we use the "new" way after the page's event handlers are already set, we could erase their handlers.
So my question is: what safe technique can I use to add an event handler in Javascript using addEventListener/attachEvent that works regardless of how other event handlers on the page are installed?
Please remember: we have no way of modifying the site that our script is installed on. (I have to emphasize that because the default answer to questions like this is always, "just rewrite the page to do everything the same way.")
Can you try your quick-and-dirty testing again? This doesn't happen for me in FF3.
elem.onclick = function() { alert("foo"); };
elem.addEventListener("click", function() { alert("bar"); }, false);
Both handlers fire for me when I click on the element.
I'm guessing you forgot the final boolean argument in addEventListener (whether to use the capture phase). I'm also guessing you forgot that IE's attachEvent needs onclick, not click.
addEventListener/attachEvent is safe in a sense you ask. They add a new event handler to a Node without altering any handlers previously added to it (even once assigned through a property onxxx). For a company that bring some to a foreign page using addEventListener/attachEvent must be the only practice. Assigning onxxx handler via properties indeed would break hosting pages scipts (that have been previously assigned the same way)