Invoking original unmolested window.open from bookmarklet - javascript

I have general purpose bookmarklet, which begins with:
javascript:with (window.open("")) {/* lots of irrelevant characters */
It works as should (opens new window and writes a report about page elements, specifically), however fails on certain pages, when authors decide what open is a good name for function:
/* somewhere in global scope */
function open() { /* something */ }
... effectively replacing window.open and breaking bookmarklet operation. By the nature of bookmarklet i cannot do anything to prevent such misbehaviour.
Is there any way to call original native window.open to recover in this cases?
Please note, my primary browser is Opera, i really want to make it work in there.

window.constructor.prototype.open
Nope, sorry. You can do some hackery to get a new one though :)
var ifr = document.createElement('iframe');
document.body.appendChild(ifr);
ifr.contentWindow.open(...)

Related

Trying to build safari extension. Not working -.-

So I'm making a Safari extension for my own personal use, and it's not working at all.
I'm trying to skip adf.ly and go directly to the website. But it's not doing anything at all.
I've tried alerting the current URL and the supposed new URL, and they aren't even displaying either.
Global.html
<!DOCTYPE html>
<script type='application/javascript'>
// Skip Adf.ly
// Made by Austen Patterson
// For Safari
//(C) Copyright 2013 Austen Patterson.
safari.application.addEventListener("start", performCommand, true);
safari.application.addEventListener("validate", validateCommand, true);
// Function to perform when event is received
function performCommand(event) {
// Make sure event comes from the button
if (event.command == "skip") {
var url = this.activeBrowserWindow.activeTab.url;
var newurl = url.replace(/http:\/\/adf\.ly\/(\d+)\//, '');
location.href(newurl);
window.open(newurl,"_self");
return;
}
}
</script>
and here is my extension builder settings.
You can't use alert from the global page. You can use console.debug, though, so that should help.
The bigger issue though is that you're treating the global page as though it has access to the page you're trying to modify via the window object. It doesn't work that way. location.href doesn't point to anything and window.open will probably not work from the global scope. (These are both leaky globals, which is something you want to avoid.) I haven't tested it, but something like this should work:
safari.application.addEventListener("beforeNavigate", function adflyChecker(event) {
var url = event.url.replace(/http:\/\/adf\.ly\/(\d+)\//, '');
safari.application.activeBrowserWindow.activeTab.url = url;
}, true);
This has the advantage of working on navigate and not requiring you to manually click the button. If you configure your extension to only apply to adf.ly URLs, then you can be sure that your code only fires when it's appropriate.
More information about the architecture of Safari extensions is available in the docs.

window.name storage for a named window in <=IE7

I have an application that uses window.name as a fallback storage to sessionStorage.
Example (simplified for brevity):
function setData(data){
window.name = JSON.stringify(data);
}
function getData(data){
return JSON.parse(window.name);
}
This all works fine and dandy in just about all browsers. However, I have recently discovered that this DOES NOT work in IE7 and below when the window is launched with a target.
winning.html
If I launch the winning.html file from the above A, using IE7, getData will always return "bob", regardless of what we try to set through setData.
If I modify the launch link like so (remove the target), it will set and remember data correctly.
winning.html
The problem is that I do not always have control of that originating link. Is there any way around this?
As is often the case, putting this problem down for a couple of days, and then coming back to it fresh has revealed the answer.
I tested the bug using this script (from this Sitepoint article) for the window.name session storage.
As you might guess, this script is not affected by the bug in my original post. Why? What makes this one work, and my simple example above not work? This bit right here is the key:
// page unload event
if (window.addEventListener) window.addEventListener("unload", Save, false);
else if (window.attachEvent) window.attachEvent("onunload", Save);
else window.onunload = Save;
For some reason, you MUST save the data back into the window.name container within the window's unload event.
Beware of using only the onunload method for this, as mobile safari will not remember the data. To get mobile safari to persist the data in window.name, you must save it manually before onunload. Essentially, for maximum compatibility, you must do both: save in onunload; save manually whenever new data is set.
window.name probably holds the name of the window which is set when you use target="bob", which actualy is the name of the window or frame ...so just use another global variable for example window._session ... if you have frames it would be nice to use window.top._session. FYI: All global JS variables are stored in window so if you define a global variable just like that: var name = "hello" ... you can access it also as window.name

Chrome JavaScript location object

I am trying to start 3 applications from a browser by use of custom protocol names associated with these applications. This might look familiar to other threads started on stackoverflow, I believe that they do not help in resolving this issue so please dont close this thread just yet, it needs a different approach than those suggested in other threads.
example:
ts3server://a.b.c?property1=value1&property2=value2
...
...
to start these applications I would do
location.href = ts3server://a.b.c?property1=value1&property2=value2
location.href = ...
location.href = ...
which would work in FF but not in Chrome
I figured that it might by optimizing the number of writes when there will be effectively only the last change present.
So i did this:
function a ()
{
var apps = ['ts3server://...', 'anotherapp://...', '...'];
b(apps);
}
function b (apps)
{
if (apps.length == 0) return;
location.href = apps[0]; alert(apps[0]);
setTimeout(function (rest) {return function () {b(rest);};} (apps.slice(1)), 1);
}
But it didn't solve my problem (actually only the first location.href assignment is taken into account and even though the other calls happen long enough after the first one (thanks to changing the timeout delay to lets say 10000) the applications do not get started (the alerts are displayed).
If I try accessing each of the URIs separately the apps get started (first I call location.href = uri1 by clicking on one button, then I call location.href = uri2 by clicking again on another button).
Replacing:
location.href = ...
with:
var form = document.createElement('form');
form.action = ...
document.body.appendChild(form);
form.submit();
does not help either, nor does:
var frame = document.createElement('iframe');
frame.src = ...
document.body.appendChild(frame);
Is it possible to do what I am trying to do? How would it be done?
EDIT:
a reworded summary
i want to start MULTIPLE applications after one click on a link or a button like element. I want to achieve that with starting applications associated to custom protocols ... i would hold a list of links (in each link there is one protocol used) and i would try to do "location.src = link" for all items of the list. Which when used with 'for' does optimize to assigning only once (the last value) so i make the function something like recursive function with delay (which eliminates the optimization and really forces 3 distinct calls of location.src = list[head] when the list gets sliced before each call so that all the links are taken into account and they are assigned to the location.src. This all works just fine in Mozilla Firefox, but in google, after the first assignment the rest of the assignments lose effect (they are probably performed but dont trigger the associated application launch))
Are you having trouble looping through the elements? if so try the for..in statement here
Or are you having trouble navigating? if so try window.location.assign(new_location);
[edit]
You can also use window.location = "...";
[edit]
Ok so I did some work, and here is what I got. in the example I open a random ace of spades link. which is a custom protocol. click here and then click on the "click me". The comments show where the JSFiddle debugger found errors.

Window.open doesn't return the window reference IE9

I'm using a script to mount my mailto link and call the default email editor. But I can't use document.location.href because of some bug in IE9, so I use window.open. It works. But I need to close the IE windows opened.
The problem is the window.close doesn't return the window reference.
function doMailto() {
var sMailto = 'mailto:?bcc=';
sMailto += document.getElementById('<%= txtEmails.ClientID %>').value;
out = window.open(sMailto);
out.close(); //CANT CALL CLOSE, BECAUSE OUT IS NULL
}
You have an extra paren at the end of the assignment line.
Also, are you trying to close the window in the same function as assigned? If not, you may need to declare the window variable outside the function so it can be closed when needed.
aside the syntax errors (two commas, two parentesis closing)...
you are opening a window that is external to the browser, your default mail client. You cannot control it through javascript.
Maybe it's an immediacy problem, try using:
var out = window.open()...
setTimeout(function(){out.close()}, 200)
and fiddle with the 200ms to see if it works then.
try
top.location.href = 'mailto:....';
you won't need to open or close any windows this way

opening a popup in IE - "Member not found"

This happens in IE6 when the user opens a popup window that opens a PDF inside. (this part works).
Then, the user opens another popup window, and at this point i get this error.
There is a good description and a possible solution here
my question is this:
Is there a better solution? Opening up a window and closing it right away seems like a silly solution to me.
I think I've got a better solution that doesn't involve closing the window first. The issue is that IE won't override a window (PDF or otherwise) if you attempt to open it again with an empty URL (i.e., ''). It will override a PDF with a non-empty URL, however. That could be a file, but about:blank works even better (which is what an empty URL does normally).
Depending on how your code is written, you may still want the try/catch, but this should eliminate the need:
windowHandle = window.open('about:blank',name,attributes);
windowHandle.document.location.href = url;
windowHandle.focus();
about:blank will force the PDF out of the child window and allow you to do what you need to do. It might not be a bad idea to place the setting of the URL and focus() in a windowHandle.onload() handler, so there aren't any timing issues with disposing of the PDF. I.e.:
windowHandle.onload=function(){
windowHandle.document.location.href = url;
windowHandle.focus();
};
I solved the problem using a try catch block.
windowHandle = window.open('',name,attributes);
try {
windowHandle.document.location.href = url;
} catch (exc) {
windowHandle.close();
windowHandle = window.open('',name,attributes);
windowHandle.document.location.href = url + suffix;
}
windowHandle.focus();
Seems to work for me.

Categories

Resources