web游览器的标签页仿 ios mac 苹果的墓碑机制 (js代码)
背景:
本来项目开发系统防挂机功能,在其余游览器中均可以使用。但是呢在苹果的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代码)的更多相关文章
- web自动化测试—selenium操作游览器属性
# coding=utf-8'''web游览器属性: 页面最大化 maximize_window() 获取当前页面地址 current_url 代码 page_source title title 后 ...
- web前端之 HTML标签详细介绍
html标签的分类 点我查看完整的html标签介绍 在html中,标签一般分为块级标签和行内标签 块级标签:块元素一般都从新行开始,它可以容纳内联元素和其他块元素,常见块元素是段落标签"p& ...
- 标签页(tab)切换的原生js,jquery和bootstrap实现
概述 这是我在学习课程Tab选项卡切换效果时做的总结和练手. 原课程中只有原生js实现,jquery和bootstrap实现是我自己补上的. 本节内容 标签页(tab)切换的原生js实现 标签页(ta ...
- 【vue】vue中实现标签页
前言 tab标签页实现很多, 纯css实现, js实现等, 外加一些特殊动画. vue中实现标签页实现 keep-alive标签和is特性 vue-router中嵌套路由 is特性实现(推荐) 优点: ...
- 【Winform-自定义控件】自定义Tab Control 带关闭符号(X)的标签页
a form & a tabControl 思路: DrawMode设一定要设为OwnerDrawFixed 事件:Form_Load.tabControl1_DrawItem.tabCont ...
- Web编程基础--HTML、CSS、JavaScript 学习之课程作业“仿360极速浏览器新标签页”
Web编程基础--HTML.CSS.JavaScript 学习之课程作业"仿360极速浏览器新标签页" 背景: 作为一个中专网站建设出身,之前总是做静态的HTML+CSS+DIV没 ...
- 阻止iOS Web APP中点击链接跳转到Safari 浏览器新标签页
问题:ios封装完之后,点击里边的按钮会跳转到网页上 ——小卡遇到这个问题就是这样解决的↓↓↓ 解决方法:建议将代码放到</head>标签前,当然,另外存为一个js 文件引用也是可以的呦~ ...
- IOS UIScrollView + UIButton 实现segemet页面和顶部标签页水平滚动效果
很长一段时间没有写博客了,最近在学习iOS开发,看了不少的代码,自己用UIScrollView和UIButton实现了水平滚动的效果,有点类似于今日头条的主界面框架,效果如下: 代码如下: MyScr ...
- Atitit.web 视频播放器classid clsid 大总结quicktime,vlc 1. Classid的用处。用来指定播放器 1 2. <object> 标签用于包含对象,比如图像、音
Atitit.web 视频播放器classid clsid 大总结quicktime,vlc 1. Classid的用处.用来指定播放器 1 2. <object> 标签用于包含对象,比如 ...
- mac系统升级导致无法在iOS设备中运行Safari Web 调试器
macOS系统升级之后,可能会导致Safari开发选项中没有iOS设备,进而无法运行Safari Web 调试器. 此问题的解决办法: 请转到设置>常规>重置>重置位置和隐私.现在, ...
随机推荐
- 分布式文件存储-FastDFS
1.1 FastDFS简介 1.1.1 FastDFS体系结构 FastDFS是一个开源的轻量级分布式文件系统,它对文件进行管理,功能包括:文件存储.文件同步.文件访问(文件上传.文件下载)等,解决了 ...
- 动手实现自己的http服务器【精简版】
1 package v2; 2 3 import java.io.IOException; 4 import java.io.OutputStream; 5 import java.io.PrintS ...
- CSS 中 MASK 实现图片遮罩登炫酷效果
顾名思义,mask 译为遮罩.在 CSS 中,mask 属性允许使用者通过遮罩或者裁切特定区域的图片的方式来隐藏一个元素的部分或者全部可见区域. 其实 mask 的出现已经有一段时间了,只是没有特别多 ...
- javascript现代编程系列教程之三——数值表示方式
在64位浮点数的表示中,我们使用了一个叫做"偏移二进制"的技术来存储指数.这是因为我们需要在有限的位数(在这种情况下是11位)内表示正数和负数. 让我们更详细地解释一下: 符号位: ...
- Redis介绍、使用、数据结构和集群模式总结
Redis(Remote Dictionary Server)是一个开源的,基于内存的数据结构存储系统,它支持多种数据结构,如字符串(String).列表(List).集合(Set).有序集合(Sor ...
- unity 3d导出安卓包时报错:A failure occurred while executing com.android.build.gradle.internal.tasks.workers$actionfacade see the console for details
unity 3d导出安卓包时报错:A failure occurred while executing com.android.build.gradle.internal.tasks.workers$ ...
- 怀里橘猫柴犬,掌上代码江湖——对话阿里云 MVP郭旭东
简介: 跟郭旭东聊过之后,我对程序员的敬佩又多一分.这个92年的开发者,难能可贵地兼备朝气蓬勃的技术能量与长远深刻的行业洞见.独自承担DevOps平台从0到1的所有工作,我打趣说超级开发者不过如此,他 ...
- 解密 Dubbo 三大中心的部署架构
简介:Dubbo作为一个微服务框架,Dubbo SDK与应用服务绑定在同一个进程内,它跟随着应用服务被部署在分布式集群各个位置,为了在分布式环境下实现各个应用服务间的协作, Dubbo 定义了一些中 ...
- [FAQ] Git 修改最后一次的提交人和提交时间 ?
$ date -R Tue, 21 Mar 2021 21:08:58 +0800 $ git commit --amend --author="xxx <xxx@email.com ...
- vue3 快速入门系列 —— 状态管理 pinia
其他章节请看: vue3 快速入门 系列 pinia vue3 状态管理这里选择 pinia. 虽然 vuex4 已支持 Vue 3 的 Composition API,但是 vue3 官网推荐新的应 ...