背景:

本来项目开发系统防挂机功能,在其余游览器中均可以使用。但是呢在苹果的safair游览器中会出现几率失效,最后经过排查发现是苹果的墓碑机制导致。即:此标签页活跃,其他标签页假死。然后就导致防挂机失效了。

原理:

假如当前游览器中有3个标签页分别是A,B,C,每个标签页都有倒计时。正常情况下,每个标签页都会倒计时。但是苹果游览器只会有一个标签页A正常倒计时,其余的B,C 倒计时不生效。

所以就需要仿墓碑机制进行开发。原理如下:

A标签页打开时,B和C标签页不活跃;

当打开其他标签页,ABC处于后台时候,最近操作的一个标签页处于活跃;

核心逻辑代码:

    //分钟数
var min;
var timeLeft;
var timer=null;
var IsnewRequest = false;
var StayTimer = null;
function resetTimer() {
backInit();
} function uuid(len, radix) {
var chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'.split('');
var uuid = [], i;
radix = radix || chars.length; if (len) {
// Compact form
for (i = 0; i < len; i++) uuid[i] = chars[0 | Math.random()*radix];
} else {
// rfc4122, version 4 form
var r; // rfc4122 requires these characters
uuid[8] = uuid[13] = uuid[18] = uuid[23] = '-';
uuid[14] = '4'; // Fill in random data. At i==19 set the high bits of clock sequence as
// per rfc4122, sec. 4.1.5
for (i = 0; i < 36; i++) {
if (!uuid[i]) {
r = 0 | Math.random()*16;
uuid[i] = chars[(i == 19) ? (r & 0x3) | 0x8 : r];
}
}
} return uuid.join('');
} function GetBigTime() { //判断:如果有其他页面打开,则赋值最大倒计时值,如果< 10 退出
//1,获取所有的time
//2,取最大的时间
//3,如果最大的时间<10 则不管;
var countDownKeyList= [];
var localStorageKeys = Object.keys(localStorage)
for (var i=0;i<localStorageKeys.length;i++) {
var item = localStorageKeys[i];
if(item.indexOf("CountDown")!=-1)
{
countDownKeyList.push(item);
}
} var countDownValueList= [];
for(var i= 0; i<countDownKeyList.length;i++)
{
var value = localStorage.getItem(countDownKeyList[i]);
countDownValueList.push(value);
} //验证最大时间
var bigTime = countDownValueList.sort().reverse()[0];
//if(Number(bigTime)>=3)
if(Number(bigTime)>=3 && Number(bigTime) != 19999999)
{
//取运行中的倒计时最大值;
window.localStorage.setItem(window.CountDown,bigTime);
return false;
}
else
{
window.localStorage.removeItem(window.CountDown);
return true;
} } function ShowCountDown (second){
const s = second % 60;
const m = Math.floor(second / 60);
return `${`00${m}`.slice(-2)} : ${`00${s}`.slice(-2)}`;
}; function reSetTimeoutInit()
{
window.localStorage.setItem("checkClose","1");
setTimeout(function(){
//1秒后执行刷新
window.localStorage.removeItem('checkClose');
}, 1000); //单位是毫秒
setTimeoutInit();
} var IsResetTime = false;
function setTimeoutInit() { this.IsnewRequest = true;
//默认无操作时间为15分钟
min = 15;
let value = window.localStorage.getItem("InvalidTime");
//如果取不到session值 则默认15分钟
if(value!=null && value!=undefined)
{
min = Number(value);
} //清理之前的倒计时
clearInterval(StayTimer); //没有唯一标识,则生成
if(window.CountDown==''||window.CountDown==undefined)
{
window.CountDown = "CountDown"+this.uuid(8,2);
} //设置初始倒计时
var MainTime = min * 60;
window.localStorage.setItem(window.CountDown,MainTime); StayTimer = setInterval(()=>{ var nowTime = window.localStorage.getItem(window.CountDown);
if(nowTime==null||nowTime=="")
{
clearInterval(StayTimer);
return;
}
//获取存储倒计时
timeLeft = Number(nowTime); var localStorageKeys = Object.keys(localStorage)
var labelList = localStorageKeys.filter(x=> x.indexOf("CountDown")!=-1 );
var activeCount = 0;
for(var i= 0; i<labelList.length;i++)
{
var value = localStorage.getItem(labelList[i]);
var nValue = Number.parseInt(value);
if(nValue!=19999999)
{
activeCount++;
}
} var localStorageKeys = Object.keys(localStorage)
var labelList = localStorageKeys.filter(x=> x.indexOf("CountDown")!=-1 );
var activeCount = 0;
for(var i= 0; i<labelList.length;i++)
{
var value = localStorage.getItem(labelList[i]);
var nValue = Number.parseInt(value);
if(nValue!=19999999)
{
activeCount++;
}
}
//如果没有一个活跃,则重新读取
if(activeCount==0)
{
this.IsnewRequest = true;
} if(this.IsnewRequest==true)
{
this.IsnewRequest = false;
for(var i= 0; i<labelList.length;i++)
{
if(labelList[i]!=window.CountDown)
{
var value = localStorage.getItem(labelList[i])
localStorage.setItem(labelList[i],"19999999");
}
else
{
timeLeft = MainTime;//设置的默认值
localStorage.setItem(labelList[i],MainTime);
}
}
} if (document.hidden) {
//首先重置时间
//赋值其余的为-999
if(timeLeft==19999999)
{
IsResetTime = true
const show = ShowCountDown(timeLeft);//恢复倒计时 并且重置时间;
console.log("[时停],倒计时:"+timeLeft);
}
else
{
if(IsResetTime)
{
timeLeft = MainTime;//设置的默认值
IsResetTime = false;
}
const show = ShowCountDown(timeLeft--);//恢复倒计时 并且重置时间;
console.log("[独苗],倒计时:"+timeLeft);
}
} else {
//首先重置时间
//赋值其余的为-999
if(timeLeft==19999999)
{
IsResetTime = true
const show = ShowCountDown(timeLeft);//恢复倒计时 并且重置时间;
console.log("[时停],倒计时:"+timeLeft);
}
else
{
if(IsResetTime)
{
timeLeft = MainTime;//设置的默认值
IsResetTime = false;
}
const show = ShowCountDown(timeLeft--);//恢复倒计时 并且重置时间;
console.log("[独苗],倒计时:"+timeLeft);
}
} var checkShow = window.localStorage.getItem('checkShow');
var blCheckShow =Number(checkShow);
if(blCheckShow==1)
{
timeLeft = -1;
setTimeout(function(){
//1秒后执行刷新
window.localStorage.removeItem('checkShow');
}, 1000); //单位是毫秒
} //const show = ShowCountDown(timeLeft--);
//设置倒计时
window.localStorage.setItem(window.CountDown,timeLeft);
if (timeLeft < 0)
{
//#endregion
window.localStorage.setItem('checkShow',"1");
var IsResetTime = false;
var blresult = this.GetBigTime();
if(blresult==true)
{
//清理定时
clearInterval(StayTimer);
//业务操作:
document.getElementsByClassName("fullScreenDiv")[0].style.display = "block";
document.getElementsByClassName("promptDiv")[0].style.display = "block";
startCountDown($("#spanCountDown").text()); } } },1000); //countTime(); var vdoc = document.getElementById("ScormIframe").contentDocument; if (vdoc != null) {
vdoc.addEventListener("mousemove", resetTimer, false);
vdoc.addEventListener("mousedown", resetTimer, false);
vdoc.addEventListener("keypress", resetTimer, false);
vdoc.addEventListener("DOMMouseScroll", resetTimer, false);
vdoc.addEventListener("mousewheel", resetTimer, false);
vdoc.addEventListener("touchmove", resetTimer, false);
vdoc.addEventListener("MSPointerMove", resetTimer, false);
}
else{
} if (language == "zh-CN") {
$("#msgInfo").html("由于长时间未操作,课件将在倒计时结束后自动关闭,系统会保存您的学习记录。");
$("#msgTimeout").html("如果您想继续学习,请关闭此窗口。");
}
else {
$("#msgInfo").html("Since there is no operation for a period of time, the courseware will be closed automatically at the end of the countdown and the learning record will be saved.");
$("#msgTimeout").html("If you want to continue learning, just close this window.");
}
} function countTime() {
if (timeLeft == 0) {
document.getElementsByClassName("fullScreenDiv")[0].style.display = "block";
document.getElementsByClassName("promptDiv")[0].style.display = "block";
startCountDown($("#spanCountDown").text());
} var startMinutes = parseInt(timeLeft / (60 * 1000), 10);
var startSec = parseInt((timeLeft - startMinutes * 60 * 1000) / 1000)
timeLeft = timeLeft - 1000;
setTimeout('countTime()', 1000);
//console.log(timeLeft);
} function startCountDown(html){
clearInterval(this.CountDownTimer);
this.CountDownTimer = setInterval(() => { var checkClose = window.localStorage.getItem('checkClose');
var blCheckClose =Number(checkClose);
if(blCheckClose==1)
{
// $("#spanCountDown").text(60);
// clearInterval(this.CountDownTimer);
document.getElementsByClassName("fullScreenDiv")[0].style.display = "none";
document.getElementsByClassName("promptDiv")[0].style.display = "none";
setTimeoutInit();
setTimeout(function(){
//1秒后执行刷新
window.localStorage.removeItem('checkClose');
}, 1000); //单位是毫秒
}
else
{
html = parseInt(html) - 1;
if (parseInt(html) <= 0) {
closeme();
}
$("#spanCountDown").text(html);
}
////console.log($("#spanCountDown").text());
}, 1000);
}
function closeme() {
var browserName = navigator.appName;
if (browserName == "Netscape") {
window.open('', '_parent', '');
window.close();
} else if (browserName == "Microsoft Internet Explorer") {
window.opener = "whocares";
window.close();
}
} function backInit() { reSetTimeoutInit(); // min = 15;
// timeLeft = min * 60 * 1000;
$("#spanCountDown").text(60);
clearInterval(this.CountDownTimer);
document.getElementsByClassName("fullScreenDiv")[0].style.display = "none";
document.getElementsByClassName("promptDiv")[0].style.display = "none";
}

结语:

其实就是按照墓碑机制进行仿照开发,此文章进行记录以后可以在其他平台进行此机制的开发;

web游览器的标签页仿 ios mac 苹果的墓碑机制 (js代码)的更多相关文章

  1. web自动化测试—selenium操作游览器属性

    # coding=utf-8'''web游览器属性: 页面最大化 maximize_window() 获取当前页面地址 current_url 代码 page_source title title 后 ...

  2. web前端之 HTML标签详细介绍

    html标签的分类 点我查看完整的html标签介绍 在html中,标签一般分为块级标签和行内标签 块级标签:块元素一般都从新行开始,它可以容纳内联元素和其他块元素,常见块元素是段落标签"p& ...

  3. 标签页(tab)切换的原生js,jquery和bootstrap实现

    概述 这是我在学习课程Tab选项卡切换效果时做的总结和练手. 原课程中只有原生js实现,jquery和bootstrap实现是我自己补上的. 本节内容 标签页(tab)切换的原生js实现 标签页(ta ...

  4. 【vue】vue中实现标签页

    前言 tab标签页实现很多, 纯css实现, js实现等, 外加一些特殊动画. vue中实现标签页实现 keep-alive标签和is特性 vue-router中嵌套路由 is特性实现(推荐) 优点: ...

  5. 【Winform-自定义控件】自定义Tab Control 带关闭符号(X)的标签页

    a form & a tabControl 思路: DrawMode设一定要设为OwnerDrawFixed 事件:Form_Load.tabControl1_DrawItem.tabCont ...

  6. Web编程基础--HTML、CSS、JavaScript 学习之课程作业“仿360极速浏览器新标签页”

    Web编程基础--HTML.CSS.JavaScript 学习之课程作业"仿360极速浏览器新标签页" 背景: 作为一个中专网站建设出身,之前总是做静态的HTML+CSS+DIV没 ...

  7. 阻止iOS Web APP中点击链接跳转到Safari 浏览器新标签页

    问题:ios封装完之后,点击里边的按钮会跳转到网页上 ——小卡遇到这个问题就是这样解决的↓↓↓ 解决方法:建议将代码放到</head>标签前,当然,另外存为一个js 文件引用也是可以的呦~ ...

  8. IOS UIScrollView + UIButton 实现segemet页面和顶部标签页水平滚动效果

    很长一段时间没有写博客了,最近在学习iOS开发,看了不少的代码,自己用UIScrollView和UIButton实现了水平滚动的效果,有点类似于今日头条的主界面框架,效果如下: 代码如下: MyScr ...

  9. Atitit.web 视频播放器classid clsid 大总结quicktime,vlc 1. Classid的用处。用来指定播放器 1 2. <object> 标签用于包含对象,比如图像、音

    Atitit.web 视频播放器classid clsid 大总结quicktime,vlc 1. Classid的用处.用来指定播放器 1 2. <object> 标签用于包含对象,比如 ...

  10. mac系统升级导致无法在iOS设备中运行Safari Web 调试器

    macOS系统升级之后,可能会导致Safari开发选项中没有iOS设备,进而无法运行Safari Web 调试器. 此问题的解决办法: 请转到设置>常规>重置>重置位置和隐私.现在, ...

随机推荐

  1. 设备像素、css像素、设备独立像素、dpr、ppi 之间的区别

    一.背景 在css中我们通常使用px作为单位,在PC浏览器中css的1个像素都是对应着电脑屏幕的1个物理像素 这会造成一种错觉,我们会认为css中的像素就是设备的物理像素 但实际情况却并非如此,css ...

  2. 力扣385(java)-迷你语法分析器(中等)

    题目: 给定一个字符串 s 表示一个整数嵌套列表,实现一个解析它的语法分析器并返回解析的结果 NestedInteger . 列表中的每个元素只可能是整数或整数嵌套列表 示例 1: 输入:s = &q ...

  3. Pandas+ SLS SQL:融合灵活性和高性能的数据透视

    简介: Pandas是一个十分强大的python数据分析工具,也是各种数据建模的标准工具.Pandas擅长处理数字型数据和时间序列数据.Pandas的第一大优势在于,封装了一些复杂的代码实现过程,只需 ...

  4. 利器解读!Linux 内核调测中最最让开发者头疼的 bug 有解了|龙蜥技术

    ​简介:通过在Anolis 5.10 内核中增强 kfence 的功能,实现了一个线上的.精准的.可定制的内存调试解决方案. 编者按:一直持续存在内核内存调测领域两大行业难题: "内存被改& ...

  5. 推文科技:AI解决方案助力内容出海

    ​ 2017年,推文科技成立,推出业内针对网络文学的AI系统,助推网文批量出海.2018年,阿里云上线海外可用区,推文科技开始与阿里云合作. 创业宣言 创业是一件用行动去实践相信的事情,也许有一天,我 ...

  6. 云原生数据仓库TPC-H第一背后的Laser引擎大揭秘

    简介: 作者| 魏闯先阿里云数据库资深技术专家 一.ADB PG 和Laser 计算引擎的介绍 (一)ADB PG 架构 ADB PG 是一款云原生数据仓库,在保证事务ACID 能力的前提下,主要解决 ...

  7. 如何利用 AHAS 保障 Web 服务稳如磐石?

    ​简介:应用高可用服务 AHAS (Application High Availability Service) 是经阿里巴巴内部多年高可用体系沉淀下来的云产品,基于阿里开源流控降级组件 Sentin ...

  8. Apsara Stack 2.0技术百科(9宫格)

    ​ ​ ​​​​​​​​ 原文链接 本文为阿里云原创内容,未经允许不得转载. ​

  9. WPF 字体 FontStyle 的 Italic 和 Oblique 的区别

    本文介绍在 WPF 里面的字体属性 FontStyle 的 Italic 和 Oblique 的斜体差别 本文的图片和知识来自: #265 – Specifying Values for FontSt ...

  10. 表和数据连接,而不是和表连接(JOIN)

    1.连接数据,但是顺序会受影响 在使用JOIN连接临时表或子查询时,无法保证结果的顺序与特定值的顺序完全一致.这是因为在查询过程中,数据库优化器可能会选择不同的执行计划,导致结果的顺序发生变化. SE ...