

システム内の同機能の画面を2つ以上のタブ・ウィンドウでの表示を禁止するために以下ような動作となる処理を実装しようとしています。

①同一機能で二つ目のタブが開かれたとき  
②既に開かれていたタブにアラートを表示する  
③アラートのOKが押下されたときに既に開かれていたタブを閉じる

現在のソースとしては以下なのですが、①の直後に非アクティブな状態の既に開かれていたタブが閉じる処理まで実行されてしまいます。  
二つめのタブを開いた直後に既に開かれていたタブをアクティブした場合は、アラートが表示されるところで処理が停止します。  
私が期待している動作をさせることは可能でしょうか。あるいは近い動作をさせる方法があれば教えていただきたいです。

[code]

    //呼び出す処理
    let tabId = 'company-edit';
    $(function () {
        setInterval(function () {
            callback(tabId)
        }, 1000);
    });
    
    //複数タブ禁止処理
    let issuedAlready = false;
    
    const callback = openedTabId => {
        forbidMultiTab(openedTabId);
    };
    
    function forbidMultiTab(openedTabId) {
        let tabId = openedTabId;
        let sessionTabId = sessionStorage.getItem(tabId);
        let localTabId = localStorage.getItem(tabId);
    
        let newAction = function () {
            let tabID = new Date().getTime();
            sessionStorage.setItem(tabId, tabID);
            localStorage.setItem(tabId, tabID);
            issuedAlready = true;
        };
    
        let currentAction = function () {
        };
    
        let oldAction = function () {
            alert('この機能は同時に複数のウィンドウ・タブで開くことができません');
            window.open('about:blank', '_self').close();
        };
    
        if (sessionTabId == null || (sessionTabId === localTabId && !issuedAlready)) {
            // sessionStorageにタブIDが保存されていないとき
            // もしくはIE8対応として、「新しいタブで開く」から開くと、sessionStorageの値がコピーされているので、発番フラグが立っていないとき
            newAction();
    
        } else if (sessionTabId === localTabId) {
            // sessionStorageの値とlocalStorageの値が等しいとき
            currentAction();
    
        } else {
            oldAction();
        }
    }
    
[/code]


CC BY-SA 4.0
2019-09-12T06:31:37.233
59010
2022-04-19T20:05:05.447
2019-09-12T15:59:47.040
3060
34779
question
javascript
非アクティブなタブでのJavaScriptの動作について


自己解決したので、私の試行錯誤を記載いたします。  
アラートは表示された後に他のタブにフォーカスが移ると、「OK」を押したときと同様に後続の処理が流れるものと理解しました。  
最終的には画面にフォーカスがないときは閉じる処理をしないように工夫し、概ね期待する動作を実現できました。  
以下、ソースです。

[code]

    //呼び出し側の記述
    
    let tabId = 'company-edit';
        $(function () {
            setInterval(function () {
                checkTab(tabId)
            }, 1000);
        });
    
    //画面をロードした時刻
    let loadingTime = new Date().getTime();
    
    //アラートが重複して設定されないようにするためのフラグ
    let setAlert = false;
    
    //画面がアクティブじゃないときに閉じないようにするためのフラグ
    let isFocus;
    $(window).focus(function() {
        isFocus = true;
    }).blur(function() {
        isFocus = false;
    });
    
    //変数に関数をいれておくことでsetIntervalから引数ありで呼び出せる
    const checkTab = openedTabId => {
        forbidMultiTab(openedTabId);
    };
    
    function forbidMultiTab(tabId) {
    
        let localTabTimestamp;
        let localData = localStorage.getItem(tabId);
        if(localData){
            localData = JSON.parse(localData);
            localTabTimestamp  = localData.time;
        }
    
        let sessionTabTimestamp;
        let sessionData = sessionStorage.getItem(tabId);
        if(sessionData){
            sessionData = JSON.parse(sessionData);
            sessionTabTimestamp = sessionData.time;
        }
    
        //最初に開いた画面の場合
        let newAction = function () {
            issuedAlready = true;
            let tmpData = {'time': loadingTime};
            sessionStorage.setItem(tabId, JSON.stringify(tmpData));//タブ
            localStorage.setItem(tabId, JSON.stringify(tmpData));//ブラウザ全体
            //画面を閉じたときのイベントを設定する
            $(function () {
                $(window).off("beforeunload");
                $(window).on("beforeunload",function(e){
                    deleteLocalStorage(tabId);
                });
            });
        };
    
        let currentAction = function () {
        };
    
        //画面を閉じる場合
        let closeAction = function () {
            if (!setAlert && isFocus) {
                alert('この機能は同時に複数のウィンドウ・タブで開くことができません。このタブを閉じます。');
                window.open('about:blank', '_self').close();
            }
        };
    
        if (sessionTabTimestamp == null) {
            // sessionStorageにタブIDが保存されていないとき
            newAction();
    
        } else if (localTabTimestamp === sessionTabTimestamp ) {
            // sessionStorageの値とlocalStorageの値が等しいとき
            currentAction();
    
        } else if (localTabTimestamp < sessionTabTimestamp) {
            // 先に開いたタブがあるとき
            closeAction();
    
        } else {
            // 今の画面のロード時刻の方が古いとき
            localStorage.setItem(tabId, JSON.stringify({'time': loadingTime}));
        }
    
    }
    
    //localStorageに保存された時刻を削除する
    let deleteLocalStorage = function () {
        let localData = localStorage.getItem(tabId);
        localData = JSON.parse(localData);
        if (localData.time === loadingTime) {
            localStorage.removeItem(tabId);
        }
    };
    
    
[/code]


CC BY-SA 4.0
2019-09-12T12:18:35.417
59024
2019-09-12T12:18:35.417
34779
59010
answer