前言

扯淡

这个月比较倒霉,我送了女朋友一台笔记本电脑作为生日礼物,结果15天一过电脑就坏了,悲剧的我还把电脑盒子给扔了!淘宝不给换更不给退

于是被女朋友臭骂了一过星期后,今天本来在公司有任务的,但是去修了个电脑(换主板啊......),一蹉跎就快五点了,现在反正干劲也不行,就写篇博客吧

需求

上周五的时候,确切说是周四晚上,老板终于又递上了一个神奇的需求

浏览器检测手机是否安装app

尼玛,反正在我看来,这个需求够奇葩的,当时我还一致认为不能完成,但是最后也居然想出了(抄出了)一个办法,于是这里拿出来与各位分享下

在此之前,我们继续聊下上次遇到的tap点透问题

tap“点透”再探索

http://www.cnblogs.com/yexiaochai/p/3377900.html

http://www.cnblogs.com/yexiaochai/p/3391015.html

看过上面两篇博客的的朋友应该知道我们为什么要使用tap事件替换click事件,然后大概知道tap会带来哪些问题,以及我是如何解决这些问题的

虽然完整解决方案因为公司财产问题未拿出来,但是基本思路是有了,其核心就是蒙版遮盖!

话说还头,这个蒙版其实还是不太能让人接受,这不我又请教了我一个同事,我们同事提出了一个属性:

pointer-events属性值详解

  • auto——效果和没有定义pointer-events属性相同,鼠标不会穿透当前层。在SVG中,该值和visiblePainted的效果相同。
  • none——元素不再是鼠标事件的目标,鼠标不再监听当前层而去监听下面的层中的元素。但是如果它的子元素设置了pointer-events为其它值,比如auto,鼠标还是会监听这个子元素的。
  • 其它属性值为SVG专用,这里不再多介绍了。

这个属性,通过前端观察/和张鑫旭的博客再深入了解一番过后发现,这个家伙可以消除一个元素的鼠标事件呢!!!自然也包括touchstart了,于是老夫感兴趣了,便有了今天这个插曲

是否继承

我们首先来看看这个属性是否会被继承:

http://sandbox.runjs.cn/show/teegz43u

 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
<meta name="viewport" content="width=device-width,initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no">
<meta content="telephone=no" name="format-detection" />
<meta name="apple-mobile-web-app-capable" content="yes" />
<style>
div { display: block; border: 1px solid black; margin: 10px; padding: 10px; }
</style>
<script id="others_zepto_10rc1" type="text/javascript" class="library" src="/js/sandbox/other/zepto.min.js"></script> </head>
<body> <div id="p1">
p1
<div id="p1-1">
p1-1
<div id="p1-1-1">
p1-1-1
</div>
<div id="p1-1-2">
p1-1-2
</div>
</div>
</div> <div id="p2">
p2
<div id="p2-1">
2-1
<div id="p2-1-1">
p2-1-1
</div>
<div id="p2-1-2">
p2-1-2
</div>
</div>
</div> </body>
<script type="text/javascript">
$('div').click(function () {
alert($(this).attr('id')) })
</script>
</html>

首先,现在鼠标点击会有一个冒泡的过程,所以会一次弹出提示框,现在我们将下面的p2的style加上我们的pointer-events属性试试点击是否有效果

结果表明,设置了pointer-events: none; 后,该元素以及下面的元素的click事件全部没有了

甚至是我们的input框都不会获取焦点了!!!,所以这个家伙确实够厉害,但是不会取消事件冒泡

有了这个结论,我们上我们的重量级代码吧,这个代码请各位用手机测试

属性解决点透

 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
<meta name="viewport" content="width=device-width,initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no">
<meta content="telephone=no" name="format-detection" />
<meta name="apple-mobile-web-app-capable" content="yes" />
<style>
#list { display: block; position: absolute; top: 100px; left: 10px; width: 200px; height: 100px; }
div { display: block; border: 1px solid black; height: 500px; width: 100%; }
#input { width: 80px; height: 200px; display: block; }
</style>
<script id="others_zepto_10rc1" type="text/javascript" class="library" src="/js/sandbox/other/zepto.min.js"></script>
</head>
<body>
<div id="list" style="background: gray;">
</div>
<div id="wrapper">
<div id="d">
<input type="text" id="input" />
</div>
</div>
</body>
<script type="text/javascript">
var list = $('#list');
var d = $('#d');
var input = $('#input');
input.tap(function (e) {
input.val(new Date().getTime());
});
list.tap(function (e) {
// $('input').css("pointer-events", "none");
list.hide();
setTimeout(function () {
list.show();
// $('input').css("pointer-events", "auto");
}, 1000);
});
d.tap(function () {
d.append($('<p>div tap</p>'));
}); </script>
</html>

