触屏网页防止误点击(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产生问题。

批处理压缩css和js for nodejs

同事推荐的压缩css和js的方法,是运行在nodejs的基础上的,所以你要先安装一个nodejs。

在有nodejs的基础上,进入命令行模式分别运行

npm install clean-css -g

npm install uglifyjs -g

clean-css是压缩css的,uglifyjs是压缩js的。
然后新建两个批处理文件。
@echo off
:: 设置压缩css文件的根目录,脚本会自动按树层次查找和压缩所有的css
SET OUTFOLDER= 压缩后的目标目录
echo 正在深度复制文件
xcopy 准备压缩的目录*.* "%OUTFOLDER%" /s /e && echo 复制成功 || echo 复制失败,请检查文件是否存在!
echo 复制完成
:: 设置压缩的路径
chdir /d %OUTFOLDER%
echo 正在查找CSS 文件
for /r . %%b in (*.css) do (
@echo 正在压缩 %%~b ...
cleancss -o %%~fb %%~fb
)
echo CSS压缩完成
echo 完成!

@echo off
:: 设置压缩JS文件的根目录,脚本会自动按树层次查找和压缩所有的JS
SET OUTFOLDER = 压缩后的目标目录
echo 正在深度复制文件
xcopy 准备压缩的目录*.* "%OUTFOLDER%" /s /e && echo 复制成功 || echo 复制失败,请检查文件是否存在!
echo 复制完成
:: 设置压缩的路径
chdir /d %OUTFOLDER%
echo 正在查找JS文件
for /r . %%a in (*.js) do (
@echo 正在压缩 %%~a ...
uglifyjs %%~fa -o %%~fa
)
echo JS压缩完成
echo 完成!

目录的格式应该是 C:\abc\
只要你写的路径是绝对路径批处理文件可以放在任意你喜欢的位置。
如果有需要,你也可以写到一起。

zepto兼容ie10的方法

原先的zepto,通过__proto__赋值,来使dom继承到$.fn方法,

无奈IE11之前的IE10,IE9不支持这种写法,

所以我们只能自己手动把方法添加到dom
// `$.zepto.Z` swaps out the prototype of the given `dom` array
// of nodes with `$.fn` and thus supplying all the Zepto functions
// to the array. Note that `__proto__` is not supported on Internet
// Explorer. This method can be overriden in plugins.
zepto.Z = function(dom, selector) {
dom = dom || []

// 支持ie10,主要是支持wp8
if(navigator.userAgent.indexOf(“MSIE 10″) > -1){
for(var func in $.fn){
dom[func] = $.fn[func];
}
}
else{
dom.__proto__ = $.fn
}

dom.selector = selector || ”
return dom
}

继续阅读“zepto兼容ie10的方法”

关于js中,“与”运算符“&&”和“或”运算符“||”的一些用法

在各类插件里总是能看到这样的赋值。
var a = b || {}
能看出如果b有值就赋值b,如果没有就给一个空对象。
那么下面这段呢
var a = (b==5 && 1) || (b==10 && 2) || (b==12 && 3) || (b==15 && 4) || 0;
就不是那么清晰可见了,下面引用一篇文章,详细说明一下这个问题。

原文地址:http://www.jb51.net/article/21339.htm

首先出个题:

如图:
假设对成长速度显示规定如下:
成长速度为5显示1个箭头;
成长速度为10显示2个箭头;
成长速度为12显示3个箭头;
成长速度为15显示4个箭头;
其他都显示都显示0各箭头。
用代码怎么实现?

差一点的if,else:
Js代码
var add_level = 0;
if(add_step == 5){
add_level = 1;
}
else if(add_step == 10){
add_level = 2;
}
else if(add_step == 12){
add_level = 3;
}
else if(add_step == 15){
add_level = 4;
}
else {
add_level = 0;
}

稍好些的switch:
Js代码
var add_level = 0;
switch(add_step){
case 5 : add_level = 1;
break;
case 10 : add_level = 2;
break;
case 12 : add_level = 3;
break;
case 15 : add_level = 4;
break;
default : add_level = 0;
break;

}如果需求改成:
成长速度为>12显示4个箭头;
成长速度为>10显示3个箭头;
成长速度为>5显示2个箭头;
成长速度为>0显示1个箭头;
成长速度为<=0显示0个箭头。

那么用switch实现起来也很麻烦了。

那么你有没有想过用一行就代码实现呢?
ok,让我们来看看js强大的表现力吧:
Js代码
var add_level = (add_step==5 && 1) || (add_step==10 && 2) || (add_step==12 && 3) || (add_step==15 && 4) || 0;
更强大的,也更优的:

Js代码
var add_level={'5':1,'10':2,'12':3,'15':4}[add_step] || 0;
第二个需求:
Js代码
var add_level = (add_step>12 && 4) || (add_step>10 && 3) || (add_step>5 && 2) || (add_step>0 && 1) || 0;
首先我们来梳理一下一个概念,请你一定要记住:在js逻辑运算中,0、””、null、false、undefined、NaN都会判为false,其他都为true(好像没有遗漏了吧,请各位确认下)。这个一定要记住,不然应用||和&&就会出现问题。
这里顺便提下:经常有人问我,看到很多代码if(!!attr),为什么不直接写if(attr);
其实这是一种更严谨的写法:
请测试 typeof 5和typeof !!5的区别。!!的作用是把一个其他类型的变量转成的bool类型。
下面主要讨论下逻辑运算符&&和||。
几乎所有语言中||和&&都遵循“短路”原理,如&&中第一个表达式为假就不会去处理第二个表达式,而||正好相反。
js也遵循上述原则。但是比较有意思的是它们返回的值。
代码:var attr = true && 4 && “aaa”;
那么运行的结果attr就不是简单的true或这false,而是”aaa”
再来看看||:
代码:var attr = attr || “”;这个运算经常用来判断一个变量是否已定义,如果没有定义就给他一个初始值,这在给函数的参数定义一个默认值的时候比较有用。因为js不像php可以直接在型参数上定义func($attr=5)。再次提醒你记住上面的原则:如果实参需要是0、””、null、false、undefined、NaN的时候也会当false来处理。

if(a >=5){
alert(“你好”);
}
可以写成:
a >= 5 && alert(“你好”);
这样只需一行代码就搞定。但是需要注意的一点就是:js中||和&&的特性帮我们精简了代码的同时,也带来了代码可读性的降低。这就需要我们自己来权衡了。
一方面精简js代码,能实质性的减少网络流量,尤其是大量应用的js公用库。个人比较推荐的做法是:如果是相对复杂的应用,请适当地写一些注释。这个和正在表达式一样,能够精简代码,但是可读性会降低,对读代码的人要求会高些,最好的办法就是写注释。

我们可以不使用这些技巧,但是我们一定要能看懂,因为这些技巧已经广泛应用,尤其是像JQuery等js框里的代码,不理解这些你就很难看懂别人的代码。
像var Yahoo = Yahoo || {};这种是非常广泛应用的。
ok,最后让我们来看一段jQuery中的代码吧:

Js代码
var wrap =
// option or optgroup
!tags.indexOf("<opt") &&
[ 1, "<select multiple='multiple'>", "</select>" ] ||!tags.indexOf("<leg") &&
[ 1, "<fieldset>", "</fieldset>" ] ||

tags.match(/^<(thead|tbody|tfoot|colg|cap)/) &&
[ 1, "<table>", "</table>" ] ||

!tags.indexOf("<tr") &&
[ 2, "<table><tbody>", "</tbody></table>" ] ||

// <thead> matched above
(!tags.indexOf("<td") || !tags.indexOf("<th")) &&
[ 3, "<table><tbody><tr>", "</tr></tbody></table>" ] ||

!tags.indexOf("<col") &&
[ 2, "<table><tbody></tbody><colgroup>", "</colgroup></table>" ] ||

// IE can't serialize <link> and <script> tags normally
!jQuery.support.htmlSerialize &&
[ 1, "div<div>", "</div>" ] ||

[ 0, "", "" ];

// Go to html and back, then peel off extra wrappers
div.innerHTML = wrap[1] + elem + wrap[2];

// Move to the right depth
while ( wrap[0]-- )
div = div.lastChild;


这段代码是作者用来处理 $(html) 时,有些标签必须要约束的,如<option>必须在<select></select>之内的。
可能你也发现了作者还有一个很巧的地方就是 !tags.indexOf(“<opt”) ,作者很巧很简单的就实现了startWith的功能了,没有一点多余的代码。jquery源代码中还有很多如此精妙的代码,大家可以去学习学习。

关于js的字符串编码

escape不编码字符有69个:*,+,-,.,/,@,_,0-9,a-z,A-Z

encodeURI不编码字符有82个:!,#,$,&,’,(,),*,+,,,-,.,/,:,;,=,?,@,_,~,0-9,a-z,A-Z

encodeURIComponent不编码字符有71个:!, ‘,(,),*,-,.,_,~,0-9,a-z,A-Z

 

CSS解决文本溢出加省略号

偶然发现text-overflow:ellipsis这个属性,发现自己学习漏洞很大,先分享吧。

引用自:百度知道

使用text-overflow:ellipsis对溢出文本显示省略号有两个好处,一是不用通过程序限定字数;二是有利于SEO。需要使用对对溢出文本显示省略号的通常是文章标题列表,这样处理对搜索引擎更友好,因为标题实际上并未被截字,而是局限于宽度而未被显示而已。

通常的做法是这样的:
1.overflow:hidden;
2.text-overflow:ellipsis;
3.-o-text-overflow:ellipsis;
4.white-space:nowrap;
5.width:100%;

其中,overflow: hidden和white-space: nowrap都是必须的否则不会显示省略号;-o-text-overflow: ellipsis针对Opera;而宽度的设定主要是针对IE6;

该方法支持Internet Explorer, Safari, Chrome 和 Opera,但FF并不支持,不过可以通过Jquery来实现类似的效果。

下载这个Jquery插件:jQuery ellipsis plugin

调用方法:
1.$(document).ready(function() {
2.    $('.ellipsis').ellipsis();
3.}

 

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

涉及到一个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

CSS3 Media Queries

转载自:W3CPLUS

Media Queries直译过来就是“媒体查询”,在我们平时的Web页面中head部分常看到这样的一段代码:

  <link href="css/reset.css" rel="stylesheet" type="text/css" media="screen" />
  <link href="css/style.css" rel="stylesheet" type="text/css" media="all" />
  <link href="css/print.css" rel="stylesheet" type="text/css" media="print" />

或者这样的形式:

  <style type="text/css" media="screen">
    @import url("css/style.css");
  </style>

不知道大家留意没有,其中两种方式引入CSS样式都有一个共同的属性“media”,而这个“media”就是用来指定特定的媒体类型,在HTML4和CSS2中充许你使用“media”来指定特定的媒体类型,如屏幕(screen)和打印(print)的样式表,当然还有其他的,比如说“TV”,“handheld”等,其中“all”表示的是支持所有媒体介质。有关于更多的Media类型,可以点击这里

上面简单说了一下HTML4和CSS2的“Media Queries”,而今天的主要是来学习CSS3中的”Media
Queries”的更多使用方法和相关知识,下面我们开始进入今天的主题。CSS3中的Media
Queries增加了更多的媒体查询,同时你可以添加不同的媒体类型的表达式用来检查媒体是否符合某些条件,如果媒体符合相应的条件,那么就会调用对应的
样式表。换句简单的说,“在CSS3中我们可以设置不同类型的媒体条件,并根据对应的条件,给相应符合条件的媒体调用相对应的样式表”。现在最常见的一个
例子,你可以同时给PC机的大屏幕和移动设备设置不同的样式表。这功能是非常强大的,他可以让你定制不同的分辨率和设备,并在不改变内容的情况下,让你制
作的web页面在不同的分辨率和设备下都能显示正常,并且不会因此而丢失样式。

首先来看一个简单的实例:

  <link rel="stylesheet" media="screen and (max-width: 600px)" href="small.css" />

上面的media语句表示的是:当页页宽度小于或等于600px,调用small.css样式表来渲染你的Web页面。首先来看media的语句中包含的内容:

1、screen:这个不用说大家都知道,指的是一种媒体类型;

2、and:被称为关键词,与其相似的还有not,only,稍后会介绍;

3、(max-width:600px):这个就是媒体特性,说得通俗一点就是媒体条件。

前面这个简单的实例引出两个概念性的东西,一个就是媒体类型(Media Type)媒体特性(Media Query),首先一起来理解一下这两个概念:

一、媒体类型(Media Type)

媒体类型(Media
Type)在css2中是一个常见的属性,也是一个非常有用的属性,可以通过媒体类型对不同的设备指定不同的样式,在css2中我们常碰到的就是
all(全部),screen(屏幕),print(页面打印或打邱预览模式),其实在媒体类型不止这三种,w3c总共列出了10种媒体类型

页面中引入媒体类型方法也有多种:

1、link方法引入

   <link rel="stylesheet" type="text/css" href="../css/print.css" media="print" />

2、xml方式引入

  <?xml-stylesheet rel="stylesheet" media="screen" href="css/style.css" ?>

3、@import方式引入

@import引入有两种方式,一种是在样式文件中通过@import调用别一个样式文件;另一种方法是
在<head></head>中的<style>…</style>中引入,单这种使用方法在
ie6-7都不被支持 如

样式文件中调用另一个样式文件:

   @import url("css/reset.css") screen;
   @import url("css/print.css") print;

在<head></head>中的<style>…</style>中调用:

  <head>
    <style type="text/css">
@import url("css/style.css") all;
    </style>
  </head>

4、@media引入

这种引入方式和@import是一样的,也有两种方式:

样式文件中使用:

   @media screen{
     选择器{
属性:属性值;
     }
   }

在<head>>/head>中的<style>…</style>中调用:

  <head>
    <style type="text/css">
@media screen{
           选择器{
     属性:属性值;
   }
}
    </style>
  </head>

以上几种方法都有其各自的利弊,在实际应用中我建议使用第一种和第四种,因为这两种方法是在项目制作中是常用的方法,对于他们的具体区别,我就不说了,想了解的大家可以去找度娘或G爸,他们能帮你解决。

二、媒体特性(Media Query)

前面有简单的提到,Media Query是CSS3 对Media Type的增强版,其实可以将Media Query看成Media Type(判断条件)+CSS(符合条件的样式规则),常用的特性w3c共列出来13种。具体的可以参阅:Media features。为了更能理解Media Query,我们在次回到前面的实例上:

  <link rel="stylesheet" media="screen and (max-width: 600px)" href="small.css" />

转换成css中的写法为:

  @media screen and (max-width: 600px) {
    选择器 {
      属性:属性值;
    }
  }

其实就是把small.css文件中的样式放在了@media srceen and (max-width;600px){…}的大括号之中。在语句上面的语句结构中,可以看出Media query和css的属性集合很相似,主要区别在:

1、Media query只接受单个的逻辑表达式作为其值,或者没有值;

2、css属性用于声明如何表现页页的信息;而Media Query是一个用于判断输出设备是否满足某种条件的表达式;

3、Media Query其中的大部分接受min/max前缀,用来表示其逻辑关系,表示应用于大于等于或者小于等于某个值的情况

4、CSS属性要求必须有属性值,Media Query可以没有值,因为其表达式返回的只有真或假两种

常用的Media Query如下表所示:

兼容的浏览器:

下面我们一起来看看Media Queries的具体使用方式

一、最大宽度Max Width

  <link rel="stylesheet" media="screen and (max-width:600px)" href="small.css" type="text/css" />

上面表示的是:当屏幕小于或等于600px时,将采用small.css样式来渲染Web页面。

二、最小宽度Min Width

   <link rel="stylesheet" media="screen and (min-width:900px)" href="big.css" type="text/css"  />

上面表示的是:当屏幕大于或等于900px时,将采用big.css样式来渲染Web页面。

三、多个Media Queries使用

   <link rel="stylesheet" media="screen and (min-width:600px) and (max-width:900px)" href="style.css" type="text/css" />

Media Query可以结合多个媒体查询,换句话说,一个Media
Query可以包含0到多个表达式,表达式又可以包含0到多个关键字,以及一种Media
Type。正如上面的其表示的是当屏幕在600px-900px之间时采用style.css样式来渲染web页面。

四、设备屏幕的输出宽度Device Width

   <link rel="stylesheet" media="screen and (max-device-width: 480px)" href="iphone.css" type="text/css" />

上面的代码指的是iphone.css样式适用于最大设备宽度为480px,比如说iPhone上的显示,这里的max-device-width所指的是设备的实际分辨率,也就是指可视面积分辨率

五、iPhone4

   <link rel="stylesheet" media="only screen and (-webkit-min-device-pixel-ratio: 2)" type="text/css" href="iphone4.css" />

上面的样式是专门针对iPhone4的移动设备写的。

六、iPad

  <link rel="stylesheet" media="all and (orientation:portrait)" href="portrait.css" type="text/css" /> 
  <link rel="stylesheet" media="all and (orientation:landscape)" href="landscape.css"  type="text/css" />

在大数情况下,移动设备iPad上的Safari和在iPhone上的是相同的,只是他们不同之处是iPad声明了不同的方向,比如说上面的例子,
在纵向(portrait)时采用portrait.css来渲染页面;在横向(landscape)时采用landscape.css来渲染页面。

七、android

  /*240px的宽度*/
  <link rel="stylesheet" media="only screen and (max-device-width:240px)" href="android240.css" type="text/css" />
  /*360px的宽度*/
  <link rel="stylesheet" media="only screen and (min-device-width:241px) and (max-device-width:360px)" href="android360.css" type="text/css" />
  /*480px的宽度*/
  <link rel="stylesheet" media="only screen and (min-device-width:361px) and (max-device-width:480px)" href="android480.css" type="text/css" />

我们可以使用media query为android手机在不同分辨率提供特定样式,这样就可以解决屏幕分辨率的不同给android手机的页面重构问题。

八、not关键字

  <link rel="stylesheet" media="not print and (max-width: 1200px)" href="print.css" type="text/css" />

not关键字是用来排除某种制定的媒体类型,换句话来说就是用于排除符合表达式的设备。

九、only关键字

  <link rel="stylesheet" media="only screen and (max-device-width:240px)" href="android240.css" type="text/css" />

only用来定某种特定的媒体类型,可以用来排除不支持媒体查询的浏览器。其实only很多时候是用来对那些不支持Media
Query但却支持Media Type的设备隐藏样式表的。其主要有:支持媒体特性(Media
Queries)的设备,正常调用样式,此时就当only不存在;对于不支持媒体特性(Media Queries)但又支持媒体类型(Media
Type)的设备,这样就会不读了样式,因为其先读only而不是screen;另外不支持Media
Qqueries的浏览器,不论是否支持only,样式都不会被采用。

十、其他

在Media Query中如果没有明确指定Media Type,那么其默认为all,如:

  <link rel="stylesheet" media="(min-width: 701px) and (max-width: 900px)" href="medium.css" type="text/css" />

另外还有使用逗号(,)被用来表示并列或者表示或,如下

  <link rel="stylesheet" type="text/css" href="style.css" media="handheld and (max-width:480px), screen and (min-width:960px)" />

上面代码中style.css样式被用在宽度小于或等于480px的手持设备上,或者被用于屏幕宽度大于或等于960px的设备上。

关于Media Query的使用这一节就介绍到此,最后总体规纳一下其功能,个人认为就是一句话:Media Queries能在不同的条件下使用不同的样式,使用页面达到不同的渲染效果。下一节将会针对Media Queries介绍几个实例,如果感兴趣的朋友记得观注本站的更新。