移动端的select解决方案

lucky-select

https://github.com/gaofeiyu/lucky-select.git

移动端的select解决方案,可级联(现在只有二级联动)。 组件参考自新浪的微招聘,致敬!

基本指令说明

单级指令 singleSelectorPopup 二级联动指令 doubleSelectorPopup 上面两个指令主要是生成下拉部分

参数

//初始化的值
title 标题
initData 初始化的值
data 下拉数据
getRightListData 二级联动通过该属性的方法过滤生成二级菜单,单级联动不存在该属性

这里的data为数组,包含两个必要键值

{id:1,name:"id对应的展示名称"}

方法

  • show(val) val为初始化的对象
  • hide() 隐藏
  • onConfirm() 确认
  • onCancel() 取消

selector单级指令

该指令是在singleSelectorPopup基础上封装的选择的部分,供使用者参考。

        scope: {value: "=", options: "=", name: "@", readonly:"@", index:"="},
        template: "<span class='selector' ng-click='showPopup();'>{{str}}</span>",
        restrict: "EA",

参数说明

  • value 显示在前台的值
  • options 下拉的数据
  • name 下拉标题
  • readonly 是否只读(不弹出下拉,只展示值)
  • index 当前选择值的索引

效果

例图1 例图2

overlay遮罩指令

通用的遮罩指令,也可以用在其他组件上。

指令说明

replace: true,
template: '<div id="overlay"  ng-click="bindClick();"></div>',
restrict:"EA"

方法

  • show(hideCallback) hideCallback会在hide里面回调
  • hide()
  • clear()

android 4.4.2 KitKat 更新对wap页面的一些影响

问题写在前面。

有的时候我们要跟app进行通讯或者跳转,会用到设定好的URL Schemes去做跳转。

有的开发者可能习惯了驼峰式命名,所以把地址协议也设置成firstSecond://这样的形式。

以前应该是没什么问题,新版本的安卓会把协议强制转换为小写,那么如果你的脚本对大小写敏感的话就要注意这个问题了。

 

下面列举一下官方的更新说明:

 

支持蓝牙MAP

Android现在支持消息访问协议(MAP)。因此,支持蓝牙功能的汽车可与您的设备交换消息。

支持Chromecast

借助Android设备和Chromecast,您可以在高清电视上尽情欣赏喜爱的精彩在线娱乐内容(例如来自Netflix、YouTube、Hulu Plus和Google Play的内容)。

Chrome网页视图

嵌入网页内容的应用现可使用Chrome快速、准确地呈现此类内容。

可选字幕

Android现在支持可选字幕和翻译字幕。要启用可选字幕,请转至“设置”>“辅助功能”,然后开启“字幕”。

内置设备管理功能

如果您丢失了设备,可以通过Android设备管理器找到该设备或清空设备数据。

经过重新设计的“下载”应用

“下载”应用经过重新设计,提供了新的排序选项、列表和网格视图,方便您管理下载的文件。

轻松切换主屏幕

如果您喜欢对设备进行个性化设置,并已安装一个或多个可供替换的主屏幕,则可以在“设置”>“主屏幕”中轻松切换。

经过重新设计的“电子邮件”应用

“电子邮件”应用经过全新设计,面貌焕然一新!现在,该应用不但提供文件夹嵌套、联系人照片等功能,还改善了邮件浏览体验。

全屏壁纸,支持预览

壁纸现在可延伸至通知栏和系统按钮区域。更换壁纸时,您可以先预览其效果再进行设置。*

HDR+拍摄模式

Nexus 5提供HDR+拍摄模式,可自动快速连拍多张照片,并将这些照片合成一张,实现绝佳的单张效果。白天拍摄的照片鲜活生动、光影分明;夜间拍摄的照片轮廓清晰、噪点寥寥。*

红外线遥控

在搭载红外(IR)遥控器的设备上,Android现在支持应用对电视和其他附近设备进行远程控制。

“快捷设置”中的位置信息设置

通过“快捷设置”中的新选项,您可以从任何地方快速调整您的位置信息设置。

位置信息模式和监测

如果您想要节省电池电量,请转至“设置”>“位置信息”,然后在“准确度高”和“耗电量低”位置信息模式之间切换。您无需在GPS、WLAN和移动网络设置之间切换。要查看最近有哪些应用申请使用您的位置信息,请转至“设置”>“位置信息”。

音频播放更省电

搭载Android 4.4的Nexus 5极大地延长了您收听音乐的时间,音频播放时间最长可达60小时。*

在锁定屏幕上调整音乐和电影播放进度

您可以在锁定屏幕上跳至歌曲或视频的某个片段。只需长按播放或暂停按钮,然后选择所需时间点即可。

