3

Webページにはいくつかのリンクがあります。

右クリックすると、「新しいタブでリンクを開く」オプション(ブラウザオプション)があります。

ユーザーが 2 つ以上のタブを開かないように制限したいですか? これどうやってするの?

<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<ul>
<li><a href="http://localhost:8080/struts_tab/abcForm1.action" oncontextmenu="return false;"><span>First Click[Right Click disabled]</span></a></li>
<li><a href="http://localhost:8080/struts_tab/defForm2.action"><span>Second clieck[Not more than 2 tabs]</span></a></li>
</ul>
</body>
</html>
4

1 に答える 1

4

ユーザーが新しいタブを開くことを制限することはできません。
(これは、ボタンもアドレスバーもないが、バックスペースやその他のイベントに応答する古いポップアップを思い出させます)

ただし、アプリに 3 番目のタブを開こうとする試みを認識させ、エラー メッセージなどの別の結果を読み込むことができます。次に例を示します。

開いているタブの最大数に達しました。同時に使用するタブは 2 つまでにしてください。close this tab

これを行うには、HTML5 sessionStorageを使用できます。
注: Web ストレージ(sessionStorageおよびlocalStorage)は、現在、すべてのブラウザーでサポートされています。

セッションストレージ

これは、ページ セッション中に使用できるストレージ領域を保持するグローバル オブジェクト ( sessionStorage) です。ページ セッションは、ブラウザーが開いている限り持続し、ページのリロードや復元後も存続します。新しいタブまたはウィンドウでページを開くと、新しいセッションが開始されます。

その後、次のことができます

  • sessionStorage に存在しない場合は、JSP で一意のトークンを生成し、それを sessionStorage に配置します。

    $(function(){
        // Read the ID. If it's null, this is a new tab: 
        // generate the ID and store it for later.
        var tabId = sessionStorage.getItem("tabId");
        if (tabId == null){
            tabId = Math.random();
            sessionStorage.putItem("tabId",tabId);
        }
    
  • アクションに送り返す

        // Add the ID to the form (as hidden field), 
        // so it will be posted back in next submission.
        $('<input>').attr('type'  , 'hidden')
                    .attr('name'  , 'tabId')
                    .attr('value' , tabId)
        .appendTo('form');
    });
    

    、おそらく BaseAction のセッターに、他のアクションによって拡張され、Interceptorprepare()によって読み取られます。

  • すでに 2 つの要素が含まれていないことを確認するコレクションに入れます。それ以外の場合は、グローバルにマップする必要があるエラー結果を返します。

    public String intercept(ActionInvocation actionInvocation) throws Exception {
        Action action = (Action) actionInvocation.getAction();
        if(action instanceof LimitedTabsAware){ //interface to identify special actions
            ActionContext context = actionInvocation.getInvocationContext();
            Map<String, String[]> request = ((HttpServletRequest) 
                                context.get(StrutsStatics.HTTP_REQUEST)).getParameterMap();
    
            if (request.containsKey("tabId")){              
                String tabId = (String) request.get("tabId")[0];
                List<String> openTabs = context.getSession().get("OPEN_TABS_KEY");
    
                if (openTabs.contains(tabId)){
                    return actionInvocation.invoke();                   
                } else if (openTabs.size()>=2){
                    return "tabLimitExceeded"; // global result
                } else {
                    openTabs.add(tabId);
                    context.getSession().put("OPEN_TABS_KEY", openTabs);
                    return actionInvocation.invoke();
                }
    
            } else {
                throw new IllegalArgumentException("There is no tabId in this request.");
            }
        } else {
            return actionInvocation.invoke();
        }
    }
    

次に、次のいずれかによって、タブが閉じられたとき (1 つのスロットを解放するため) を認識する方法を見つける必要があります。

  • コレクション内の要素の有効期間のタイミングを計る(タブをしばらく使用しないと、セッションが期限切れになるため、コレクション内のトークンも期限切れになります)
  • それ以外の場合は、要素の有効性を更新するアクションにシグナルを送信するJavaScript AJAX タイマーをページに配置します (例: 30 秒ごと) 。keep-aliveタブが閉じられると、シグナルは送信されなくなります。
于 2015-06-09T09:12:33.767 に答える