我想检测用户是否在同一会话中打开了多个窗口或标签,如果他这样做了 - 我想在屏幕上打印一个特殊信息。
此限制只应在一个特殊URL中使用,因此如果用户打开了两个带有URL的标签/窗口:http://page.com/limite.htm - 我想打印特殊信息。当用户打开两个带有网址的窗口/标签时:http://page.com/limite.htm和http://page.com/index.htm - 一切正常,我也不会显示任何信息。
有可能吗? 感谢。
答案 0 :(得分:3)
我认为最好的方法是使用localStorage。 http://www.gwtproject.org/doc/latest/DevGuideHtml5Storage.html
从链接中了解localStorage:
其他Windows /标签的可用性:在运行相同网络应用的一个浏览器的每个窗口和标签中共享
因此,您可以在选项卡/窗口打开时设置一个条目,并在它关闭时进行更改。当另一个选项卡/窗口打开时,首先检查此条目值。
显然你需要小心:例如,浏览器崩溃可能不会触发"关闭"部分,因此用户无法打开新选项卡,即使没有打开(localStorage仍然存在!)。如果您有服务器会话,则可以要求用户再次登录(或再次运行您的身份验证过程),并重置此值。您还可以尝试使用sessionStorage条目来跟踪此类问题。从链接,关于sessionStorage:
持久性:只有在其原始窗口或标签页中生存。
此外,还有一些名为" Cross window messaging",允许您在标签之间进行通信,但请检查您要支持的浏览器是否支持。
http://ajaxian.com/archives/cross-window-messaging-with-html-5-postmessage
答案 1 :(得分:2)
我今天做的事非常相似。我希望这会有所帮助。
// helper function to set cookies
function setCookie(cname, cvalue, seconds) {
var d = new Date();
d.setTime(d.getTime() + (seconds * 1000));
var expires = "expires="+ d.toUTCString();
document.cookie = cname + "=" + cvalue + ";" + expires + ";path=/";
}
// helper function to get a cookie
function getCookie(cname) {
var name = cname + "=";
var decodedCookie = decodeURIComponent(document.cookie);
var ca = decodedCookie.split(';');
for(var i = 0; i < ca.length; i++) {
var c = ca[i];
while (c.charAt(0) == ' ') {
c = c.substring(1);
}
if (c.indexOf(name) == 0) {
return c.substring(name.length, c.length);
}
}
return "";
}
// Do not allow multiple call center tabs
if (~window.location.hash.indexOf('#admin/callcenter')) {
$(window).on('beforeunload onbeforeunload', function(){
document.cookie = 'ic_window_id=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;';
});
function validateCallCenterTab() {
var win_id_cookie_duration = 10; // in seconds
if (!window.name) {
window.name = Math.random().toString();
}
if (!getCookie('ic_window_id') || window.name === getCookie('ic_window_id')) {
// This means they are using just one tab. Set/clobber the cookie to prolong the tab's validity.
setCookie('ic_window_id', window.name, win_id_cookie_duration);
} else if (getCookie('ic_window_id') !== window.name) {
// this means another browser tab is open, alert them to close the tabs until there is only one remaining
var message = 'You cannot have this website open in multiple tabs. ' +
'Please close them until there is only one remaining. Thanks!';
$('html').html(message);
clearInterval(callCenterInterval);
throw 'Multiple call center tabs error. Program terminating.';
}
}
callCenterInterval = setInterval(validateCallCenterTab, 3000);
}
答案 2 :(得分:1)
LocalStorage不能跨协议工作 - 因此,如果用户使用http在一个选项卡中打开您的站点,使用https打开另一个选项卡,则这两个选项卡都将看到单独的localStorage对象。 Cookie没有相同的问题(它们还有其他问题,例如将每个http请求的大小扩展回您的网站)
下面的示例代码维护一个映射,其中键是唯一的浏览器选项卡标识符,值是一个时间戳,指示该选项卡上次确认它何时仍处于打开状态。地图存储在cookie中。它不是一个完美的方法 - 每个选项卡每3秒更新一次而不是立即更新,并且有竞争条件(多个选项卡更新相同的cookie)但是取决于你之后你可能会做什么。
如果您仅在特定页面上运行此代码,您(或多或少)知道该页面何时在同一浏览器中打开多次。或者在您网站的每个页面上运行它,并知道您的网站何时在多个标签页中打开。
为了简洁起见,省略了Cookie读/写代码(但是取自https://stackoverflow.com/a/24103596/4486628),并且为了简单起见,cookie中的数据编码是使用json完成的,但是你明白了。
如果您运行此代码并使用FireBug的Cookie标签观看Cookie,则可以在打开和关闭标签时看到Cookie更新。实际上,在打开多个标签时做一些提醒用户的事情留给读者练习。
var timePeriod = 3000; // 3 seconds
function tabHandler() {
// ensure the current window has an identifier set
if (!window.name.match(/^MySite[0-9]{3}/)) {
window.name = 'MySite' + Math.round(Math.random() * 1000);
}
// read in the state of all the tabs
var tabCookie = readCookie('tabs') || null;
var tabs = JSON.parse(tabCookie) || {};
// update the timestamp for the current tab
var now = (new Date()).getTime();
tabs[window.name] = now;
// remove tab details that haven't had their timestamp updated
var tooOld = timePeriod * 2;
for (var tabKey in tabs) {
if ((now - tabs[tabKey]) > tooOld) {
delete tabs[tabKey];
}
}
// write back the current state of tabs
createCookie('tabs', JSON.stringify(tabs), 1);
setTimeout(tabHandler, timePeriod);
}
setTimeout(tabHandler, timePeriod);