如何让JavaScript在当前显示器上打开弹出窗口

22

场景:

  1. 用户有两个显示器。
  2. 他们的浏览器在次要显示器上打开。
  3. 他们在浏览器中单击一个链接,该链接调用window.open()函数并指定了特定的窗口偏移量。
  4. 弹出窗口总是在他们的主要显示器上打开。

在JavaScript中是否有方法可以使弹出窗口在与初始浏览器窗口(启动器)相同的显示器上打开?


这些“解决方案”一个也不能帮助我。你找到了任何方法吗? - oma
@oma 我已经提供了一个适合我的解决方案,在这篇帖子中回答了你的问题:http://stackoverflow.com/questions/6911138/position-javascript-window-open-centered-on-secondary-screen/14269826#14269826 - Suvi Vignarajah
你应该在这里发布它,而不是在其他地方重复发布。另一个是重复的,而这个帖子有更相关的上下文。 - oma
真的,我在发布另一个帖子后才看到这个问题 - 让我把我的答案移到这里。 - Suvi Vignarajah
8个回答

22
您无法指定显示器,但可以将弹出窗口的位置指定为相对于单击引起窗口弹出的位置。
使用getMouseXY()函数获取要传递给window.open()方法的左和上参数的值。(左和上参数仅适用于V3及以上版本的浏览器)。
window.open文档: 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;
}

19

以下是我从 Facebook OAuth API 中不怕丢脸地逆向工程出来的东西。在 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));

这行代码的作用是什么?var h = (a < 0) ? window.screen.width + a : a;使用这行代码后,我的屏幕定位不正确。 - plainjimbo
在 OS X 上,Firefox 中的所有监视器布置都可以正常工作。但对于 Chrome 中的上下监视器布置则无法正常工作(水平位置正确但垂直方向不会移动到主监视器之外)。对于 Safari 中的并列排列,则无法横向移动到主监视器之外,但垂直定位是正确的。 对于 Chrome 和 Safari 我认为没有其他解决方法了,这似乎是浏览器限制/错误。 - plainjimbo
当我尝试定位Facebook分享对话框时,这对我非常完美(我打赌很多查找此问题的人都是出于同样的原因)。 - Jon z
@plainjimbo 我认为这可能是某些浏览器在存在两个屏幕的情况下将screenX返回为负数。不过我不明白为什么要将顶部除以2.5。 - Aseem Bansal

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

按照以下方式调用,它将在当前窗口的顶部打开

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

或者稍微偏移一下
popup('http://www.google.com', 'my-win', 30, 30);

重点是window.screenX/screenLeft给出的位置是相对于整个桌面而不仅仅是监视器的。
window.screen.left是给你需要的信息的理想选择。问题在于它在页面加载时设置,用户可能会将窗口移动到另一个监视器上。
更多研究
解决这个问题的最终方案(超出了仅仅从当前窗口位置进行偏移)需要知道窗口所在屏幕的尺寸。由于屏幕对象在用户移动窗口时不会更新,我们需要自己构建一种检测当前屏幕分辨率的方法。这是我想出的方法。
/**
 * 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();
};

如果您希望始终在窗口所在的任何监视器的左上角打开窗口,则可以使用以下方法:

function openAtTopLeftOfSameMonitor(url, winName) {
  getScreenProps(function(scr){
    window.open(url, winName, 'top=0,left=' + scr.left);
  })
}

在火狐浏览器中可以正常工作。似乎谷歌浏览器对左侧和顶部参数不太关注。 - oma

3

在当前屏幕上打开居中窗口,同时与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();
    }
}

0

只有用户11153的版本适用于Chrome和双屏幕。这是它的TypeScript版本。

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

0

我最近遇到了这个问题,最终找到了一种方法来定位弹出窗口在屏幕上的位置。请查看我的解决方案,链接在我的github页面上:https://github.com/svignara/windowPopUp

关键在于使用window.screen对象,该对象返回availWidthavailHeightavailLeftavailTop值(以及widthheight)。有关对象中变量的完整列表以及这些变量表示的内容,请参见https://developer.mozilla.org/en-US/docs/DOM/window.screen

本质上,我的解决方案是在单击弹出窗口的触发器时查找window.screen的值。这样我就知道它是从哪个监视器屏幕上单击的。而availLeft值则处理其余部分。以下是具体步骤:

基本上,如果从左侧开始的第一个可用像素(availLeft)是负数,那就表示在“主”监视器的左侧有一台监视器。同样,如果从左侧开始的第一个可用像素大于0,则意味着以下两种情况之一:
  1. 该监视器位于“主”监视器的右侧;或者
  2. 屏幕左侧有一些“垃圾”(可能是应用程序停靠栏或Windows开始菜单)。
无论哪种情况,您都希望弹出窗口的偏移量从左侧可用像素后开始。
offsetLeft = availableLeft + ( (availableWidth - modalWidth) / 2 )

0

如果您知道每个显示器的分辨率,您可以估计这个问题。

相对于鼠标(如上所述)或原始浏览器窗口的位置也可能很有用,尽管您必须假设用户使用浏览器最大化(这并不一定是真实情况)。


-3
只要您知道落在特定监视器上的x和y位置,就可以执行以下操作:
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');

OP应该如何知道x和y的位置?你不能假设总会有两个显示器,或者它们的分辨率...这并没有帮助。 - Ruan Mendes

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接