安全的应用沙盒

应用沙盒功能已通过Security-Enhanced Linux得以强化。

内置计步功能

在Nexus 5上使用健身应用(如Moves)时,手机就相当于一个计步器,可用来计算步数。Android 4.4和新硬件可让您以更省电的方式评估自己的运动量。

以全新方式支持碰触付款

Android 4.4采用了全新的开放式NFC支付架构,支持所有移动运营商,允许应用管理您云端或设备上的支付信息。现在,您可以使用Google电子钱包或其他应用,在超过一百万家商店中使用碰触付款功能。

改进触摸屏

结合改进后的软件和Nexus 5的最新硬件,Android现在能以前所未有的速度和准确度,响应您的触摸操作。*

移动端上的点击事件

刚接触手机的时候,前端工程师喜欢用click去处理点击/触摸事件。
渐渐地,通过体验和看过一些文章,我们知道手机上还有touch专用事件,于是我们开始专用touchstart或者touchend来处理触摸事件,然后我们就碰到了各种问题…

Click的延迟问题

click从功能上讲问题不大,但是响应有延迟,传说300毫秒,其实根据机能不同会有更长时间的延迟。

据说一些安卓机用click会出现其他的问题,我没碰到过所以不细说了。

各种touch先天不足

touch响应快,但是你碰到屏幕就是一个touchstart事件,离开屏幕就是一个touchend事件,就算你去拖动屏幕也会执行触发这两个事件,产生的问题我们叫误点击。

解决响应时间和误点击的几个方案

首先我这里不谈jqueryMobile。

那么我知道的几个解决方案为:

fastclick,https://github.com/ftlabs/fastclick;

MBP.fastButton,https://github.com/h5bp/mobile-boilerplate

zepto的tap和singleTap事件,http://zeptojs.com/

上面几个方案都可以很好的解决响应和误点击问题。

那么我们进入正题——“连点”问题

什么是“连点”?
当你点击一个层,而这个层因为事件控制而隐藏了,这时候恰巧这个层下面的区域点击的同一个位置也有点击事件被触发了,那么就是“连点”了。

这个问题发生在弹出层的情况比较多。

上面提到的三个方案在新的手机里面都不太容易(总有特殊情况)出现“连点”问题,但是在老的安卓里面,比如我手上的三星Note中fastclick就会出现连点。

而其他方案表现就很好,所以从这个角度fastclick基本被淘汰了。

还有一种“连点”!

连点还有一种情况,就是你可能在事件里面写了个window.location.href跳转,你这个跳转非常快的完成了,然后又恰巧你跳转的页面在你点击的位置也有个点击事件/链接,那么这个事件/链接也会被触发。
这个是点击问题中最丧心病狂的~
而且关键的是除了click和a标签本身,其他方案都无法避免这个问题。

所以请避免使用点击事件做跳转。

父子Dom的点击事件关系

如果我的一个大dom上有个点击事件,dom中的子dom也有个点击事件,那么点击子dom会执行谁的事件呢?

如果你用click和fastclick就都会执行,其他的方案是执行子dom的事件。

综上所述

如果你在项目中用了zepto,请优先用zepto的相关点击事件,来避免可能发生的问题。
当然了fastclick还有其他的响应功能,如果你需要的话可以在合适的时候去使用它。

编写移动端网站你可能要准备的一些方案

很多pc端的页面仔想去编写wap端的页面,但是又因为对可能出现的问题有恐惧的心理而不敢出手?
pc和wap的网站虽然有很多差异,但是我们完全不用产生距离感,只要掌握一些主要问题的解决方案,大胆动手去做就好了。

这里介绍一套《HTML5移动Web开发实践》对wap的一些处理方案。

先下载这套代码和示例

https://github.com/h5bp/mobile-boilerplate

说明里面有对这个demo的说明

Mobile browser optimizations.
CSS normalizations and common bug fixes.
The latest jQuery.
A custom Modernizr build for feature detection and a polyfill for CSS Media Queries.
Home page icon for Android, iOS, Nokia, Firefox
Cross-browser viewport optimization for Android, iOS, Mobile IE, Nokia, and Blackberry.
Open Web App support for Firefox for Android and Firefox OS
Better font rendering in Mobile IE.
iPhone web app meta.
INSTANT button click event.
Textarea autogrow plugin.
Hide URL bar method.
Prevent form zoom onfocus method.
Mobile site redirection.
User Agent Detection.
An optimized Google Analytics snippet.
Apache server caching, compression, and other configuration defaults for Grade-A performance.
Cross-domain Ajax.
“Delete-key friendly.” Easy to strip out parts you don’t need.
Extensive inline and accompanying documentation.

 

