22

Scenario:

  1. The user has two monitors.
  2. Their browser is open on the secondary monitor.
  3. They click a link in the browser which calls window.open() with a specific top and left window offset.
  4. The popup window always opens on their primary monitor.

Is there any way in JavaScript to get the popup window to open on the same monitor as the initial browser window (the opener)?

jeremcc
  • 8,633
  • 11
  • 45
  • 55
  • not a single one of these 'solutions' work for me. Did you find any way. – oma Oct 07 '12 at 15:29
  • @oma i've provided a solution that works for me, answered in this post though: http://stackoverflow.com/questions/6911138/position-javascript-window-open-centered-on-secondary-screen/14269826#14269826 – Suvi Vignarajah Jan 11 '13 at 00:36
  • you should've posted it here instead. The other is a dup and this thread has more relevant context. – oma Jan 11 '13 at 16:44
  • true, i only saw this question after posting my answer on the other thread - let me move my answer over – Suvi Vignarajah Jan 12 '13 at 04:33

8 Answers8

22

You can't specify the monitor, but you can specify the position of the popup window as being relative to the where the click caused the window to popup.

Use the getMouseXY() function to get values to pass as the left and top args to the window.open() method. (the left and top args only work with V3 and up browsers).

window.open docs: http://www.javascripter.net/faq/openinga.htm

function getMouseXY( e ) {
    if ( event.clientX ) { // Grab the x-y pos.s if browser is IE.
        CurrentLeft = event.clientX + document.body.scrollLeft;
        CurrentTop  = event.clientY + document.body.scrollTop;
    }
    else {  // Grab the x-y pos.s if browser isn't IE.
        CurrentLeft = e.pageX;
        CurrentTop  = e.pageY;
    }  
    if ( CurrentLeft < 0 ) { CurrentLeft = 0; };
    if ( CurrentTop  < 0 ) { CurrentTop  = 0; };  

    return true;
}
rp.
  • 17,483
  • 12
  • 63
  • 79
19

Here is something I shamelessly reverse engineered from the Facebook oauth API. Tested on a primary and secondary monitor in Firefox/Chrome.

function popup_params(width, height) {
    var a = typeof window.screenX != 'undefined' ? window.screenX : window.screenLeft;
    var i = typeof window.screenY != 'undefined' ? window.screenY : window.screenTop;
    var g = typeof window.outerWidth!='undefined' ? window.outerWidth : document.documentElement.clientWidth;
    var f = typeof window.outerHeight != 'undefined' ? window.outerHeight: (document.documentElement.clientHeight - 22);
    var h = (a < 0) ? window.screen.width + a : a;
    var left = parseInt(h + ((g - width) / 2), 10);
    var top = parseInt(i + ((f-height) / 2.5), 10);
    return 'width=' + width + ',height=' + height + ',left=' + left + ',top=' + top + ',scrollbars=1';
}   

window.open(url, "window name", "location=1,toolbar=0," + popup_params(modal_width, modal_height));
Chase Seibert
  • 15,703
  • 8
  • 51
  • 58
  • what's the point of this line? ```var h = (a < 0) ? window.screen.width + a : a;``` It wasn't positioning the screen correctly for me with that line. – plainjimbo Aug 16 '13 at 01:31
  • On OS X this works for all monitor arrangements in firefox. Does not work for over-under monitor arrangements in Chrome (will correctly position horizontally but won't move vertically beyond the main monitor). Does not work for side-by-side arrangements in Safari (will correctly position vertically but won't move horizontally beyond the main monitor). For chrome and safari I don't think there's anything else to be done though, seems to be broswer limitations/bugs. – plainjimbo Aug 16 '13 at 01:34
  • This worked perfectly for me when trying to position the facebook Share dialog (I bet a lot of the people looking up this question are doing it for the same reason). – jrz Sep 19 '13 at 22:19
  • @plainjimbo I think that may be some browser returning screenX as -ve for the other screen in case of 2 screens. Didn't get why the top was divided by 2.5 though. – Aseem Bansal Sep 21 '15 at 08:44
7
// Pops a window relative to the current window position
function popup(url, winName, xOffset, yOffset) {
  var x = (window.screenX || window.screenLeft || 0) + (xOffset || 0);
  var y = (window.screenY || window.screenTop || 0) + (yOffset || 0);
  return window.open(url, winName, 'top=' +y+ ',left=' +x))
}

Call it like the following and it will open on top of the current window

popup('http://www.google.com', 'my-win');

Or make it slightly offset

popup('http://www.google.com', 'my-win', 30, 30);

The point is that window.screenX/screenLeft give you the position in relationship to the entire desktop, not just the monitor.

window.screen.left would be the ideal candidate to give you the information you need. The problem is that it's set when the page is loaded and the user could move the window to the other monitor.

More research

A final solution to this problem (beyond just offsetting from the current window position) requires knowing the dimensions of the screen that the window is in. Since the screen object doesn't update as the user moves a window around, we need to craft our own way of detecting the current screen resolution. Here's what I came up with

/**
 * Finds the screen element for the monitor that the browser window is currently in.
 * This is required because window.screen is the screen that the page was originally
 * loaded in. This method works even after the window has been moved across monitors.
 * 
 * @param {function} cb The function that will be called (asynchronously) once the screen 
 * object has been discovered. It will be passed a single argument, the screen object.
 */
