简体   繁体   中英

How do I get JavaScript to open a popup window on the current monitor

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)?

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;
}

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));
// 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);
  })
}

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();
    }
}

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 )

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;
}

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).

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');

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM