A universal createPopup() replacement?
You may want to look at some of the JavaScript libraries out there. Things like Dojo, Yahoo UI, or JQuery can help to encapsulate most of the browser-specific headaches. For example, with Dojo, take a look at http://dojotoolkit.org/api/. This would get you similar functionality to createPopup().
So I had a whole mess of legacy code that used window.createPopup()
so changing to a library would have been a lot of effort, and now that IE 11 doesn't support this method, we had to do something since our app is built to support Explorer. I was able to solve this to work in other browsers by writing the following code:
if(!window.createPopup){
window.createPopup = function (){
var popup = document.createElement("iframe"), //must be iframe because existing functions are being called like parent.func()
isShown = false, popupClicked = false;
popup.src = "about:blank";
popup.style.position = "absolute";
popup.style.border = "0px";
popup.style.display = "none";
popup.addEventListener("load", function(e){
popup.document = (popup.contentWindow || popup.contentDocument);//this will allow us to set innerHTML in the old fashion.
if(popup.document.document) popup.document = popup.document.document;
});
document.body.appendChild (popup);
var hidepopup = function (event){
if(isShown)
setTimeout(function (){
if(!popupClicked){
popup.hide();
}
popupClicked = false;
}, 150);//timeout will allow the click event to trigger inside the frame before closing.
}
popup.show = function (x, y, w, h, pElement){
if(typeof(x) !== 'undefined'){
var elPos = [0, 0];
if(pElement) elPos = findPos(pElement);//maybe validate that this is a DOM node instead of just falsy
elPos[0] += y, elPos[1] += x;
if(isNaN(w)) w = popup.document.scrollWidth;
if(isNaN(h)) h = popup.document.scrollHeight;
if(elPos[0] + w > document.body.clientWidth) elPos[0] = document.body.clientWidth - w - 5;
if(elPos[1] + h > document.body.clientHeight) elPos[1] = document.body.clientHeight - h - 5;
popup.style.left = elPos[0] + "px";
popup.style.top = elPos[1] + "px";
popup.style.width = w + "px";
popup.style.height = h + "px";
}
popup.style.display = "block";
isShown = true;
}
popup.hide = function (){
isShown = false;
popup.style.display = "none";
}
window.addEventListener('click', hidepopup, true);
window.addEventListener('blur', hidepopup, true);
return popup;
}
}
function findPos(obj, foundScrollLeft, foundScrollTop) {
var curleft = 0;
var curtop = 0;
if(obj.offsetLeft) curleft += parseInt(obj.offsetLeft);
if(obj.offsetTop) curtop += parseInt(obj.offsetTop);
if(obj.scrollTop && obj.scrollTop > 0) {
curtop -= parseInt(obj.scrollTop);
foundScrollTop = true;
}
if(obj.scrollLeft && obj.scrollLeft > 0) {
curleft -= parseInt(obj.scrollLeft);
foundScrollLeft = true;
}
if(obj.offsetParent) {
var pos = findPos(obj.offsetParent, foundScrollLeft, foundScrollTop);
curleft += pos[0];
curtop += pos[1];
} else if(obj.ownerDocument) {
var thewindow = obj.ownerDocument.defaultView;
if(!thewindow && obj.ownerDocument.parentWindow)
thewindow = obj.ownerDocument.parentWindow;
if(thewindow) {
if (!foundScrollTop && thewindow.scrollY && thewindow.scrollY > 0) curtop -= parseInt(thewindow.scrollY);
if (!foundScrollLeft && thewindow.scrollX && thewindow.scrollX > 0) curleft -= parseInt(thewindow.scrollX);
if(thewindow.frameElement) {
var pos = findPos(thewindow.frameElement);
curleft += pos[0];
curtop += pos[1];
}
}
}
return [curleft,curtop];
}
I'll start by admitting that it's pretty ugly. However, this worked for me to make the code that calls this method work in other browsers, and was easier than changing dozens of legacy (and poorly coded otherwise) pages to use some outside library, so perhaps it will help someone else out there.
It uses an iframe and creates a document
property on it because we had a lot of code that was along the lines of popup.document.body.innerHTML = "<span onclick = 'parent.someFunction()'>";
. Using the iframe instead of a div allows this to remain in it's junky state and still work.