对我们比较有用的有(不是按照上面顺序的哦):

移动浏览器的优化;
协助低版本浏览器兼容HTML5、CSS3的Modernizr(如果你是纯移动端开发者可以不考虑modernizr;
跨浏览器的视图优化;
更好的字体渲染;
点击事件的优化;
跨域ajax等。

当你了解并可以熟练使用上述功能后,wap浏览器的开发就是纸老虎了;)

一段以userAgent判断是否为手机浏览器的js代码

虽然我不关心,但同事说腾讯是这么用的。
其实就是写了个正则字典穷举手机的可能。个人感觉适用性能覆盖90%以上的用户(只要“安全”浏览器不把userAgent改的太奇葩,或者用户不太奇葩)。
if(/AppleWebKit.*Mobile/i.test(navigator.userAgent) || (/MIDP|SymbianOS|NOKIA|SAMSUNG|LG|NEC|TCL|Alcatel|BIRD|DBTEL|Dopod|PHILIPS|HAIER|LENOVO|MOT-|Nokia|SonyEricsson|SIE-|Amoi|ZTE/.test(navigator.userAgent))){
if(window.location.href.indexOf("?mobile")<0){
try{
if(/Android|webOS|iPhone|iPod|BlackBerry/i.test(navigator.userAgent)){
//移动端
}else if(/iPad/i.test(navigator.userAgent)){
//这里对ipad做了处理
}else{
//移动端
}
}catch(e){}
}
}else{
//pc端
}

wp是个特殊的存在(IE),要怎么单独判断wp呢。
var ISWP = !!(navigator.userAgent.match(/Windows\sPhone/i));
因为wp的特殊性海量的方法给你判断,具体情况再具体分析。

手机端按钮包含按钮的触发问题

问题

如果给一个dom添加触摸事件以后,那这个dom里面子元素的触摸事件还可以触发么?这是最近项目中遇到的一个问题。

之后我做了个测试。

 

测试

测试环境:iphone4&ios6,lumia920&wp8,某安卓机

测试的点击方式:默认的click、MBP、Fastclick、Zepto&tap。

测试演示:http://gaofeiyu.com/demo/click/click.html

演示的基本逻辑是黄色块点击后会隐藏自己,黑色的底色块和红色块点击后会改变色块内的html并记录点击次数。

演示里面可以看出click和Fastclick的子元素和父元素都会触发,而MBP和tap事件只有当前dom会触发。

 

总结

在移动项目中还是Zepto和Fastclick混用的方案比较合适,无论点透还是这种逻辑混乱的交互都搞得通。

建议在项目中尽量用一种触摸事件触发方式,不然碰到问题改代码会很难看。我这边最开始用的是tap,之后发现各种问题搞得不得不做很多多余的操作,在优化后还是统一用了Fastclick,父子元素的问题,也只能换个方向去解决,毕竟这个问题本身的用户体验就不是很好。

 

 

我还顺便写了个连点的小样例在演示里面,有心的人可以分析一下。

 

 

关于移动设备“点透”的问题

“点透”是什么

你可能碰到过在列表页面上创建一个弹出层,弹出层有个关闭的按钮,你点了这个按钮关闭弹出层后后,这个按钮正下方的内容也会执行点击事件(或打开链接)。我暂时定义为这是一个“点透”现象。

如何产生的

一般来说我们用原生的touch事件,还有jqueryMobile和zepto的tap可能会产生上面的问题。
相关的内容可以参考http://blog.youyo.name/archives/zepto-tap-click-through-research.html

注:当你点击链接页面刷新太快也会出现点透状况,这个是要在测试中特别注意的。

来说点转载文章中没说到的

规避这个点透现象除了上面参考文章说的方法,有更简单的方法。
推荐方法是引入Fastclick.js插件,该插件重写了默认的click事件,你可以通过
FastClick.attach(document.body);

来对整个文档操作,也可以对某节点单独操作。
那么我之前写的《触屏网页防止误点击(GHOSTCLICK)》中的 MBP 也可以避免这个问题,选择你喜欢的方法去解决。

 

 

触屏网页防止误点击(ghostClick)

如果在触屏的网页中,你为一个dom元素绑定’touchstart’,’touchend’事件来实现点击互动,那么如果你拖动屏幕时触摸到这个dom也会触发这两个事件,因为move的过程中也会执行start和end,这违背了我们的交互需要。
显然,我们要想办法规避这个问题。
如果你用jqueryMobil或者zepto,只要用里面针对触屏的事件,是不会碰到这个问题的。
基本思路就是重写了触发的的方法,根据条件来判断当前事件状态,在’touchend’的时候来决定当前用户是用了点击还是用了移动。
如果不想引入类库要怎么做。

