4

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

Community
  • 1
  • 1
GibboK
  • 71,848
  • 143
  • 435
  • 658
  • Sorry guys, I was not able to make a jsbin as for limitation with iframes, please try it locally :) – GibboK Feb 18 '16 at 14:54

1 Answers1

2

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.

Arman Ozak
  • 2,304
  • 11
  • 11
  • It works!! I actually used input.style.opacity = 0; in the final implementation. Once again thanks for your time and help on this. – GibboK Feb 19 '16 at 09:07