背景:

本来项目开发系统防挂机功能,在其余游览器中均可以使用。但是呢在苹果的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. HashMap面试必问的数据结构相关知识总结

    1:HashMap 的数据结构? A:哈希表结构(链表散列:数组+链表)实现,结合数组和链表的优点.当链表长度超过 8 时,链表转换为红黑树.transient Node<K,V>[] t ...

  2. 架构设计|基于 raft-listener 实现实时同步的主备集群

    背景以及需求 线上业务对数据库可用性可靠性要求较高,要求需要有双 AZ 的主备容灾机制. 主备集群要求数据和 schema 信息实时同步,数据同步平均时延要求在 1s 之内,p99 要求在 2s 之内 ...

  3. python 多进程jieba分词,高效分词,multiprocessing

    自然语言任务经常使用jieba分词,数据量大时怎么加速,jieba分词不支持使用asyncio异步加速,使用multiprocessing还是可以的 import jieba import jieba ...

  4. 力扣614(MySQL)-二级关注者(中等)

    题目: 在 facebook 中,表 follow 会有 2 个字段: followee, follower ,分别表示被关注者和关注者. 请写一个 sql 查询语句,对每一个关注者,查询关注他的关注 ...

  5. 「开源人说」|AI普惠,阿里灵杰开源历程与思考

    简介: 施兴 阿里巴巴资深技术专家 阿里巴巴开源项目EasyRec负责人 以下为开发者社区「开源人说」第四期--大数据&AI专场的主题分享,点击链接了解更多精彩详情 https://devel ...

  6. 耗时又繁重的SQL诊断优化,以后就都交给数据库自治服务DAS吧!

    在我们业务系统中,数据库越来越扮演着举足轻重的角色. 和其它公司一样,在阿里巴巴业务场景下,大部分业务跟数据库有着非常紧密的关系,数据库一个微小的抖动都有可能对业务造成非常大的影响, 如何让数据库更稳 ...

  7. 技术干货 | jsAPI 方式下的导航栏的动态化修改

    ​简介: 操作指导:通过 jsAPI 实现导航栏的动态修改. ​ 很多开发同学在接入 H5 容器后都会对容器的导航栏进行深度定制,除了 Native 的定制化之外,还有很多场景是使用到 jsAPI 的 ...

  8. LlamaIndex 探索视频系列

    如果您喜欢通过视频学习,现在正是查看我们的"探索 LlamaIndex"系列的好时机.否则,我们建议您继续阅读"理解 LlamaIndex"教程. 自下而上开发 ...

  9. [PHP] 有关PHP浮点数默认显示位数 precision 以及如何调整

    PHP 以浮点数显示的有效位数默认是 14 位.-1 表示将使用一种增强的算法来四舍五入这些数字. 如果想显示更长的浮点位数,可以设置如:ini_set('precision', 40); 有两点需要 ...

  10. dotnet 读 WPF 源代码笔记 为什么加上 BooleanBoxes 类

    在 WPF 框架,为什么需要定义一个 BooleanBoxes 类.为什么在 D3DImage 的 Callback 方法里面,传入的是 object 对象,却能被转换为布尔.本文将告诉大家为什么需要 ...