我们增加一个函数MBP(全称为Mobile Boilerplate,该点击事件函数是该项目中的一部分)。
整个函数参考《HTML5移动Web开发实践》四章9节的代码内容

但是书里的内容有些问题,我对里面的内容做了一些修改,我们看下面代码。

函数部分

(function(document){//防止误点击
window.MBP = window.MBP || {};
MBP.fastButton = function (element, handler) {//函数入口
this.element = element;
this.handler = handler;
if (element.addEventListener) {//这里对选用的触发事件做了区分,保证触屏和非触屏用的是不同的事件绑定。
if (document.hasOwnProperty("ontouchstart")) {
element.addEventListener('touchstart', this, false);
}else{
element.addEventListener('click', this, false);
}
}
};
MBP.fastButton.prototype.handleEvent = function(event) {//监听触发事件类型
switch (event.type) {
case 'touchstart': this.onTouchStart(event); break;
case 'touchmove': this.onTouchMove(event); break;
case 'touchend': this.onClick(event); break;
case 'click': this.onClick(event); break;
}
};
MBP.fastButton.prototype.onTouchStart = function(event) {
//onTouchStart方法监听touchmove和touchend事件,Stoppropagation函数用来防止事件在监听中传递,阻止冒泡,即只在当前方法体内寻找当前事件的监听器
event.stopPropagation();
this.element.addEventListener('touchend', this, false);
document.body.addEventListener('touchmove', this, false);
this.startX = event.touches[0].clientX;
this.startY = event.touches[0].clientY;
};
MBP.fastButton.prototype.onTouchMove = function(event) {//如果触摸偏移10像素以上判断为move事件
if(Math.abs(event.touches[0].clientX - this.startX) > 10 ||
Math.abs(event.touches[0].clientY - this.startY) > 10 ) {
this.reset();
}
};
MBP.fastButton.prototype.onClick = function(event) {//如果不是其他可能,执行事件
event.stopPropagation();
this.reset();
this.handler(event);
if(event.type == 'touchend') {
MBP.preventGhostClick(this.startX, this.startY);
}
};
MBP.fastButton.prototype.reset = function() {//核心方法,移除move和touched的事件,以保证做正确的事件
this.element.removeEventListener('touchend', this, false);
document.body.removeEventListener('touchmove', this, false);
};
MBP.preventGhostClick = function (x, y) {
MBP.coords.push(x, y);
window.setTimeout(function (){
MBP.coords.splice(0, 2);
}, 2500);
};
MBP.ghostClickHandler = function (event) {//这部分是对不支持touch事件设备的兼容
for(var i = 0, len = MBP.coords.length; i < len; i += 2) {
var x = MBP.coords[i];
var y = MBP.coords[i + 1];
if(Math.abs(event.clientX - x) < 25 && Math.abs(event.clientY - y) < 25) {
event.stopPropagation();
event.preventDefault();
}
}
};
if (document.addEventListener) {//为文档中其他click事件添加防止误点击操作
document.addEventListener('click', MBP.ghostClickHandler, true);
}
MBP.coords = [];
})(document);

如何使用

var btn = document.getElementById('domId');
btnTouch = new MBP.fastButton(btn,function(){alert('点击成功')});

关于触摸事件的延伸——点透问题

在移动设备中用了触摸点击事件会产生一系列的点透问题,可以转到我文章中的《关于移动设备“点透”的问题》查看解决方法。

其他补充

不要在该方法生成的事件中添加alert事件,不然在ios(我的环境是ios6)中触发后会在下一次触摸屏幕的时候触发touchstart事件,执行未被销毁的alert产生问题。

消除手机上触发链接或包含事件元素后产生的区域框

涉及到一个css3属性-webkit-tap-highlight-color;

这个是控制触摸含点击事件元素后高亮框的样式,如果想消除(其实是看不到,不是真正意义的消除),只要设置框为透明的就好了。

-webkit-tap-highlight-color:rgba(0,0,0,0);

注意这个只有webkit浏览器好用,目前IOS有效,测了几个版本安卓也还好,在没有想到更好的方法前,就先用这个吧。

event.preventDefault和恢复元素默认事件

写页面事件的时候,有的时候需要用event.preventDefault取消原有的事件后进行重写,这个大家应该都知道。

那么怎么在取消默认事件后再恢复呢。

解绑我们自定义的事件就好了。

以Jquery为例

我们用$(“body”).bind(“touchmove”,function(event){event.preventDefault;//code});取消了body的拖动事件。

恢复这个拖动事件只要$(“body”).unbind(“touchmove”);

就OK了~意外地简单:3