http://sandbox.runjs.cn/show/wub3i7fr

这里各位请使用手机访问试试,现在这个网页有几个问题:

我点击灰色区域会将灰色区域隐藏,灰色区域消失,一秒后重现,于是可能发生两个问题:

① 某些浏览器中后面的div tap事件会触发

② input元素必定获得焦点

div事件有些时候我们可以通过阻止冒泡处理,但是input这个问题基本不可调和,因为其获得焦点弹出键盘十分恼火

元素我们是通过一个蒙版解决,先我们来看看是否可以给我们的容器wrapper加上一个css属性解决呢???

 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
<meta name="viewport" content="width=device-width,initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no">
<meta content="telephone=no" name="format-detection" />
<meta name="apple-mobile-web-app-capable" content="yes" />
<style>
#list { display: block; position: absolute; top: 100px; left: 10px; width: 200px; height: 100px; }
div { display: block; border: 1px solid black; height: 500px; width: 100%; }
#input { width: 80px; height: 200px; display: block; }
</style>
<script id="others_zepto_10rc1" type="text/javascript" class="library" src="/js/sandbox/other/zepto.min.js"></script>
</head>
<body>
<div id="list" style="background: gray;">
</div>
<div id="wrapper">
<div id="d">
<input type="text" id="input" />
</div>
</div>
</body>
<script type="text/javascript">
var list = $('#list');
var d = $('#d');
var input = $('#input');
input.tap(function (e) {
input.val(new Date().getTime());
});
list.tap(function (e) {
$('#wrapper').css("pointer-events", "none");
list.hide();
setTimeout(function () {
$('#wrapper').css("pointer-events", "auto");
}, 350)
setTimeout(function () {
list.show();
}, 1000);
});
d.tap(function () {
d.append($('<p>div tap</p>'));
}); </script>
</html>

http://sandbox.runjs.cn/show/1wldtigt

可以看到,我们解决了点透的问题,所以有我有这些厉害的同事是很幸运的,有了这个方案,我们就可以在zepto中封装我们的代码了

在tap点击后为容器标签设置该属性,350ms后取消即可,这样可以最大程度的包装代码不会修改

但是这个方案不是没有问题:

最重要的是他依然有个时间阀值,经过我测试时350ms,意思是我使用tap事件后会有350ms的事件某些区域完全无法点击

那么容器所占区域小的话还可接受,如果所占区域大的话就是噩梦,因为用户的点击明显会出现阻力

然后,毕竟会点透的情况不是多数,所以此方案仍有缺陷,最后还是得动一些其它力气

后续

这次tap的研究先到这里,我们我们有机会再继续,所以回到我们今天的主题吧!!!

浏览器检测手机是否安装app

这个需求初次提出其实让人感觉很为难,至少我是很为难的,因为压根就找不到办法嘛,经过周四晚上的纠结,基本就放弃了

第二天也给老大说搞不定,老大基本也仍为搞不定,但是这个需求是最大的老大提出的,所以跟进力度很强,这不是,过了没多久就来了个vip(代表级别高......)

哥来了就寄出了法宝,先是一个国外的网站,然后就是我们传说中的淘宝了

PS:说实话,虽然电脑的事情与淘宝无关,但是老夫现在对淘宝还是比较怨念的!!!!

淘宝不愧是业内技术领先的技术团队,我们来看看他的网站:

其它不必关注,我们就看这个“立即打开”!!!各位知道手机上这个立即打开干了什么吗?

这个家伙不得了,如果按照了app 的话点击立即打开就会打开app,如果没有按照的话居然跳向了市场连接

在某些时候这个对等与他有一个a标签会根据需求而获得不同的值!!!

