博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Javascript/JQuery五步入门——正则&DOM&事件
阅读量:6424 次
发布时间:2019-06-23

本文共 19695 字,大约阅读时间需要 65 分钟。

1.正则表达式检测是否为URL——总结正则表达式相关知识

正则表达式测试工具 http://tool.chinaz.com/regex/ 通过这个可以检测我们的正则表达式是否匹配了希望的内容。

下面用十点简要总结正则表达式的一些基本用法。

一,创建一个正则表达式

var reg = /pattern/; 或 var reg = new  RegExp('pattern');

二,正则表达式方法

reg.exec(str); 或 str.match(reg); 都是返回数组,exec只返回第一个匹配即只有一个元素的正则信息数组while(match=reg.exec(str))console.log(match[1])遍历输出匹配到的字符串,而match是在指定全局g时返回每一个匹配。
reg.test(str); 返回布尔值以表示是否成功
str.replace(reg,'c'); 将str字符串中匹配reg的部分用’’代替,结果作为返回值被返回
str.search(reg); 返回正则表达式第一次匹配的位置
str.split(reg); 返回分割后的数组

三,限制匹配个数的语法规则 

1. c{n} {
1}表示一个的意思。/c{1}/只能匹配一个c。 /c{n}/则会匹配n个连续的c。reg = /c{1}/;str='cainiao';execReg(reg,str);返回结果creg = /c{2}/;str='cainiao';execReg(reg,str);返回结果null,表示没有匹配成功。2. c{m,n}c{
3,4}的意思是,连续的3个c或者4个c。reg = /c{3,4}/;str='ccccTest';execReg(reg,str);结果返回cccc,这表明正则会尽量多品牌,可3可4的时候它会选择多匹配一个。3. c{n,}c{
1,}表示1个以上的c。例如:reg = /c{1,}/;str='cccccTest';execReg(reg,str);返回ccccc,再次说明了正则表达式会尽量多地匹配。reg = /c{2,}/;str='cainiao';execReg(reg,str);结果返回null,c{
2,}表示2个以上的c,而cainiao中只有1个c。4. * + ? 与转意\* \+ \?* 表示0次或者多次,可有可无,等同于{0,},即c* 和 c{0,} 是一个意思。+ 表示一次或者多次,必须出现,等同于{1,},即c+ 和 c{1,} 是一个意思。? 表示0次或者1次,可无可有一次,等同于{0,1},即c? 和 c{0,1} 是一个意思。如果我们真的想匹配’c*’这个字符串的时候,就要将*转义reg = /c\*/;str='c*';execReg(reg,str);返回匹配的字符串:c*。同理,要匹配其他元字符,只要在前面加上一个“\”就可以了。5. 贪心模式与非贪心模式只要在合法的情况下,正则会尽量多去匹配字符,叫做贪心模式。如果我们希望正则尽量少地匹配字符,那么就可以在表示数字的符号后面加上一个?变成非贪心模式。{n,}?, *?, +?, ??, {m,n}?reg = /c{1,}?/;str='ccccc';execReg(reg,str);返回的结果只有1个c,尽管有5个c可以匹配,但是由于正则表达式是非贪心模式,所以只会匹配一个。

四,边界\b 非边界\B /^开头  $/结尾匹配

\b表示的边界的意思,也就是说,只有字符串的开头和结尾才算数。例如/\bc/就表示字符串开始的c或者是结尾的c。看下面的例子:reg = /\bc/;str='cainiao';execReg(reg,str);返回结果c。匹配到了左边界的c字符。reg = /\bc/;str='维生素c';execReg(reg,str);仍然返回c,不过这次返回的是右侧边界的c。reg = /\bc/;str='bcb';execReg(reg,str);这次匹配失败,因为bcb字符串中的c被夹在中间,既不在左边界也不再右边界。与\b对应\B表示非边界。例如:reg = /\Bc/;str='bcb';execReg(reg,str);这次会成功地匹配到bcb中的c,而reg = /\Bc/;str='cainiao';execReg(reg,str);则会返回null。因为\B告诉正则,只匹配非边界的c。
^表示只匹配字符串的开头。看下面的例子: reg = /^c/; str='维生素c'; execReg(reg,str); 结果为null,因为字符串‘维生素c’的开头并不是c,所以匹配失败。 reg = /^c/; str='cainiao'; execReg(reg,str); 这次则返回c,匹配成功,因为cainiao恰恰是以c开头的。 与^相反,$则只匹配字符串结尾的字符: reg = /c$/; str='维生素c'; execReg(reg,str); 这次返回的结果是c,表明匹配成功。

