I'm creating a popup window with no URL source using window.open(). I don't give it a URL because soon I'll want to post a form to it. However, in the meantime I'd like to display a short "Now loading..." message so the user isn't looking at a blank page for the 2-3 seconds it'll take the form post to go through.
I tried adding Javascript that just writes to the popup window's document. That worked great in Firefox and IE 8, but failed with an Access Denied message in IE 6 and 7. Anyone know of a way around this? I would love to be able to a) hard-code some HTML into window.open(), b) learn how to update the popup's DOM in this situation, or c) hear about anything anyone can think of.
Below is the code I'm using to spawn the window:
var wref = window.open("", winName, "toolbar=1,resizable=1,menubar=1,location=1,status=1,scrollbars=1,width=800,height=600");
if (wref != null) {
try {wref.opener = self;} catch (exc) {}
// while we wait for the handoff form post to go through, display a simple wait message
$j(wref.document.body).html('Now loading
'); // EPIC FAIL
wref.focus();
IE considers "about:blank" to be a insecure URL and it won't let you talk to it. I would create a "Now Loading..." static HTML file and open that instead.
Test
<script type="text/javascript">
function test() {
window.open('javascript:opener.write(window);', '_name', 'width=200,height=200');
}
function write(w) {
w.document.write("Hello, World.");
}
</script>
Works in IE 6, 7 & 8, Opera 9.6, Firefox 2 & 3.
Does not work in Safari for Windows 3 & 4 or Google Chrome.
When it does work, it results in a pretty ugly URL in the Location box.
If the browser support listed above is acceptable, you can use the solution provided, otherwise I'd do what David said and window.open('Loading.htm' ...) where Loading.htm contains whatever content you want to display (you should probably keep it lightweight otherwise it might take longer to load and render than the form will to POST).
Also note that the winName you supply in IE must NOT have spaces... if so it will fail.
Another workaround is to open an empty "blank.htm" file on your site, then do the document.open() to access it
Related
I would like to write a simple script to open a Website and call a function that is part of a linked .js-file.
To be more precise, I want to open a SharePoint, invoke the function that is used to open the folder in windows explorer and close the website again.
For some reason, I may not open the folder directly in explorer unless I had it done this way at least once during the active windows session...
How may I do this?
So far, I tried the following:
var IE = new ActiveXObject("InternetExplorer.Application");
var WSH = new ActiveXObject("WScript.Shell");
IE.visible = true;
IE.navigate("https://mysharepoint.com/Folder");
WSH.PopUp("Click to fire function");
//the following line throws an error, because the function is unknown...
IE.Document.defaultView.setTimeout(NavigateHttpFolder, 0, "https://mysharepoint.com/Folder", "_blank");
//the following line does not throw an error, but nothing happens either..
IE.Document.defaultView.setTimeout(function(){NavigateHttpFolder("https://mysharepoint.com/Folder", "_blank");}, 0);
However, when I open my Sharepoint and type the following line into the addressbar it does exactly what I want to achieve and it opens the folder...
javascript:NavigateHttpFolder("https://mysharepoint.com/Folder", "_blank");
Could you please help me? I simply cannot find a way to get this to work.
UPDATE: Now it worked suddenly! I tried it the following way before but it didn't do anything until now (???)...
IE.Navigate('javascript:NavigateHttpFolder("https://mysharepoint.com/Folder", "_blank");');
You can include script with path to external website
<script type="text/javascript" src="http://www.external.com/script.js"></script>
Follow the following steps.
Steps 1:
Go to google.
Open the javascript console.
Enter the command: document.all.q.value = "hello"
As expected the element with a name of "q" (the search field) is set to "hello").
Steps 2:
Go to google.
In the address bar type javascript: document.all.q.value = "hello!"
Press Enter
If your browser is either Internet Explorer, or Google Chrome, the javascript will have replaced the google website with an entirely blank page, with the exception of the word "Hello".
Finally
Now that you've bugged out your browser, go back to Google.com and repeat Steps 1. You should receive an error message "Uncaught ReferenceError: document is not defined (...) VM83:1
Question:
Am I doing something wrong? And is there another method which works, while still using the address bar for JS input?
The purpose of a javascript: scheme URL is to generate a new page using JavaScript. Modifying the existing page with it is something of a hack.
document.all.q.value = "hello!"; evalues as "hello!", so when you visit that URL, a new HTML document consisting solely of the text hello! is generated and loaded in place of the existing page.
To avoid this: Make sure the JS does not return a string. You can do this by using void.
javascript:void(document.all.q.value = "hello!");
When messing around with javascript: in the adressbar some (if not the most) browsers handle it as a new page, so you have to add a window.history.back(); at the end
javascript: document.all.q.value = "hello!"; window.history.back();
Is it possible, using javascript, to control an overlay firefox extension? I've extracted the contents of the extension and have identified what functions/methods I need to run, but they are not accessible within the scope of the console.
Thanks in advance for any ideas.
Yes it possible to interact with other add-ons, given the right circumstances.
My test case here will be com.googlecode.sqlitemanager.openInOwnWindow(), which is part of the SqliteManager addon.
In newer builds (I'm using Nightly), there is the Browser Toolbox. With it is is as simple as opening a toolbox and executing com.googlecode.sqlitemanager.openInOwnWindow() in the Console.
You may instead use the Browser Console (or any chrome enabled WebDev Console for that matter, e.g. the Console of "about:newtab"). But you need some boilerplate code to first find the browser window. So here is the code you can execute there: var bwin = Services.wm.getMostRecentWindow("navigator:browser"); bwin.com.googlecode.sqlitemanager.openInOwnWindow()
Again, enable chrome debugging. Then open a Scratchpad and switch to Chrome in the Environment menu. Now executing com.googlecode.sqlitemanager.openInOwnWindow() in our Scratchpad will work.
You may of course write your own overlay add-on.
As a last resort, patch the add-on itself.
Bootstrapped/SDK add-ons: you can load XPIProvider.jsm (which changed location recently) and get to the bootstrapped scope (run environment of bootstrap.js) via XPIProvider.bootstrapScopes[addonID], and take it from there (use whatever is in the bootstrap scope, e.g. the SDK loader).
Now about the right circumstances: If and how you can interact with a certain add-on depends on the add-on. Add-ons may have global symbols in their overlay and hence browser window, such as in the example I used. Or may use (to some extend) JS code modules. Or have their own custom loader stuff (e.g. AdBlock Plus has their own require()-like stuff and SDK add-ons have their own loader, which isn't exactly easy to infiltate)...
Since your question is rather unspecific, I'll leave it at this.
Edit by question asker: This is correct, however I figured I'd add an example of the code I ended up using in the end, which was in fact taken directly from mozilla's developer network website:
In my chrome js:
var myExtension = {
myListener: function(evt) {
IprPreferences.setFreshIpStatus(true); // replace with whatever you want to 'fire' in the extension
}
}
document.addEventListener("MyExtensionEvent", function(e) { myExtension.myListener(e); }, false, true);
// The last value is a Mozilla-specific value to indicate untrusted content is allowed to trigger the event.
In the web content:
var element = document.createElement("MyExtensionDataElement");
element.setAttribute("attribute1", "foobar");
element.setAttribute("attribute2", "hello world");
document.documentElement.appendChild(element);
var evt = document.createEvent("Events");
evt.initEvent("MyExtensionEvent", true, false);
element.dispatchEvent(evt);
Update for Firefox 47 and up
Things changed drastically in Firefox 47. This is the new way to access it.
var XPIScope = Cu.import('resource://gre/modules/addons/XPIProvider.jsm');
var addonid = 'Profilist#jetpack';
var scope = XPIScope.XPIProvider.activeAddons.get(addonid).bootstrapScope
Old way for < Firefox 47
Update for methods of today
Typically you will do so like this:
If i wanted to get into AdBlocks scope, I check AdBlock id, it is {d10d0bf8-f5b5-c8b4-a8b2-2b9879e08c5d} so I would go:
var XPIScope = Cu.import('resource://gre/modules/addons/XPIProvider.jsm');
var adblockScope = XPIScope.XPIProvider.bootstrapScopes['{d10d0bf8-f5b5-c8b4-a8b2-2b9879e08c5d}'];
You can now tap into anything there.
Another example, I have an addon installed with id NativeShot#jetpack
I would tap into it like this:
var XPIScope = Cu.import('resource://gre/modules/addons/XPIProvider.jsm');
var nativeshotScope = XPIScope.XPIProvider.bootstrapScopes['NativeShot#jetpack'];
if you do console.log(nativeshotScope) you will see all that is inside.
I've an extension, and an XUL file inside it (let's call it A). XUL file contains an <iframe>, where is loaded some web page (let's call it B). B is loaded from the different domain.
A is parent to B. I want to send a message from within B to A using window.parent.postMessage().
I'm getting the following exception:
... permission denied to B to call method ChromeWindow.postMessage
How to fix that error? If there is no way to do that, how can I pass message from B to A?
I am using Firefox 16.0.1 under Windows 7.
I had a very similar problem,
it's just I had a html-popup (local) that couldn't send 'postMessage' to my xul-background-task.
I think I got it to work,
strangely enough by initiating a MessageEvent of my own (the very same thing postMessage does)
but with a (I believe obsolete) fallback.. in short: I brewed something together from MDN and other sites ;)
My script in the content:
var Communicator =
{
postMessage: function(data)
{
// We need some element to attach the event to, since "window" wont work
// let's just use a fallback JSON-stringified textnode
var request = document.createTextNode(JSON.stringify(data));
// and as always attach it to the current contentwindow
document.head.appendChild(request);
// Now let's make a MessageEvent of our own, just like window.postMessage would do
var event = document.createEvent("MessageEvent");
event.initMessageEvent ("own_message", true, false, data, window.location, 0, window, null);
// you might want to change "own_message" back to "message" or whatever you like
//and there we go
request.dispatchEvent(event);
}
}
And instead of window.postMessage(data) now use Communicator.postMessage(data)
that's all!
Now in my overlay there's nothing but our good old
addEventListener('own_message', someMessageFunc, false, true);
//or maybe even "message" just like originally
Hopefully this will work for you, too (didn't check that on iframes...)
You should check the type of iframe B
Edit:
Apparently you must flag your chrome as contentaccessible, and take into consideration the security.
Just posting in case someone faced the same problem.
Succeeded in posting message from within B to A using events as described here.
But it is not answer, because window.parent.postMessage() still doesn't work as intended.
I noticed that my Javascript bookmarklet was failing on certain sites like Google Reader and Google search results pages (and randomly on some non-Google sites). Looking at the console, I could see that, for these pages, clicking the bookmarklet did not append elements to the head/body like it normally did, but created a new document that looked like this:
<html>
<head></head>
<body></body>
</html>
Even when I reduced my bookmarklet to javascript:alert(window.location.href); it would create this blank page and run the bookmarklet therein, so that the alert showed about:blank. On most sites, this blank page is not created and the correct location is shown.
Can someone explain this? Are these sites sandboxing externally run code as a safety measure?
UPDATE: I currently can't reproduce this on browsers other than Chrome 17.0.932.0 dev. Please let me know if anyone else can reproduce these results on Chrome or otherwise.
I think this is a bug in Google Chrome, I've filed it to their bug database: https://bugs.webkit.org/show_bug.cgi?id=72606
You need to ensure that the topmost code, i.e. the one right after javascript: does not return anything.
Usually this is done by wrapping everything in void():
javascript:void(alert(window.location.href));
It's very odd that it breaks with alert() though since the function itself doesn't return anything...
If a javascript: url returns a string it will be used to create a new document:
javascript:'foo bar baz';
This can be a tough issue to debug if you don't know to watch out for it. It can crop up if you use a function that returns a string or end your bookmarklet with a line that sets a string value:
javascript: a = prompt('foo bar baz'); b = a;
A simple solution is to use a closure:
javascript:(function(){ var a; a = prompt('foo bar baz'); window.b = a}());
An alternative is to end with void 0;
javascript: a = prompt('foo bar baz'); b = a; void 0;