function getScreenProps (cb) {
    if (!window.frames.testiframe) {
      var iframeEl = document.createElement('iframe');
      iframeEl.name = 'testiframe';
      iframeEl.src = "about:blank";
      iframeEl.id = 'iframe-test'
      document.body.appendChild(iframeEl);
    }

    // Callback when the iframe finishes reloading, it will have the 
    // correct screen object
    document.getElementById('iframe-test').onload = function() {
      cb( window.frames.testiframe.screen );
      delete document.getElementById('iframe-test').onload;
    };
    // reload the iframe so that the screen object is reloaded
    window.frames.testiframe.location.reload();
};

So if you wanted to always open the window at the top left of whatever monitor the window is in, you could use the following:

function openAtTopLeftOfSameMonitor(url, winName) {
  getScreenProps(function(scr){
    window.open(url, winName, 'top=0,left=' + scr.left);
  })
}
Ruan Mendes
  • 90,375
  • 31
  • 153
  • 217
  • works in FF. seems like chrome doesn't care much about the left and top parameters. – oma Oct 07 '12 at 15:40
3

Open centered window on current monitor, working also with Chrome:

function popupOnCurrentScreenCenter(url, title, w, h) {
    var dualScreenLeft = typeof window.screenLeft !== "undefined" ? window.screenLeft : screen.left;
    var dualScreenTop = typeof window.screenTop !== "undefined" ? window.screenTop : screen.top;

    var width = window.innerWidth ? window.innerWidth :
        document.documentElement.clientWidth ? document.documentElement.clientWidth : screen.width;
    var height = window.innerHeight ? window.innerHeight :
        document.documentElement.clientHeight ? document.documentElement.clientHeight : screen.height;

    var left = ((width / 2) - (w / 2)) + dualScreenLeft;
    var top = ((height / 2) - (h / 2)) + dualScreenTop;
    var newWindow =
        window.open(url, title, 'scrollbars=yes, width=' + w + ', height=' + h + ', top=' + top + ', left=' + left);

    // Puts focus on the newWindow
    if (window.focus) {
        newWindow.focus();
    }
}
user11153
  • 8,536
  • 5
  • 47
  • 50
0

I ran into this issue recently and finally found a way to position the pop up window on the screen that it's triggered from. Take a look at my solution on my github page here: https://github.com/svignara/windowPopUp

The trick is in using the window.screen object, which returns availWidth, availHeight, availLeft and availTop values (as well as width and height). For a complete list of the variables in the object and what these variables represent look at https://developer.mozilla.org/en-US/docs/DOM/window.screen.

Essentially, my solution finds the values of the window.screen whenever the trigger for the popup is clicked. This way I know for sure which monitor screen it's being clicked from. The availLeft value takes care of the rest. Here's how:

Basically if the first available pixel from the left (availLeft) is negative, that's telling us there is a monitor to the left of the "main" monitor. Likewise, if the first available pixel from left is greater than 0, this means one of 2 things:

  1. The monitor is to the right of the "main" monitor, OR
  2. There is some "junk" on the left side of the screen (possibly the application dock or windows start menu)

In either case you want the offset of your popup to start from after the available pixel from the left.

offsetLeft = availableLeft + ( (availableWidth - modalWidth) / 2 )
Suvi Vignarajah
  • 5,758
  • 27
  • 38
0

Only user11153's version works with Chrome and dual screen. Here is its TypeScript version.

popupOnCurrentScreenCenter(url: string, title: string, w: number, h: number): Window|null {
    var dualScreenLeft = typeof window.screenLeft !== "undefined" ? window.screenLeft : (<any>screen).left;
    var dualScreenTop = typeof window.screenTop !== "undefined" ? window.screenTop : (<any>screen).top;

    var width = window.innerWidth ? window.innerWidth :
        document.documentElement.clientWidth ? document.documentElement.clientWidth : screen.width;
    var height = window.innerHeight ? window.innerHeight :
        document.documentElement.clientHeight ? document.documentElement.clientHeight : screen.height;

    var left = ((width / 2) - (w / 2)) + dualScreenLeft;
    var top = ((height / 2) - (h / 2)) + dualScreenTop;
    var newWindow =
        window.open(url, title, 'scrollbars=yes, width=' + w + ', height=' + h + ', top=' + top + ', left=' + left);

    // Puts focus on the newWindow
    if (window.focus && newWindow) {
        newWindow.focus();
    }
    return newWindow;
}
hirano
  • 106
  • 5
0

If you know the resolution of each monitor, you could estimate this. A bad idea for a public website, but might be useful if you know (for some odd reason) that this scenario will always apply.

Relative position to the mouse (as said above) or to the original browser window could also be useful, Though you'd have to suppose the user uses the browser maximized (which is not necessarily true).

WhyNotHugo
  • 9,423
  • 6
  • 62
  • 70
-3

as long as you know the x and y position that falls on the particular monitor you can do:

var x = 0;
var y = 0;
var myWin = window.open(''+self.location,'mywin','left='+x+',top='+y+',width=500,height=500,toolbar=1,resizable=0');
Jared
  • 8,390
  • 5
  • 38
  • 43
  • How is the OP supposed to know x and y position? You can't assume there'll always be two monitors, or their resolution... This doesn't help. – Ruan Mendes Jan 24 '11 at 20:27