五,代表任意非\n的点’.’ 

reg = /./;str='cao';execReg(reg,str);结果显示,正则匹配到了字符c。reg = /.+/;str='blue——经典  好_。';execReg(reg,str);结果是所有的字符都被匹配掉了,包括一个空格,一个下滑线,和一个破折号。reg = /^./;str='\ncaao';execReg(reg,str);结果是null,终于失败了,正则要求字符串的第一个字符不是换行,但是恰恰字符是以\n开始的。

六,正则表达式中的或,“|“

b|c表示,匹配b或者c。reg = /b|c/;str='blue';execReg(reg,str);结果是b。reg = /^b|c.+/;str='caao';execReg(reg,str);匹配开头的b或者是c.+,c开头则匹配掉整个caao。

七,子正则表达式的括号与其多义

reg = /^(b|c).+/;str='bbs.blueidea.com';execReg(reg,str);这次的结果是整个串bbs.blueidea.com,加上上面的括号这后,正则表示,如果字符串的开头是b或者c,那么匹配开头的b或者c以及其后的所有的非换行字符。

 

 

捕获

 

 

(exp)

匹配exp,并捕获文本到自动命名的组里

(?<name>exp)

匹配exp,并捕获文本到名称为name的组里,也可以写成(?’name’exp)

(?:exp)

匹配exp,不捕获匹配文本,也不给分组分配组号

 

 

 断言

 

 

 

(?=exp)

匹配exp前面位置,但是不匹配exp

(?<exp)

匹配exp后面位置,但是不匹配exp

(?!exp)

匹配后面的不是exp的位置,但是不匹配exp

(?<!exp)

匹配前面不是exp的位置,但是不匹配exp

小括号的多义,分组捕获。

var reg1 = /(\d{3}) (\d{3})/var str = '111 222'str.replace(reg1, '$2 $1') // => '222 111' , 注意这里的$2,$1,存放了匹配的字符串 var reg2 = /(\d{3})(\d{4})(\d{4})/var mobile = '13522722724'reg2.test(mobile)RegExp.$1 // => 135RegExp.$2 // => 2272RegExp.$3 // => 2724 var reg3 = /(\d{3})(\d{4})(\d{4})/var mobile = '13522722724'mobile.replace(reg3, '$1 $2 $3') // => '135 2272 2724'

较长的正则表达式中,反向引用会降低匹配速度,性能降低,不需要反向引用时应使用分组不捕获,括号前加?:。 

另外正则有一个限制相邻信息而不实际匹配的语法,括号前加?=。最适合的例子就是将12个数字分拆成3组4个数字,.replace(/(\d{4})(?=\d)/g,"$1 ")。 

在/g全局匹配基础上,逐4个替换成$1+空格,当第三组不满足后面为数字的相邻限制,不做替换,最后没有冗余空格。

var reg = /(John) (?=Resig)/reg.test('John') // => falsereg.test('John Backus') // => falsereg.test('John Reisg') // => trueRegExp.$1 // => 'John',注意这里不是 "John Resig"

参考: http://www.cnblogs.com/dwlsxj/p/Regex.html 

 

另外,正则表达式\+数字n表示匹配的第n个group

捕获组可以通过从左到右计算其开括号来编号。例如,在表达式 ((A)(B(C))) 中,存在四个这样的组: 

1     ((A)(B(C))) 
2     \A 
3     (B(C)) 
4     (C) 
组零始终代表整个表达式。 
之所以这样命名捕获组是因为在匹配中,保存了与这些组匹配的输入序列的每个子序列。捕获的子序列稍后可以通过 Back 引用在表达式中使用,也可以在匹配操作完成后从匹配器检索。 
/^(11+?)\1+$/ 解释:以11开头的非贪婪模式匹配至少2个连续的1,作为组1被匹配1次或多次(被用来检测1的个数是否为素数)。