但是,我们知道打开app是安装了app才会打开的,不然就是个死链接,死链接必然打不开!于是带着好奇带着敬畏,我们打开了淘宝的js库

PS:淘宝压缩混淆后js确实很小,而且没有使用类库哦

各位看官直接找到这个目录吧,于是进去我们一步步跟进去:

① 点击点

虽然小生本领不行,但是读代码还是入门的,所以国内一旦出了什么心技术,基本很快就能普及,这就是国内的技术,不是做不出来,就是不知道做出了是什么样子

一旦你做出了,那么我也能做出了,并且做的更好,所以我们缺乏创新啊......

我们找到了入口,于是进入install方法

② install

这群代码一目了然,读到这里,其实可以很轻易的猜测实现方案了!

③ 猜测实现方案

于是我就开始猜测,猜测的结果就是:

如果安装app 的情况下,打开链接会让window失去焦点,于是清除了计时器
如果没有安装app计时器里面的代码会执行,所以跳向了app市场

当然,最后发现一个问题:手机上网页无法失去焦点,这只是我自己的判断(无法失去焦点),所以最后也放弃了这个猜测

④ 陷入僵局

于是思路再次陷入僵局,任务不能实现,但是将淘宝代码搞下来,也无法实现,最后就开始以各种漫无目的,垃圾的办法搞,终于不注意成功了一次!!!

无意义的成功是因为将定时器设置的很大......

⑤ 解决方案

最后发现了方案,安装app 的情况下,网页会进入后台打开app!!!

网页进入后台后会挂起js 的执行,但是这个期间有600-1000ms的时间js仍然会执行

淘宝执行的阀值是600,我们大概是900,所以一直在原地踏步了很久

这个网页进入后台却成了解决问题的关键,于是新鲜代码出来了:

 var log = function (msg) {
$('body').before('<div class="log">' + msg + '</div>');
};
var timeout, t = 1000, hasApp = true;
setTimeout(function () {
if (hasApp) {
log('安装了app');
$('#dl_app').hide(); } else {
log('未安装app');
$('#dl_app').show();
log('开始强制下载');
forceDownload();
}
}, 2000)
function testApp() {
var t1 = Date.now();
var ifr = $('<iframe id="ifr"></iframe>')
ifr.attr('src', '您们app的协议');
$('body').append(ifr);
timeout = setTimeout(function () {
try_to_open_app(t1);
}, t);
}
function try_to_open_app(t1) {
var t2 = Date.now();
if (!t1 || t2 - t1 < t + 200) {
hasApp = false;
}
}
testApp();

将这段代码加入网站首页1-2秒后hasApp就会告诉我们是否安装了app,当然问题也很明显:

缺陷

① 经测试,如果未安装app的情况下,safari会给出一个alert类似的提示,老夫将它去不掉!!!

PS:如果各位知道怎么去掉,请赐教

② 进入H5站点,如果安装了app便会打开app,这个是无法避免的

除了上面两个较明显的缺陷,其它还好了......

结语

我们今天的学习暂时到此,也不知道对各位有没有用

