I get the utils of the window like this:
var utils = Services.wm.getMostRecentWindow('navigator:browser').
QueryInterface(Components.interfaces.nsIInterfaceRequestor).
getInterface(Components.interfaces.nsIDOMWindowUtils);
then running this code says its not a function:
Services.prompt.alert(null, 'is modal?', utils.isInModalState())
//Exception: utils.isInModalState is not a function
even though it says in the documentation it is.
I am not able to run this code either:
utils.enterModalState()
It runs without error but the window does not enter or leave modal state.
The .isInModalState property is actually tagged [noscript], so it is not available in Javascript, only C++.
.enterModalState() doesn't do what you think it does. It does not make a window UI-modal (like an alert dialog). It just essentially suspends scripts and event processing in the window.
Related
In a web app that allows users to play with javascript I require them to have a function main() in their "program". There's a "run" button, and an "edit" button. When you press "run" text from a <textarea> is used to create a script block and insert it into the DOM. Then main() is called.
I catch window.onerror to display errors to the user. This generally works OK. If there is no main(), an appropriate error message is shown.
When you press "edit", the script block is set to blank (script.text = '';),and removed from the DOM.
Testing, I noticed that if I had "program" consisting of just:
function main() { printLn('main here'); }
it worked as expected, but when I changed that to:
function moon() { printLn('moon here'); }
instead of getting a message saying main() not defined, it still worked as before, despite the fact that the script block had the "moon" text. This continued to happen if I gave each created script block a distinctive ID, and if I changed the script block type to text/plain before removing it.
The problem occurs in current Firefox, Chrome, and Opera. You can see what happens here
The functions are still defined, even if you remove the script that defined it.
This is in stark contrast to CSS, where removing or modifying a stylesheet will remove or update the styles on the page accordingly.
There's a good reason for that, and that is that CSS is designed to be easily re-evaluated when changes are made. JavaScript on the other hand is far too complex for the browser to be able to understand what "removing a script" actually does.
So, provided you have run one function with main(), it will continue to exist even if you then delete it.
My suggestion would be to create a closure to run your script. You can do this with something like...
var input = "........"; // user's input
var runner = "if( typeof main === 'undefined') {"+
"showErrorMessage('No main() defined');"+ // or whatever your error function is
"} else { main(); }";
var func = new Function("(function() {"+input+runner+"})()");
func();
It's always worth noting that the global scope can still be accessed, such as if the user forgets to var their local variables, or if they outright access window.something. So long as it's only being run on the user's own machine, this isn't much of an issue, but if people can share their codes with others then you will need to be much more careful.
So here' s the piece of code. I'm very new to JavaScript so don't be afraid to explain the obvious
$(".my-css-class").on("click", function() {
($(this).attr("data-property-1"), $(this).attr("data-property-2"), this);
});
There's an element in the .jsp page that looks like this:
<i class="clickMe"></i>
I know the .jsp creates a link-icon, and that the above JavaScript is an event handler. I know that it passes these 3 values as arguments another JavaScript method:
function doStuff(prop1, prop2, obj) {
if (prop1 == 'foo') {
//do stuff with prop2
}
else{
// do stuff with obj
}
}
It all works fine. What I want to know is what exactly is going on to make it work? I can't find anything in the code that connects what the event-handler returns to the 'doStuff' java-script function.
The names are totally different, so it's not reflection, it can't be parameter matching because there's other functions with the same number and type of parameters in the file, it can't be convention based because it still works if I find/replace the name of the function to gibberish.
I guess basically I'm asking what this line is doing:
($(this).attr("data-property-1"), $(this).attr("data-property-2"), this);
tl;dr: I'm at a loss, I know how the properties get as far as the onClick event-handler's anonymous function - but how does JavaScript know to pass them as arguments the to the doStuff() function?
the onClick event is a standard event triggered on click of any clickable html element and is automatically raised by the DOM.
You are hooking in to this by listening on any matched ".my-css-class" elements for an onClick Event.
The jquery syntax ".on" has been simplified over time and allows you to hook into any number of events like "submit" - OnSubmit event , or "load" - onLoad Event
Wherever your on("click", myFunction) event hook is picked up, your myFunction will execute.
Looking at your second point...
because it still works if I find/replace the name of the function to gibberish.
The DoStuff function will be found and replaced across all files in your site? or page? or open tabs? , so therefore it must exist somewhere as "doStuff(" or "giberish(".
so when you do a global find/replace, do each one slowly, until you locate it.
Finally, when you do a view source in the browser, this should either explicitly show you the doStuff function, or at the very least give you a clue as to satelite files loaded at runtime, where you can go and investigate.
Use firebug in firefox to debug loaded resources; the ".net tab" to view external loaded resources and the html/javascript they might contain. (for example: your master page might be loading in an embeded resource that contains the doStuff method, becuase of a user or server control reference in that master page)
Also have a look at this:
http://www.developerfusion.com/article/139949/debugging-javascript-with-firebug/
You can step through the javascipt piece by peice until it hits the doStuff method.
Just remember to set at least 1 breakpoint ;-)
I'm trying to modify a variable - which is created in javascript - and run a function to change some visual stuff on a page. But my greasemonkey script is - i guess - running before the javascript, i'm getting an error says function is not defined.
How can I force to run my script after the javascript runs?
Actually what I'm trying to do is very simple. There is a variable called cursort, what I want to do is change that to "data-price" and sort the list again using updateSort(). Here is the code:
var cursort = "data-price";
updateSort();
I had to do something similar, there was a object defined at the end of the page that I wanted to just cancel out, so it's functions wouldn't run (it captured link clicks and ran some stuff).
In the page it was defined like this:
var someObj = { ... }
I made a greasemonkey script (after much trial/error) that looked like this.
window.addEventListener ("load", runAfter, false);
function runAfter() {
unsafeWindow.someObj = null;
}
Now clicking on the links does not trigger all the other actions that were in someObj.
Maybe you can do something like that?
I'm trying to test a page using CasperJS, in particular I want to poke the data model a bunch. Let's say I've got a basic function called taxes, and I want to ensure that it uses the right tax rate. So I'd like something like:
this.test.assert(taxes(100, 'Ontario') === 15, "Check ontario tax rate");
Rather than filling out a form and seeing what it prints. That taxes method exists in the global scope, so I'm able to execute it quite easily from anywhere (including from the console in firebug or Chrome). But it's not in the right scope for that to work inside CasperJS (I think? I'm getting ReferenceError: Can't find variable: taxes.
It seems like I'm missing something simple.
TL;DR: How do I execute an on-page bit of JS directly inside a CasperJS test?
Have you tried using evaluate()?
relevant quote: "execute code as if you were using the browser console."
something along the lines of:
casper.evaluate(function(amount, province) {
return taxes(amount, province);
}, {100, 'Ontario'});
Use assertEvalEquals() method.
If you're calling the method via a jQuery-style reference, make sure to explicitly include the library, lest you'll get the ReferenceError:
var casper = require('casper').create({
clientScripts: ['js/jquery-1.7.2.js']
});
...
casper.start('foo.php',
function() {
console.log(this.evaluate(function() {
return $('taxes').text();
}));
});
casper.run();
See: https://groups.google.com/forum/#!msg/casperjs/2uyUOqdzShw/bHWrJYXni40J
If you're calling it implicitly in the global scope (i.e., straight javascript, rather than, for example, $('taxes')), you might have to explicitly prepend the window or document namespace to the reference:
document.querySelector('#taxes').value = taxes_text;
I thought I'd found the solution a while ago (see my blog):
If you ever get the JavaScript (or should that be JScript) error "Can't execute code from a freed script" - try moving any meta tags in the head so that they're before your script tags.
...but based on one of the most recent blog comments, the fix I suggested may not work for everyone. I thought this would be a good one to open up to the StackOverflow community....
What causes the error "Can't execute code from a freed script" and what are the solutions/workarounds?
You get this error when you call a function that was created in a window or frame that no longer exists.
If you don't know in advance if the window still exists, you can do a try/catch to detect it:
try
{
f();
}
catch(e)
{
if (e.number == -2146823277)
// f is no longer available
...
}
The error is caused when the 'parent' window of script is disposed (ie: closed) but a reference to the script which is still held (such as in another window) is invoked. Even though the 'object' is still alive, the context in which it wants to execute is not.
It's somewhat dirty, but it works for my Windows Sidebar Gadget:
Here is the general idea:
The 'main' window sets up a function which will eval'uate some code, yup, it's that ugly.
Then a 'child' can call this "builder function" (which is /bound to the scope of the main window/) and get back a function which is also bound to the 'main' window. An obvious disadvantage is, of course, that the function being 'rebound' can't closure over the scope it is seemingly defined in... anyway, enough of the gibbering:
This is partially pseudo-code, but I use a variant of it on a Windows Sidebar Gadget (I keep saying this because Sidebar Gadgets run in "unrestricted zone 0", which may -- or may not -- change the scenario greatly.)
// This has to be setup from the main window, not a child/etc!
mainWindow.functionBuilder = function (func, args) {
// trim the name, if any
var funcStr = ("" + func).replace(/^function\s+[^\s(]+\s*\(/, "function (")
try {
var rebuilt
eval("rebuilt = (" + funcStr + ")")
return rebuilt(args)
} catch (e) {
alert("oops! " + e.message)
}
}
// then in the child, as an example
// as stated above, even though function (args) looks like it's
// a closure in the child scope, IT IS NOT. There you go :)
var x = {blerg: 2}
functionInMainWindowContenxt = mainWindow.functionBuilder(function (args) {
// in here args is in the bound scope -- have at the child objects! :-/
function fn (blah) {
return blah * args.blerg
}
return fn
}, x)
x.blerg = 7
functionInMainWindowContext(6) // -> 42 if I did my math right
As a variant, the main window should be able to pass the functionBuilder function to the child window -- as long as the functionBuilder function is defined in the main window context!
I feel like I used too many words. YMMV.
Here's a very specific case in which I've seen this behavior. It is reproducible for me in IE6 and IE7.
From within an iframe:
window.parent.mySpecialHandler = function() { ...work... }
Then, after reloading the iframe with new content, in the window containing the iframe:
window.mySpecialHandler();
This call fails with "Can't execute code from a freed script" because mySpecialHandler was defined in a context (the iframe's original DOM) that no longer exits. (Reloading the iframe destroyed this context.)
You can however safely set "serializeable" values (primitives, object graphs that don't reference functions directly) in the parent window. If you really need a separate window (in my case, an iframe) to specify some work to a remote window, you can pass the work as a String and "eval" it in the receiver. Be careful with this, it generally doesn't make for a clean or secure implementation.
If you are trying to access the JS object, the easiest way is to create a copy:
var objectCopy = JSON.parse(JSON.stringify(object));
Hope it'll help.
This error can occur in MSIE when a child window tries to communicate with a parent window which is no longer open.
(Not exactly the most helpful error message text in the world.)
Beginning in IE9 we began receiving this error when calling .getTime() on a Date object stored in an Array within another Object. The solution was to make sure it was a Date before calling Date methods:
Fail: rowTime = wl.rowData[a][12].getTime()
Pass: rowTime = new Date(wl.rowData[a][12]).getTime()
I ran into this problem when inside of a child frame I added a reference type to the top level window and attempted to access it after the child window reloaded
i.e.
// set the value on first load
window.top.timestamp = new Date();
// after frame reloads, try to access the value
if(window.top.timestamp) // <--- Raises exception
...
I was able to resolve the issue by using only primitive types
// set the value on first load
window.top.timestamp = Number(new Date());
This isn't really an answer, but more an example of where this precisely happens.
We have frame A and frame B (this wasn't my idea, but I have to live with it). Frame A never changes, Frame B changes constantly. We cannot apply code changes directly into frame A, so (per the vendor's instructions) we can only run JavaScript in frame B - the exact frame that keeps changing.
We have a piece of JavaScript that needs to run every 5 seconds, so the JavaScript in frame B create a new script tag and inserts into into the head section of frame B. The setInterval exists in this new scripts (the one injected), as well as the function to invoke. Even though the injected JavaScript is technically loaded by frame A (since it now contains the script tag), once frame B changes, the function is no longer accessible by the setInterval.
I got this error in IE9 within a page that eventually opens an iFrame. As long as the iFrame wasn't open, I could use localStorage. Once the iFrame was opened and closed, I wasn't able to use the localStorage anymore because of this error. To fix it, I had to add this code to in the Javascript that was inside the iFrame and also using the localStorage.
if (window.parent) {
localStorage = window.parent.localStorage;
}
got this error in DHTMLX while opening a dialogue & parent id or current window id not found
$(document).ready(function () {
if (parent.dxWindowMngr == undefined) return;
DhtmlxJS.GetCurrentWindow('wnManageConDlg').show();
});
Just make sure you are sending correct curr/parent window id while opening a dialogue
On update of iframe's src i am getting that error.
Got that error by accessing an event(click in my case) of an element in the main window like this (calling the main/outmost window directly):
top.$("#settings").on("click",function(){
$("#settings_modal").modal("show");
});
I just changed it like this and it works fine (calling the parent of the parent of the iframe window):
$('#settings', window.parent.parent.document).on("click",function(){
$("#settings_modal").modal("show");
});
My iframe containing the modal is also inside another iframe.
The explanations are very relevant in the previous answers. Just trying to provide my scenario. Hope this can help others.
we were using:
<script> window.document.writeln(table) </script>
, and calling other functions in the script on onchange events but writeln completely overrides the HTML in IE where as it is having different behavior in chrome.
we changed it to:
<script> window.document.body.innerHTML = table;</script>
Thus retained the script which fixed the issue.