(\w)((?=\1\1\1)(\1))+ 解释:重复4次或以上的字母匹配除最后两位之前的部分

Java中Matcher.group(n) 和 s.substring(m.start(n), m.end(n)) 是等效的

 

八,一个字符[abc] 反[^abc]

[abc]表示a或者b或者c中的任意一个字符,[^abc]就表示不能是a,b或者c中的任何一个。^在正则表达式开始部分的时候表示开头的意思,例如/^c/表示开头是c;但是在字符集和中,它表示的是类似“非“的意思。reg = /^[abc]/;str='bbs';execReg(reg,str);返回结果是b。reg = /[^abc]/;str='blue';execReg(reg,str);返回的结果是l,因为它是第一个非abc的字符(即第一个b没有匹配)。在字字符集合中可以使用如下的表示方式:[a-z],[A-Z],[0-9],分别表示小写字母,大写字母,数字。例如:reg =  /^[a-zA-Z][a-zA-Z0-9_]+/;str='test';execReg(reg,str);结果是整个test,正则的意思是开头必须是英文字母,后面可以是英文字母或者数字以及下划线。

九,数字\d 非数字\D 英文字符\w

\d表示数字的意思,相反,\D表示非数字。例如:reg = /\d/;str='cao8';execReg(reg,str);返回的匹配结果为8,因为它是第一个数字字符。reg = /\D/;str='cao8';execReg(reg,str);返回c,第一个非数字字符。\w表示英文字符,等同于字符集合[a-zA-Z0-9_]。例如:reg = /\w+/;str='blue';execReg(reg,str);返回完整的blue字符串,因为所有字符都是单词字符。reg = /\w+/;str='.className';execReg(reg,str);结果显示匹配了字符串中的className。\W表示非单词字符,等效于[^a-zA-Z0-9_]reg = /\W+/;str='中文如何?';execReg(reg,str);返回完整的字符串,因为,无论是中文和“?”都算作是非单词字符。

十,几种空白字符匹配

\f匹配换页符,\n匹配换行符,\r匹配回车,\t匹配制表符,\v匹配垂直制表符。\s匹配单个空格,等同于[\f\n\r\t\v]。例如:reg = /\s.+/;str='This is a test  String.';execReg(reg,str);返回“is a test String.”,正则的意思是匹配第一个空格以及其后的所有非换行字符。同样,\S表示非空格字符。reg = /\S+/;str='This is a test  String.';execReg(reg,str);匹配结果为This,当遇到第一个空格之后,正则就停止匹配了。

 

实例

用正则表达式写Encode与Decode