又到周末了,我们一起来研究【浏览器如何检测是否安装app】吧的更多相关文章

  1. Emgu-WPF 激光雷达研究-移动物体检测

    原文:Emgu-WPF 激光雷达研究-移动物体检测 接上篇: https://blog.csdn.net/u013224722/article/details/80738619 先pose出效果图,下 ...

  2. 5月第2周业务风控关注 | 央行:严禁未经授权认可的APP接入征信系统

    本文由  网易云发布. 易盾业务风控周报每周呈报值得关注的安全技术和事件,包括但不限于内容安全.移动安全.业务安全和网络安全,帮助企业提高警惕,规避这些似小实大.影响业务健康发展的安全风险. 1.央行 ...

  3. MQTT协议学习研究 & Mosquitto简要教程(安装和使用)

    若初次接触MQTT协议,可先理解以下概念: [MQTT协议特点]——相比于RESTful架构的物联网系统,MQTT协议借助消息推送功能,可以更好地实现远程控制. [MQTT协议角色]——在RESTfu ...

  4. 深入研究浏览器对HTML解析过程

    HTML HTML解析 HTML解析是一个将字节转化为字符,字符解析为标记,标记生成节点,节点构建树的过程. 标记化算法 是词法分析过程,将输入内容解析成多个标记.HTML标记包括起始标记.结束标记. ...

  5. 浅谈Hybrid技术的设计与实现第二弹

    前言 浅谈Hybrid技术的设计与实现 浅谈Hybrid技术的设计与实现第二弹 浅谈Hybrid技术的设计与实现第三弹——落地篇 接上文:浅谈Hybrid技术的设计与实现(阅读本文前,建议阅读这个先) ...

  6. 通过手机浏览器打开APP或者跳转到下载页面.md

    目录 通过手机浏览器打开APP或者跳转到下载页面 添加 schemes 网页设置 参考链接 通过手机浏览器打开APP或者跳转到下载页面 以下仅展示最简单的例子及关键代码 由于硬件条件有限,仅测试了 A ...

  7. Android 如何通过浏览器打开App

    首先给出参考资料http://my.oschina.net/liucundong/blog/354029?p=3#rpl_291191828 通过浏览器直接打开Android应用程序 Android ...

  8. 开始研究unreal4了

    最后一个周末了,昨天去做了许多事,算是对最近的一些整理和了结吧.早上广州下雨了,9点起来吃了早餐之后又睡了1个小时.中午吃了泡面,幸福感max.晚上煎了菜脯蛋和肉卷,拖着拉着把<旋风十一人> ...

  9. 20155228 2016-2017-2 《Java程序设计》第1周学习总结

    20155228 2016-2017-2 <Java程序设计>第1周学习总结 教材学习内容总结 这部分内容是以教材为基础,根据个人的理解来描述的,有的地方的理解和表述可能不规范甚至不正确, ...

随机推荐

  1. java compiler level does not match the version of the installed java project facet 解决方案

    项目出现 java compiler level does not match the version of the installed java project facet 错误,一般是项目移植出现 ...

  2. Laravel 5.3 auth中间件底层实现详解

    1. 注册认证中间件, 在文件 app/Http/Kernel.php 内完成: protected $routeMiddleware = [ 'auth' => \Illuminate\Aut ...

  3. SSISDB5:Parameter

    Parameter 是Package 提供给外界的接口,通过传递不同的Parameter value,能够动态控制 Package 执行不同的Task或container,产生不同的结果. 一,Par ...

  4. Latch1:理解 PageIOLatch和PageLatch

    Latch主要分为三种,Buffer Latch,I/O Latch, non-buf latch. 1,PageLatch 在访问数据库的数据页(Data Page或Index Page)时,如果相 ...

  5. ASP.NET MVC之视图生成URL(二)

    前言 上一节我们讲述了MVC中从控制器到视图传递数据的四种方式,想必大家早已掌握了,那我们继续往下走. 话题 在MVC的Web应用程序中,我们经常会出现这样的操作,从一个视图跳转到另外一个视图,大部分 ...

  6. Objective-C精选字符串处理方法

    无论是什么编程语言对字符串的操作是少不了的,对复杂的字符串的分析和操作我们可以用正则表达式来达到我们的目的.简单的字符串处理我们可以借助OC中NSString封装好的字符串处理方法,不过前提是你得了解 ...

  7. ASP.NET 字符编码的那些事

    ASP.NET 中的字符编码问题,一般会有两个场景: HTML 编码:一般是动态显示 HTML 字符或标签,写法是:HttpUtility.HtmlDecode(htmlString) 或 Html. ...

  8. 相克军_Oracle体系_随堂笔记009-检查点队列

    1.检查点队列 checkpoint queue RBA 日志块地址 redo block address LRBA 第一次被脏的地址 HRBA 最近一次被脏的地址 on disk rba 重做日志( ...

  9. 《Python Web 接口开发与测试》---即将出版

    为什么要出这样一本书? 首先,今年我有不少工作是跟接口自动化相关的,工作中的接口自动化颇有成效. 我一直是一个没有测试大格局的人,在各种移动测试技术爆发的这一年,我却默默耕耘着自己的一亩三分地儿(We ...

  10. MVC中实现加载更多

    需要实现的功能: 数据太多想初次加载部分数据,在底部加上“加载更多”按钮 点击后加载第二页数据(从数据库只取指定页数据)后接在已有数据后面(类似于android中的下拉加载更多) 每次加载时显示“正在 ...