4

I am normally used to "window.open" to open a popup window into a new URL. How can open a window into a new URL, shadow out/grey out the current window, and on close remove the shadow background.

Is it best to use jQuery to do this? Could I use the default libraries without use jquery plugins?

I want to do something like this and then "disable" my shadow on unload. Hopefully that uses core jQuery libraries or standard javascript calls. I want to avoid using any plugins besides jQuery.

var popup = window.open('http://google.com', 'popup');
showShadow();
$(window).unload(function() {
    if(!popup.closed) {
        disableShadow();
    }
});
Berlin Brown
  • 11,504
  • 37
  • 135
  • 203
  • I would really recomend you use a modal window instead of a pop up window. If you don't want to use a plug-in for jquery, it is really easy to just put a div that has half opacity, 100% size and high z-index, and another one with higher z-index that contains the pop up you want either with ajax or an i-frame. Would you like a solution like that? Or if you prefer, a real pop up solution that can be used in all browsers could be done with a cookie. Would you like me to post any of those solutions? – Oscar Abraham Nov 07 '12 at 16:35

13 Answers13

4

Basically, you can open the popup and set that window the beforeunload. In short, something like this:

popup = window.open("", "name", "width=400, height=300")
popup.onbeforeunload = function() { $('#shadow').hide();}

I created a fiddle for you.

http://jsfiddle.net/DDksS/

Bart Calixto
  • 19,210
  • 11
  • 78
  • 114
3

So you want to build your own modal box using jQuery instead of using an existing plugin? ...OK, let's play (as it was already pointed out, using popups is not a user-friendly solution):

Your check list :

 - the trigger
 - the shadow layer
 - the modal box size and position
 - add content to modal and display it along the shadow

1) The trigger is a simple html link to open the content inside the modal

<a href="http://jsfiddle.net" class="myModal" data-width="400" data-height="300">open url</a>

... we will pass the size of the modal via data-width and data-height (HTML5) attributtes.

2) The shadow layer is the html structure that we will append to the body after the trigger. We can set the structure in a js variable

var shadow = "<div class='shadow'></div>";

3) As we mentioned, the size of the modal is set through some data-* attributes in the link. We would need to do some math

var modalWidth = $(this).data("width");
var modalHeight = $(this).data("height");
var modalX = (($(window).innerWidth()) - modalWidth) / 2; // left position
var modalY = (($(window).innerHeight()) - modalHeight) / 2; // top position

NOTE : $(this) is our trigger selector .myModal that we'll get inside an .on("click") method later on. BTW, the .on() method requires jQuery v1.7+

4) Now we need to create the modal's html structure and pass the content href. We'll create a function

function modal(url) {
    return '<div id="modal"><a id="closeModal" title="close" href="javascript:;"><img src="http://findicons.com/files/icons/2212/carpelinx/64/fileclose.png" alt="close" /></a><iframe src="' + url + '"></iframe></div>';
}

... as you can see, our structure contains a close button to remove the modal and the shadow layer. The function also gets a parameter when is called (url) which allows to set the src attribute of the iframe tag.

NOTE : we have to use the iframe tag to open external urls, however we should always consider the same origin policy and other security restrictions when using iframes.

So now, we need to put together all the events after we click on our .myModal trigger, which are appending both the shadow and the modal box to the body and to remove them when we click on the close button so

$(".myModal").on("click", function(e) {
    e.preventDefault();
    // get size and position
    modalWidth = $(this).data("width");
    modalHeight = $(this).data("height");
    modalX = (($(window).innerWidth()) - modalWidth) / 2;
    modalY = (($(window).innerHeight()) - modalHeight) / 2;
    // append shadow layer
    $(shadow).prependTo("body").css({
        "opacity": 0.7
    });
    // append modal (call modal() and pass url)
    $(modal(this.href)).appendTo("body").css({
        "top": modalY,
        "left": modalX,
        "width": modalWidth,
        "height": modalHeight
    });
    // close and remove
    $("#closeModal").on("click", function() {
        $("#modal, .shadow").remove();
    });
}); // on 

STYLE : of course we will need some basic CSS style to make our modal elements work properly:

.shadow {width: 100%; height: 100%; position: fixed; background-color: #444; top: 0; left:0; z-index: 400}
#modal {z-index: 500; position: absolute; background: #fff; top: 50px;}
#modal iframe {width: 100%; height: 100%}
#closeModal {position: absolute; top: -15px; right: -15px; font-size: 0.8em; }
#closeModal img {width: 30px; height: 30px;}

* SEE DEMO *

BONUS : you could also bind a keyup event to close the modal using the escape key

$(document).keyup(function(event) {
    if (event.keyCode === 27) {
        $("#modal, .shadow").remove();
    }
}); //keyup

LAST NOTE : the code is subject to many improvements and optimization but is a basic layout of what many lightboxes do. My last recommendation : use fancybox for more advanced functionality ... sometimes it doesn't worth the effort to re-invent the wheel ;)

Community
  • 1
  • 1
JFK
  • 40,963
  • 31
  • 133
  • 306
  • Great answer. Don't understand why it has only one upvote. I'll add another one, though. Few votes on hard to understand answers reflect the very poor SO community knowledge. Thanks for the time you spent to post such a detailed and complete answer. – Felipe Alameda A Sep 02 '13 at 06:30
2

Using Javascript to create new popup windows is so 1990's, not to mention not very user-friendly. What you're looking for, both UI-wise and looks-wise is a modal dialog; there's billions of examples and pre-packaged jquery snippets on how to create modal dialogs, and most client-side UI frameworks such as jQuery UI, YUI and Bootstrap have modal dialog functionality built-in. I'd recommend diving into those.

cthulhu
  • 3,142
  • 2
  • 23
  • 32
  • 2
    One could also argue that a native browser pop up is preferable over a custom modal dialog. Less overhead, more recognizable (styled according to user agent UI and OS), easier to implement. – Joram van den Boezem Nov 07 '12 at 17:29
  • Why does this kind of personal opinion has been upvoted while it is not answering the question at all? It's like someone asks «what are the directions to drive from point A to point B» and answering «you don't have to drive, just take a walk»... – Cholesterol Jan 23 '14 at 17:32
1

Try jquery plugins such as fancybox http://fancybox.net/

iJade
  • 23,144
  • 56
  • 154
  • 243
1

Basically, you need to attach an event listener to your new window to run the disableShadow() function in your webpage.

If you add this to your code I think it should work.

popup.unload(function() { disableShadow() }); 

Adapted From: Attach an onload handler on a window opened by Javascript

Community
  • 1
  • 1
eighteyes
  • 1,306
  • 1
  • 11
  • 18
1

You should use the beforeUnload event of the window instance returned by the window.open() call, like this:

popup = window.open('relative_url', 'popup');
$(popup).bind('beforeunload', function() {
    disableShadow();
});

Note that the URL must be on the same domain in order for the opener window to interact with the popup!

See the fiddle here: http://jsfiddle.net/hongaar/QCABh/

Joram van den Boezem
  • 1,104
  • 10
  • 24
1

All you need is standard javascript function showModalDialog. Then your code will look like

var url = 'http://google.com';
showShadow();
var optionalReturnValue = showModalDialog(url);

//Following code will be executed AFTER you return (close) popup window/dialog
hideShadow(); 

UPDATE As hongaar stated Opera does not like showModalDialog. And it does not fire on(before)unload when popup is closed either. To make workaround you need timer (window.setTimeout) to periodically check if window still exists. For further details look here

Community
  • 1
  • 1
Jan Pfeifer
  • 2,854
  • 25
  • 35
  • OK but doesn't seem to be as widely supported as window.open/ unload. – Berlin Brown Nov 06 '12 at 15:07
  • Its supported by all major browsers now. Its still the best you can get. If not you will only "emulate" modal behaviour with window.open. The next option, as others stated, is to use non-window dialog. IE jquery dialog or your own. Your DIV with loaded (AJAX/jQuery.load) content on top of your shadow. – Jan Pfeifer Nov 06 '12 at 16:18
  • 1
    Keep in mind though, `showModalDialog` in Google Chrome will display a non-modal window, and Opera doesn't support it at all. – Joram van den Boezem Nov 06 '12 at 17:18
  • Indeed. But it works still good in Chrome and "additional modality" will be achieved by custom shadow in this case. – Jan Pfeifer Nov 07 '12 at 07:01
  • I wonder if JavaScript execution stops after calling the showModalDialog function in Chrome? – Joram van den Boezem Nov 07 '12 at 13:45
1

You can open a new window, and when it closes you can execute a function in the opener window.

I'll do a quick example by writing the script right into the new window, but you could also just include it in the HTML that is used for the new window if a link is supplied for the popup:

$("#popupBtn").on('click', openPopup); //using a button to open popup

function openPopup() {
    $('#cover').fadeIn(400);
        var left = ($(window).width()/2)-(200/2),
            top = ($(window).height()/2)-(150/2),
            pop = window.open ("", "popup", "width=400, height=300, top="+top+", left="+left),
            html  = '<!DOCTYPE html>';
            html += '<head>';
            html += '<title>My Popup</title>';
            html += '<scr'+'ipt type="text/javascript">';
            html += 'window.onbeforeunload = function() { window.opener.fadeoutBG(); }';
            html += '</sc'+'ript>';
            html += '</head>';
            html += '<body bgcolor=black>';
            html += '<center><b><h2 style="color: #fff;">Welcome to my most excellent popup!</h2></b></center><br><br>';
            html += '<center><b><h2 style="color: #fff;">Now close me!</h2></b></center>';
            html += '</body></html>';

        pop.document.write(html);
}

window.fadeoutBG = function() { //function to call from popup
    $('#cover').fadeOut(400);
}

Using a fixed cover that is faded in will also prevent any clicks on elements on the page, and you could even attach a click handler to the cover with pop.close() to close the popup if the cover is clicked, just like a modal would close if you clicked outside it.

One of the advantages of calling a function on the parent page from the popup is that values can be passed from the popup to the parent, and you can do a lot of stuff you otherwise could'nt.

FULLSCREEN_FIDDLE

FIDDLE

adeneo
  • 312,895
  • 29
  • 395
  • 388
  • this way you get a prevent popup blocker. – Bart Calixto Nov 07 '12 at 02:00
  • @Bart - That's just details! I don't get a popup blocker. I've edited the answer to resolve popup blocker issues? – adeneo Nov 07 '12 at 02:19
  • You can keep all the necessary JavaScript in the opener document, no need to use document.write(). – Joram van den Boezem Nov 07 '12 at 13:34
  • All the mainstream browsers have built-in popup blockers that will most likely block this. Second, inlining HTML in your Javascript via string concatenation is rather ugly; prefer to externalize the html shown, or use a client-side templating library instead. – cthulhu Nov 07 '12 at 15:32
  • Did you not read the answer "I'll do a quick example writing the script right into the new window"? Normally you would use an external file for this, but that's not really an option in jsFiddle, so I used document.write for the example? – adeneo Nov 07 '12 at 23:02
  • I actually like the solution, I just need onbeforeunload to work. – Berlin Brown Nov 08 '12 at 01:08
1

Why don't you just use jQuery UI? I know that you don't want another library but is rather extension of jQuery rather then another lib since it can live without it. It have great deal of widget and every one of them can be changed,configured. What is best that it can viewed with different themes, even you can create one with they're theme roller fast and easy, and it can be modularized. Just take what you need in current project. Check this out:

http://jqueryui.com/dialog/#modal-form

It's really simple to use. With this you can open modal dialog with frame to different url. On close event you can do whatever you want.

n.podbielski
  • 595
  • 6
  • 11
1

Try ColorBox

its simple and easy to use

http://www.jacklmoore.com/colorbox

quick example:

<link rel="stylesheet" href="http://www.jacklmoore.com/colorbox/example1/colorbox.css" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script>
<script src="http://www.jacklmoore.com/colorbox/colorbox/jquery.colorbox.js"></script>
<script>
    $(document).ready(function(){
        //Examples of how to assign the ColorBox event to elements
        $(".iframe").colorbox({iframe:true, width:"80%", height:"80%"});
    });
</script>

<a class='iframe' href="http://google.com">Outside Webpage (Iframe)</a>
Ardavan Kalhori
  • 1,664
  • 1
  • 18
  • 32
0

You can also try this out ... http://fancyapps.com/fancybox/

Examples here

thedev
  • 2,816
  • 8
  • 34
  • 47
0

try http://thickbox.net/ in modal type, examples: http://thickbox.net/#examples

Dario
  • 417
  • 4
  • 17
0

I've done this as well.

First off, some URLs simply WILL NOT WORK in an (iframe) modal window; I can't say if it'll work in the browser-supported native modal windows as I haven't tried this. Load google or facebook in an iframe, and see what happens.

Second, things like window onunload events don't always fire (as we've seen some people already).

The accepted answer version will also only work on a static page. Any reloading (even F5 on the page) will cause the shadow to hide. Since I can't comment on the accepted answer, I at least wanted this to be known for anyone else looking at these results.

I've taken a less technical approach to solving this problem in the past: polling.

http://jsfiddle.net/N8AqH/

<html>
    <head>
        <script type="text/javascript">
            function openWindow(url)
            {
                var wnd = window.open(url);
                var timer = null;

                var poll = function()
                {
                    if(wnd.closed) { alert('not opened'); clearInterval(timer); }
                };  

                timer = setInterval(poll, 1000);
            }
        </script>
    </head>
    <body>
        <a href="#" onclick="openWindow('http://www.google.com'); return false;">click me</a>
    </body>
</html>

See the link above for an example. I tested in IE, FF, and Chrome. My timer is every 1 second, but the effort on the browser is so low you could easily drop this down to 100 ms or so if you wanted it to feel more instant.

All you'd have to do in this example is, after calling window.open, call your "show shadow" function and instead of alerting when you close, call your "hide shadow" function and it should achieve what you're looking for.

Eli Gassert
  • 9,745
  • 3
  • 30
  • 39