如何获取JavaScript以在当前监视器上打开弹出窗口

如何获取JavaScript以在当前监视器上打开弹出窗口

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

场景:

  • 用户有两个监视器。
  • 他们的浏览器在辅助监视器上打开。
  • 他们单击浏览器中的一个链接,该链接调用window.open()并具有特定的上下窗口偏移量。
  • 弹出窗口始终在其主监视器上打开。
  • JavaScript中是否有任何方法可以使弹出窗口在与初始浏览器窗口(打开器)相同的监视器上打开?


    您不能指定监视器,但是可以将弹出窗口的位置指定为相对于单击导致窗口弹出的位置。

    使用getMouseXY()函数获取要作为左参数和顶参数传递给window.open()方法的值。 (左侧和顶部的args仅适用于V3及更高版本的浏览器)。

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

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    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;
    }

    这是我从Facebook oauth API进行的无耻反向工程。在Firefox / Chrome中的主监视器和辅助监视器上进行了测试。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    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));

    1
    2
    3
    4
    5
    6
    // 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))
    }

    像下面这样调用它,它将在当前窗口的顶部打开

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

    或使其稍微偏移

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

    关键是window.screenX / screenLeft可以为您提供相对于整个桌面的位置,而不仅仅是显示器。

    window.screen.left将是为您提供所需信息的理想人选。问题在于它是在页面加载时设置的,用户可以将窗口移至另一台监视器。

    更多研究

    解决此问题的最终方法(不仅仅是从当前窗口位置偏移)还需要知道窗口所在的屏幕尺寸。由于屏幕对象不会随着用户移动窗口而更新,因此我们需要精心设计自己检测当前屏幕分辨率的方式。这是我想出的

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    /**
     * 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();
    };

    因此,如果您想始终打开窗口所在的任何监视器的左上方的窗口,则可以使用以下命令:

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


    在当前监视器上打开居中窗口,也可与Chrome一起使用:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    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的版本可用于Chrome和双屏。这是它的TypeScript版本。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    popupOnCurrentScreenCenter(url: string, title: string, w: number, h: number): Window|null {
        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) {
            newWindow.focus();
        }
        return newWindow;
    }

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

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

    本质上,每当单击弹出窗口的触发器时,我的解决方案都会找到window.screen的值。这样,我可以确定是从哪个监视器屏幕上单击的。 availLeft值负责其余部分。这是如何做:

    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:

  • The monitor is to the right of the"main" monitor, OR
  • There is some"junk" on the left side of the screen (possibly the application dock or windows start menu)
  • 无论哪种情况,您都希望弹出窗口的偏移量从左侧的可用像素之后开始。

    1
    offsetLeft = availableLeft + ( (availableWidth - modalWidth) / 2 )

    如果您知道每个监视器的分辨率,则可以进行估算。
    对于公共网站来说这是个坏主意,但如果您知道(出于某种奇怪的原因)这种情况将始终适用,则可能会很有用。

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


    只要您知道特定监视器上的x和y位置,就可以执行以下操作:

    1
    2
    3
    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');


    推荐阅读