简体   繁体   中英

How to programmatically applying focus to a parent frame within an iframe in Firefox (work around for window.focus())?

I need to programmatically set focus for a "parent" frame from an iframe .

Please try out the following example.

  • 01 - Click first on 01 show panel , and a div with an iframe will show up
  • 02 - Click within the iframe on 02 click me , the div with an iframe will be hidden

On step 02 I need to set the focus from the iframe to the "parent" frame .

I am doing this using window.focus() which works well on Chrome.

My problem is on Firefox , the script keeps the focus on the iframe (see the result in div resultFocus ) and does not focus on "parent"frame

I need a work around for FireFox, any idea how to fix it?

test.html

<!DOCTYPE html>
<html>
<head>
    <title></title>
    <meta charset="utf-8" />
    <style>
        #panel {
            position: absolute;
            top: 50px;
            left: 250px;
            width: 250px;
            height: 150px;
        }
        #resultFocus {
            position:absolute;
            left: 650px;
        }
        .btn {
            width: 150px;
            height: 30px;
            margin: 5px;
            background-color: lightblue;
        }
    </style>
    <script>
        (function (window) {

            var _hidePanel = function () {
                var panel = document.getElementById('panel');
                panel.style.display = 'none';
            };
            var _showPanel = function () {
                var panel = document.getElementById('panel');
                panel.style.display = '';
            };

            var _addListeners = function () {
                var btnHide = document.getElementById('btnHide');
                btnHide.addEventListener('click', function (event) {
                    _hidePanel();
                    _setFocusMainWindow();
                    _showActiveFocus();
                    });
                var btnShow = document.getElementById('btnShow');
                btnShow.addEventListener('click', function (event) {
                    _showPanel();
                });

                var btnInner = document.getElementById('iframe').contentWindow.document.getElementById('btnInner');
                btnInner.addEventListener('click', function (event) {
                    _hidePanel();
                    _setFocusMainWindow();
                    _showActiveFocus();
                });

                var btnShowActiveFocus = document.getElementById('btnShowActiveFocus');
                btnShowActiveFocus.addEventListener('click', function (event) {
                    _showActiveFocus();
                });
            };

            var _showActiveFocus = function () {
                var resultFocus = document.getElementById('resultFocus');
                resultFocus.innerHTML = '';
                resultFocus.innerHTML = document.activeElement;
            };

            var _setFocusMainWindow = function () {
                window.focus();
            };

            window.start = function () {
                _addListeners();
                _hidePanel();
                _showActiveFocus();
            }
        })(window);
    </script>
</head>
<body onload="start();">
    <div id="btnShow" type="button" class="btn">01 show panel</div>
    <div id="btnHide" type="button" class="btn" style="display:none;">03 hide panel</div>
    <div id="btnShowActiveFocus" type="button" class="btn" style="display:none;">show active focus</div>
    <div id="panel">
        <iframe id="iframe" src="include.html"></iframe>
    </div>
    <div id="resultFocus" rows="2" cols="20"></div>
</body>
</html>

include.html

<!DOCTYPE html>
<html>
<head>
    <title></title>
    <meta charset="utf-8" />
    <style>
        body {
        background-color:orange;
        }

    </style>
    <script>
    </script>
</head>
<body>
<h1>I am an iframe!</h1>
    <button id="btnInner" type="button">02 - click me</button>

</body>
</html>

Possibly related: How to get window.focus() to work in firefox

You can solve this issue by adding an invisible fake focus target and focusing in and out of that target programmatically before focusing on the window itself. Here is how to do it:

Add the fake focus element in the DOM right at the beginning of start() :

window.start = function () {
    var input = document.createElement('INPUT');
    input.id = 'fakefocus';
    input.type = 'checkbox';
    input.style.position = 'absolute';
    input.style.left = '-999em';
    document.body.appendChild(input);

    _addListeners();
    _hidePanel();
    _showActiveFocus();
};

Focus in and out of the fake focus element right before _setFocusMainWindow(); in click event listener of the btnInner :

btnInner.addEventListener('click', function (event) {
    _hidePanel();
    var ff = document.getElementById('fakefocus');
    ff.focus();
    ff.blur();
    _setFocusMainWindow();
    _showActiveFocus();
});

And actually, after doing that, you might not even need window.focus(); anymore.

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