/*1.用浏览器内部转换器实现html转码*/    htmlEncode:function (html){        //1.首先动态创建一个容器标签元素,如DIV        var temp = document.createElement ("div");        //2.然后将要转换的字符串设置为这个元素的innerText(ie支持)或者textContent(火狐,google支持)        (temp.textContent != undefined ) ? (temp.textContent = html) : (temp.innerText = html);        //3.最后返回这个元素的innerHTML,即得到经过HTML编码转换的字符串了        var output = temp.innerHTML;        temp = null;        return output;    },    /*2.用浏览器内部转换器实现html解码*/    htmlDecode:function (text){        //1.首先动态创建一个容器标签元素,如DIV        var temp = document.createElement("div");        //2.然后将要转换的字符串设置为这个元素的innerHTML(ie,火狐,google都支持)        temp.innerHTML = text;        //3.最后返回这个元素的innerText(ie支持)或者textContent(火狐,google支持),即得到经过HTML解码的字符串了。        var output = temp.innerText || temp.textContent;        temp = null;        return output;    },    /*3.用正则表达式实现html转码*/    htmlEncodeByRegExp:function (str){           var s = "";         if(str.length == 0) return "";         s = str.replace(/&/g,"&");         s = s.replace(//g,">");         s = s.replace(/ /g," ");         s = s.replace(/\'/g,"'");         s = s.replace(/\"/g,""");         return s;     },   /*4.用正则表达式实现html解码*/   htmlDecodeByRegExp:function (str){           var s = "";         if(str.length == 0) return "";         s = str.replace(/&/g,"&");         s = s.replace(/</g,"<");         s = s.replace(/>/g,">");         s = s.replace(/ /g," ");         s = s.replace(/'/g,"\'");         s = s.replace(/"/g,"\"");         return s;     }

 

综合写出检测一个字符串是否为一个有效URL的JS正则表达式程序

http://www.iteye.com/topic/481228

检查邮箱地址格式

n = n.replace(/[。|,|,|、]/g, "."), /^[A-Z_a-z0-9-\.]+@([A-Z_a-z0-9-]+\.)+[a-z0-9A-Z]{2,4}$/.test(n)

IP合法性检测 使用正则分组,四部分都不能大于255

((2[0-4]\d|25[0-5]|[01]?\d\d?)\.){3}(2[0-4]\d|25[0-5]|[01]?\d\d?)

 

 

2.遍历与事件响应,计时器

1:首先页面加载时马上响应JS代码如下运行(不一定要等所有的JS和图片加载完毕,就可以执行方法):

$(document).ready(function(){});

另一种简单写法:

$(function () {})

2:当然有些必须要等到所有元素都加载完才可以执行JS方法,可以如下面这种写法:

$(window).load(function() {
});

3:还有一种是DOM元素加载之前执行Jquery代码:

(function() {
})(jQuery)

 

对body中多个按钮定义onclick事件,用window.event.srcElement得到操作的按钮。

HTML

inervalId=setInterval("CountDown()",1000);

clearInterval(inervalId);

时钟实现

Untitled Document

 

屏幕数值获取与html注入,模拟QQ虚假弹窗

Untitled Document

    运用计时器制作淡入淡出的侧边分享栏

    Untitled Document
    分享到

     

    3.运动框架

    已经封装好的JS运动框架代码,传入Object和JSon,就可以对对象进行style数值运动变化。

    注意要将计时器设置在对象上,opacity属性特殊处理。

    在Jquery中有.animation({json},'slow',func(){}) 就可以作为我们的运动框架了。

    一些特殊效果也有如 fadeIn(500)/fadeOut(500)/fadeTo(0.5, 500) slideUp(500) 灵活使用

    function getstyle(obj,name){    if(obj.currentStyle){        return obj.currentStyle[name];      }else{          return getComputedStyle(obj,false)[name];    }} function startMove(obj,json,func){    clearInterval(obj.timer);     obj.timer=setInterval(function(){        var check=true;        for(var attr in json){            var cur=0;            if(attr=='opacity'){                cur=parseInt(parseFloat(getstyle(obj,attr))*100);            } else {                cur=parseInt(getstyle(obj,attr));            }            var speed=(json[attr]-cur)/6;            speed=speed>0?Math.ceil(speed):Math.floor(speed);            if(cur!=json[attr]){                check=false;                if(attr=='opacity'){                    obj.style.filter='alpha(opacity:'+(cur+speed)+')';                    obj.style.opacity=(cur+speed)/100;                }                else                    obj.style[attr]=cur+speed+'px';            }        }        if(check){            clearInterval(obj.timer);            if(func)                func();        }    },30);}

    在HTML中调用运动框架JS文件

    Untitled Document

     

    4.DOM操作

      

    HTML代码对应一颗DOM树。对DOM的各种操作事实上都是对这颗DOM树展开的。

    1. 查找节点

    主要是通过jQuery选择器来完成。结合文章开头的DOM树实例就行说明。        

    1 var $li=$("ul li:eq(0)");   //查找ul中第一个
  • 2 alert($li.text()); //打印出第一个节点中的文本内容
  • 2. 创建节点

    创建元素节点并不只是单单创建元素节点,还需要将其挂到DOM树上。例如我们创建一个<li>节点然后将其挂在<ul>上,具体代码如下:

    var $li_new=$("
  • "); //创建一个
  • 元素$("ul").append($li_new); //将其添加到
  • 3. 插入节点

    一种插入节点的方法是通过jQuery中的append()方法,下面通过表1将插入节点的各种方法进行总结。

                  表1                                            插入节点的各种方法

    方法   描述 示例
    append() 向每个匹配元素内部追加节点或是内容 

    HTML代码:<p>你好吗?</p>

    jQuery代码:$("p").append(“<b>还不错哦.</b>”);

    结果:<p>你好吗?<b>还不错哦.</b></p>

    appendTo()

    $(A).append(B):是将B追加到A上

    $(A).appendTo(B):是将A追加到B上

    HTML代码:<p>你好吗?</p>

    jQuery代码:$("<b>还不错哦.</b>").appendTo(“p”);

    结果:<p>你好吗?<b>还不错哦.</b></p>

     prepend()  向每个匹配的元素内部追加内容   

    HTML代码:<p>你好吗?</p>

    jQuery代码:$("p").prepend(“<b>还不错哦.</b>”);

    结果:<p><b>还不错哦.</b>你好吗?</p>

     prependTo()

    $(A).prepend(B):是将B追加到A上

    $(A).prependTo(B):是将A追加到B上 

     

    HTML代码:<p>你好吗?</p>

    jQuery代码:$("<b>还不错哦.</b>").aprependTo(“p”);

    结果:<p><b>还不错哦.</b>你好吗?</p>

     after() 在每个匹配的元素之后添加内容   

    HTML代码:<p>你好吗?</p>

    jQuery代码:$("p").after(“<b>还不错哦.</b>”);

    结果:<p>你好吗?</p><b>还不错哦.</b>

    insertAfter

    $(A).after(B):将B插入到A后

    $(A).insertAfter(B):将A插入到B后

    HTML代码:<p>你好吗?</p>

    jQuery代码:$(“<b>还不错哦.</b>”).insertAfter(“p”);

    结果:<p>你好吗?</p><b>还不错哦.</b>

    before() 在每个匹配元素之前插入内容

    HTML代码:<p>你好吗?</p>

    jQuery代码:$(“p”).before(“<b>还不错哦.</b>”);

    结果:<b>还不错哦.</b><p>你好吗?</p>

    insertBefore()

    $(A).before(B):将B插入到A前

    $(A).insertBefore(B):A插入到B前

    HTML代码:<p>你好吗?</p>

    jQuery代码:$(“<b>还不错哦.</b>”).insertBefore(“p”);

    结果:<b>还不错哦.</b><p>你好吗?</p>

    4. 删除节点

    jQuery中提供了三种方法删除多余的节点。

    remove()方法

    $("ul li:eq(0)").remove();     //获取ul下的第一个
  • 节点后,删除该节点
  • 值得注意的有两点:1.经remove()方法删除后的节点还可以恢复, 例如上述代码被删除后可以通过以下代码恢复

    1 var $li_delete=$("ul li:eq(0)");     //获得ul下第一个li节点2 $li_delete.remove();                 //将该节点删除3 $("ul").append($li_delete);          //在将被删除的节点添加到ul上,需要注意的是此时该li节点被放置到ul的最后面

    remove()参数,指定某属性的标签删除

    1 $("ul li").remove(“li[title=篮球]”);     //在
      下,删除属性title为篮球的li的节点

     

    detach()方法

    具体用法与remove方法基本一样。与remove()方法相同的是该方法在删除元素节点后,也可以恢复元素。与remove()方法不同的是该方法删除所匹配的元素时,并不会删除该元素所绑定的事件、附加的数据,比如说:一个<p>绑定了一个click(function(){ alert("能恢复吗?");});事件,如果用remove()删除之后,再次恢复该元素时候并不会恢复click()事件,而detach()方法则在恢复时,同时也可以恢复其click()事件。

     

    empty()方法

    准确的说,empty()方法并不是删除节点,而是清空节点,清空元素中的所有后代节点。最后只剩一个空节点(该元素的属性依然存在)。例如我们清空第三个羽毛球的<li>节点。可以用下述代码完成。

    1 $("ul li:eq(2)").empty;   //清空该节点

    5. 复制节点

    通过使用clone()方法,如果只写clone()则表示说明只复制节点,复制节点后,被复制的新元素并不具有任何行为。

    如果想复制原节点所绑定的行为(事件),那么写法应该为clone(true).

     

    6.替换节点与包裹节点

      两个方法replaceWith()与replaceAll(): $(A).replaceWith(B):用B替换A     

      $(A).replaceAll(B):用A替换B

    $("p").wrap("""");   用标签将

    包裹起来

     

    7. 属性操作

    1. 获取属性和设置属性

      通过使用attr()获取属性的值,参数可以为多个。执行下述代码就会弹出“你最喜欢的运动”.

    var $p=$("p");                  //获取节点

    var p_text=$p.attr("title");  //获取节点

    的属性title的值

     

    2. 删除属性

      通过removeAttr();如下例代码。

    1 $("p").removeAttr("title");     //删除

    的title属性

     

    8. 样式操作

    1.获取样式和设置样式

      我们知道,在HTML中改变样式的方法是通过CSS来完成的,一般都通过在元素中定义id或者class,而id或者class也输入该元素的一个属性,故可以通过attr()方法来获取和设置其属性。例如<p>标签中原始属性是class=start,在CSS中又定义了一个end的样式。这时我们就可以通过以下代码进行设置样式。

    1 $("p").attr("class",“end”);  //将

    标签的样式class从start该为end

    2. 追加样式

      通过jQuery中提供的addClass()方法进行追加样式,值得注意的是addClass()是该原先的样式中添加了一种新的样式(多了一种样式,如果以前样式是一种则使用该方法后样式变为两种),而attr()则是该变了元素的初始样式(样式没有增多)。

    3. 移除样式

      通过jQuery中的removeClass()方法。如果参数为空,则代表是移除其所有的样式。

    4. 切换样式

      通过使用jQuery中的toggle()方法,该方法在jQuery中有着广泛的应用,以后要出一篇blog要把常用的jQuery方法进行总结。这里只说toggle()方法应该如何切换样式。实际上,通过的是tooggleClass()方法进行切换。该方法可以控制样式的重复切换,如果类名存在就删除它,如果类名不存在就添加它。示例代码如下。

    1 $("p").tooggleClass("another");              //重复切换类名anohter

    5. 判断是否含有某个样式

    通过hasClass()方法进行判断,如果有则返回true,没有返回false。

    6. 设置样式

    .css控制sytle对象的各种样式属性。

    1 $("p").css({"color":"red","font-size":"14px"});  //设置

    的颜色和字体

     

    9. 设置和获取HTML、文本、值

    1. html()方法

      该方法类似于javascript中的innerHTML属性,获取的是HTML代码。

    2.text()方法

      该方法类似于javascript中的innerText属性,获取的是文本内容。

    3.val()方法

      该方法类似与javascript中的value属性,获取或者设置元素的值。需要注意的是,如果获取的是多个元素,那么返回值也将是含多个元素值的集合。

     

    10. 遍历节点

    1.children()方法:节点的子元素,而不考虑后代元素,即DOM树一个节点的直接子节点。

    2.next()方法:获得匹配元素后面紧邻的同辈元素

    3.prev()方法:获得匹配元素前面紧邻的同辈元素。

    4.siblings()方法:取得匹配元素前后所有的同辈元素

     

    运用DOM和运动框架制作模仿微博的发布效果。

    Untitled Document
    大家都在说

     

    5.JS的面向对象

    通过new构造函数创建一个对象,并给对象定义方法。

    通过call继承父对象,通过引用或复制来继承方法。

    call和apply,作用都是将函数绑定到另外一个对象上去运行

    格式和参数定义:

    A.call( B [,arg1,arg2,… ] );       // 参数列表,arg1,arg2,...

    将A作为对象B的一个方法运行

    辨析:http://blog.csdn.net/ithomer/article/details/6592082 .

    下面是一个实例,用来懒加载图片,其中将callback作为对象img的方法运行。

    function loadImage(url,callback) {    var img = new Image();    img.src = url;    if(img.complete) {  // 属性判断图片是否已经存在于浏览器缓存        callback.call(img);         return; // 直接返回,不用再处理onload事件    }    img.onload = function(){        img.onload = null;        callback.call(img);    }}

    实例2:

    style要设置成绝对位置,style位置属性要为字符串px的,可通过offsetLeft等属性获得数值。

    注意window.event.clientX只有在鼠标事件中才有效,下面是实现对div拖拽的程序。

    本程序将程序封装成对象Drag,注意其中对this属性的分辨和记录。

    Untitled Document
    aaa
    bbb

     

    用面向对象的方法写成的电话号码格式化验证功能的JS

    $(function() {    new numConfirm().addEvent();})function numConfirm() {    this.splitType = [3, 4, 4];}numConfirm.prototype = {    _position : function(target) {        var self = this;        var elemWidth = $(target).outerWidth(), elemHeight = $(target).outerHeight(), elemParent = $(target).parents('.parentCls'), containerHeight = $('.js-max-input', elemParent).outerHeight();        $(elemParent).css({            "position" : 'relative'        });        $('.js-max-input', elemParent).css({            'position' : 'absolute',            'top' : -elemHeight - containerHeight / 2,            'left' : 0        });    },    addEvent : function() {        var self = this;        $('.inputElem').each(function(index, item) {            $(this).keyup(function(e) {                var value = $.trim(e.target.value);                if (value == '') {                    $('.js-max-input').hide();                } else {                    $('.js-max-input').show();                }                var count = 0, output = [];                for (var i = 0; i < self.splitType.length; i++) {                    var s = value.substr(count, self.splitType[i]);                    if (s.length) {                        output.push(s);                    }                    count += self.splitType[i];                }                value = output.join('-');                $('.js-max-input').text(value);                self._position($(this));            });        });    }};
    View Code

     

    6、事件冒泡与阻止冒泡

    当事件发生后,这个事件就要开始传播,因为事件源本身并没有处理事件的能力需要委托DOM树父节点。例如我们点击一个按钮时,就会产生一个click事件,但这个按钮本身不能处理这个事件,事件必须从这个按钮传播出去,从而到达能够处理这个事件的代码中(例如我们给按钮的onclick属性赋一个函数的名字,就是让这个函数去处理该按钮的click事件)。 

    当事件在传播过程中,找到了一个能够处理它的函数,这时候我们就说这个函数捕捉到了这个事件。 
    说到这里,关键的问题来了,那就是一个函数是如何捕捉一个事件的呢?这就涉及到事件的冒泡了。 
    为了更好地理解冒泡的概念,现在想象一下你的面前放着一杯水,但这杯水和我们平时看到的有点点不同,它分为数层,每一层又分成一或多个区域,最顶层是我们熟悉的窗口对象(即window对象),下一层分为好几个区域(document对象、history对象等等),而document对象的下一层又分为多个子对象。 
    这些对象的层次关系构成了DOM中的对象树。 
    事件的传播是有方向的,当点击一个按钮时所产生的事件从这个按钮处开始向上传播(就像一个水泡从杯底冒上来,这就是之所以叫事件冒泡的原因),但这个事件总是寻找特定的属性是否有值。例如按钮的click事件先寻找在按钮上是否有onclick属性的有意义的定义(即该属性指向一个存在的函数或一段可执行的语句),如果有,执行这个函数或语句;然后事件继续向上传播,到达按钮的上一层对象(例如一个form对象或document对象,总之是包含了按钮的父对象),如果该对象也定义了onclick属性,则执行属性的值。 
    所以,如果这个按钮上面有3层(form、document、window),且这三层都定义了onclick属性,则当按钮的click事件产生时,将会调用4个(包括按钮本身的一个)函数或执行4段语句。

    在火狐Firefox、opera、IE下阻止冒泡事件是不同的代码的,火狐下使用的是event.stopPropagation(),而IE下使用的是cancelBubble,jQuery 可以使用e.stopPropagation()就可以兼容了。

    img.onmouseup = function(e){                e = e || window.event;                if(e.stopPropagation){                    e.stopPropagation();                }else{                    e.cancelBubble = true;                }            }

    附百度划词搜索的JS代码

    var baidusearch = (function(){        function init(tn){        addEV(document, 'mouseup', fn);        function fn(){            var isStandard = "getSelection" in window;            var ico_img = document.getElementById('selectsearch-icon');            if(ico_img){                ico_img.parentNode.removeChild(ico_img);            }            setTimeout(function(){                selection = isStandard ? window.getSelection() : document.selection.createRange()                var text = (isStandard ? selection+'' : selection.text).replace(/\n+/g, '');                if(text && text.length){                    if(text.length > 76){                        text = text.substring(0, 76);                    }                    show(isStandard, selection, text);                }            }, 25);        }        function show(isStandard, selection, text){            var scrollTop = document.body.scrollTop + document.documentElement.scrollTop;            var scrollLeft = document.body.scrollLeft + document.documentElement.scrollLeft;            if(isStandard){                var rangePos = selection.getRangeAt(0).getBoundingClientRect();                if(rangePos.top==0 && rangePos.right==0)                    return;                var tempTop = rangePos.top>35 ? rangePos.top-35+scrollTop : scrollTop;                var tempLeft = rangePos.right+70>document.documentElement.clientWidth ? document.documentElement.clientWidth-65+scrollLeft : rangePos.right+5+scrollLeft;                            }else{                var selectionLeft = selection.boundingLeft+selection.boundingWidth;                var tempTop = selection.boundingTop>35 ? selection.boundingTop-35+scrollTop : scrollTop;                var tempLeft = selectionLeft+70>document.documentElement.clientWidth ? document.documentElement.clientWidth-65+scrollLeft : selectionLeft+scrollLeft;            }            var text = encodeURI(text);            var img = document.createElement('img');            img.src = 'http://img.baidu.com/img/iknow/qb/select-search.png';            img.alt = '搜索';            img.style.cssText = "width:65px; height:31px; border:0px none;";            var link = document.createElement('a');            link.id = 'selectsearch-icon';            link.style.cssText = "cursor:pointer; position:absolute;"            link.href = 'http://www.baidu.com/s?wd='+text+'&tn='+tn+'&hl_tag=flayer';            link.target = '_blank';            link.onclick = function(){                link.parentNode.removeChild(link);            }            link.style.left = tempLeft + 'px';            link.style.top = tempTop + 'px';            link.appendChild(img);            document.body.appendChild(link);            img.onmouseup = function(e){                e = e || window.event;                if(e.stopPropagation){                    e.stopPropagation();                }else{                    e.cancelBubble = true;                }            }        }        function addEV(d,b,a){
    if(window.attachEvent){d.attachEvent("on"+b,a)}else{
    if(window.addEventListener){d.addEventListener(b,a,false)}}} }; return { 'init' : init }})();
    View Code

     

    转载于:https://www.cnblogs.com/updateofsimon/p/3533013.html

    你可能感兴趣的文章
    12:Web及MySQL服务异常监测案例
    查看>>
    数据库性能优化之冗余字段的作用
    查看>>
    DBA_实践指南系列9_Oracle Erp R12应用补丁AutoPatch/AutoControl/AutoConfig(案例)
    查看>>
    数据库设计三大范式
    查看>>
    ionic 字体的导入方法
    查看>>
    IP路由原理
    查看>>
    内部类详解
    查看>>
    洛谷P2726 阶乘 Factorials 数学
    查看>>
    类加载机制
    查看>>
    火柴棒等式(2008年NOIP全国联赛提高组)
    查看>>
    mongodb int型id 自增
    查看>>
    【转】关于大型网站技术演进的思考(十八)--网站静态化处理—反向代理(10)...
    查看>>
    Java中的4种代码块
    查看>>
    Ocelot(七)- 入门
    查看>>
    生成水杯热气
    查看>>
    程序员工作心法
    查看>>
    三个常用的PHP图表类库
    查看>>
    python中异常处理--raise的使用
    查看>>
    高中数学与初中数学的接轨点
    查看>>
    python 安装第三方模块
    查看>>