On a recent project we came across an issue where user initiated popups get blocked in Safari when being called by an AS3 Flash app. The issue doesn’t happen in AS2 and I’d not come across it before, but when I did and I researched it I found it was a well documented issue with no solution. Most popup blockers are able to distinguish between a user initiated popup and an automatic one, and this is the case with all browsers with AS2 or all browsers except Safari with AS3. But what do you do if a popup is an integral part of your design and you’re using AS3? As far as I can tell there is no fix for this issue, we found some apparent solutions but when when tested them they failed.
What I came up with isn’t a fix so much as a working solution. When you initiate a popup in Flash it’s done by calling a JavaScript function called window.open(). This function returns a boolean of True upon success or False upon failure. So programmatically this gives us a way of knowing if the popup has been blocked. In which case we offer the user up an HTML link to the popup that we know won’t get blocked. I believe that when designed well and with thought this can be an elegant solution for a small base of users who are probably already used to seeing certain functionality across the web fail for them.
There’s obviously a number of way to implement this, but as a quick and dirty example lets create a hidden HTML block to appear if the popup fails:
Okay now lets look at the popup JavaScript function that Flash calls:
function shareFacebook(){
success=window.open('http://www.facebook.com/sharer.php?u=http://richie-p.com/blog','FacebookShare','toolbar=0,status=0,width=626,location=no,menubar=no,height=436');
if (!success){
document.getElementById("popupMessage").style.display="block";
}
}
So basically what’s going to happen is that the hidden window appears only if the popup failed, thus allowing for the user to click the HTML which doesn’t get blocked.
But what if we have multiple popup windows? We need a way to have one message div that can trigger an endless number of popups. And why does the message have to remain forever visible once it appears?
Bearing this in mind here’s an example of a more elegant generic version. Again it’s quick an dirty code and I wouldn’t necessarily expect it to be in a production environment in its current state:
This time we have the popupMessage call a generic function:
The actual popup JavaScript function that Flash calls is the same, but this time we need it to set global variables:
var popupFunc="";
var popupTimer="";
function shareFacebook(){
p=window.open('http://www.facebook.com/sharer.php?u=http://richie-p.com/blog','FacebookShare','toolbar=0,status=0,width=626,location=no,menubar=no,height=436');
if (!p){
popupFunc="facebookShare";
clearTimeout(popupTimer);
$("#popupMessage").slideDown("slow");
popupTimer=window.setTimeout('$("#popupMessage").slideUp("slow")',10000);
}
}
So what basically happens is if the popup fails we set the name of the popup function that failed into a global variable called popupFunc. We use the jQuery slideDown() method to gracefully make the message appear. We also use a global variable called popupTimer to hide the message after 10 seconds. And in case the message is already showing from a different request we clear the popupTimer so it doesn’t disappear too quickly.
And finally lets look at the generic popup function:
function launchPopup(){
$("#popupMessage").slideUp("slow");
eval(popupFunc+"()");
}
We hide the message and call the popup function.
Like I say this is all quick and dirty for display purposes. But I really believe this to be a solid and elegant solution to a frustrating and problematic situation.