DOM是 Document Object Model的缩写,意思是文档对象模型。根据 W3C DOM 规范(http://www.w3.org/DOM),DOM是一种与浏览器、平台、语言无关的接口,使用该接口可以轻松地访问页面中所有的标准组件。简单来说,DOM解决了Netscape的JavaScript和Microsoft的JScript之间的冲突,给予了 Web 设计师和开发者一套标准的方法,让他们能够轻松获取和操作网页中的数据、脚本和表现层对象。
3.1 DOM操作的分类
一般来说,DOM操作分为3个方面,即DOM Core(核心)、HTML-DOM、CSS-DOM。
1.DOM Core
DOM Core并不专属于JavaScript,任何一种支持DOM的程序设计语言都可以使用它。它的用途并非仅限于处理网页,也可以用来处理任何一种使用标记语言编写出来的文档,例如XML。
JavaScript 中的getElmentById()、getElementsByTagName()、getAttribute()和setAttribute()等方法,这些都是DOM Core的组成部分。
例如:
使用DOM Core来获取表单对象的方法:
document.getElementsByTagName("form");
使用DOM Core来获取某元素的src属性的方法:
element.getAttribute("src");
2.HTML-DOM
在使用JavaScript和DOM为HTML文件编写脚本时,有许多专属于HTML-DOM的属性。HTML-DOM的出现甚至比DOM Core还要早,它提供了一些更简明的记号来描述各种HTML元素的属性。
例如:
使用HTML-DOM来获取表单对象的方法:
document.forms //HTML-DOM提供了一个forms对象
使用HTML-DOM来获取某元素的src属性的方法:
element.src;
因此获取某些对象、属性既可以用DOM Core来实现,也可以使用HTML-DOM实现。相比较而言HTML-DOM的代码通常比较简短,不过它只能用来处理Web文档。
3.CSS-DOM
CSS-DOM是针对 CSS的操作。在JavaScript中,CSS-DOM技术的主要作用是获取和设置style对象的各种属性。通过改变style对象的各种属性,可以使网页呈现出各种不同的效果。
例如:
设置某元素style对象字体颜色的方法:
element.style.color = "red";
jQuery作为JavaScript库,继承并发扬了JavaScript对DOM对象的操作的特性,使开发人员能方便地操作DOM对象。下面详细介绍jQuery中的各种DOM操作。
3.2 jQuery中的DOM操作
下面我们构建一个网页。因为每一张网页都能用DOM表示出来,而每一份DOM都可以看作一棵DOM树。构建的网页效果如图
<p title="选择你最喜欢的水果." >你最喜欢的水果是?</p>
<ul>
<li title='苹果'>苹果</li>
<li title='橘子'>橘子</li>
<li title='菠萝'>菠萝</li>
</ul>
根据上面的网页结构构建出一棵DOM树,如图
接下来,对DOM的各种操作都将围绕这棵DOM树而展开。
3.2.1 查找节点
1.查找元素节点
获取元素节点并打印出它的文本内容,jQuery代码如下:
var $li = $("ul li:eq(1)"); //获取<ul>里第2个<li>节点
var li_txt = $li.text(); //获取第2个<li>元素节点的文本内容
alert(li_txt); //打印文本内容
以上代码获取了<ul>元素里第2个<li>节点,并将它的文本内容“橘子”打印出来,效果如图
2.查找属性节点
利用 jQuery 选择器查找到需要的元素之后,就可以使用 attr()方法来获取它的各种属性的值。attr()方法的参数可以是一个,也可以是两个。当参数是一个时,则是要查询的属性的名字,例如:
var $para = $("p"); //获取<p>节点
var p_txt = $para.attr("title"); //获取<p>元素节点属性title
//var p_txt = $para.text(); 效果同上条语句相同
alert(p_txt); //打印title属性值
以上代码获取了<p>节点,并将它的title属性的值打印出来,效果如图
3.2.2 创建节点
在DOM操作中,常常需要动态创建HTML内容,使文档在浏览器里的呈现效果发生变化,并且达到各种各样的人机交互的目的。
1.创建元素节点
例如要创建两个<li>元素节点,并且要把它们作为<ul>元素节点的子节点添加到DOM节点树上。
(1)创建两个<li>新元素。
(2)将这两个新元素插入文档中。
第(1)个步骤可以使用jQuery的工厂函数$()来完成:
var $li_1 = $("<li></li>"); //创建第1个<li>元素
var $li_2 = $("<li></li>"); //创建第2个<li>元素
$("ul").append($li_1); //添加到<ul>节点中,使之能在网页中显示
$("ul").append($li_2); //可以采取链式写法:$("ul").append($li_1).append ($li_2)
$(html)方法会根据传入的HTML标记字符串,创建一个DOM对象,并将这个DOM对象包装成一个jQuery对象后返回。
运行代码后,新创建的<li>元素将被添加到网页中,因为暂时没有在它们内部添加任何文本,所以只能看到<li>元素默认的“· ”,如图
2.创建文本节点
var $li_3 = $("<li>香蕉</li>"); //创建一个<li>元素,包括元素节点和文本节点
//“香蕉”就是创建的文本节点
var $li_4 = $("<li>雪梨</li>"); //创建一个<li>元素,包括元素节点和文本节点
//“雪梨”就是创建的文本节点。
$("ul").append($li_3); //添加到<ul>节点中,使之能在网页中显示
$("ul").append($li_4); //添加到<ul>节点中,使之能在网页中显示
效果如图:
注意:无论$(html)中的HTML代码多么复杂,都可以使用相同的方式来创建。例如$("<li><em>这是</em><b>一个</b>< a href='#' >复杂的组合</ a></li>");
3.创建属性节点
var $li_5 = $("<li title='香蕉'>香蕉</li>"); //创建一个<li>元素
//包括元素节点、文本节点和属性节点
//其中title='香蕉'就是创建的属性节点
var $li_6 = $("<li title='雪梨'>雪梨</li>"); //创建一个<li>元素
//包括元素节点、文本节点和属性节点
//其中title='雪梨'就是创建的属性节点
$("ul").append($li_5);
$("ul").append($li_6); //添加到<ul>节点中,使之能在网页中显示
上图创建文本节点的例子中新增的元素没有属性节点,创建属性节点的例子中新增的元素有title属性节点
3.2.3 插入节点
这些插入节点的方法不仅能将新创建的DOM元素插入到文档中,也能对原有的DOM元素进行移动。
例如利用它们创建新元素并对其进行插入操作:
var $li_1 = $("<li title='香蕉'>香蕉</li>");
var $li_2 = $("<li title='雪梨'>雪梨</li>");
var $li_3 = $("<li title='其他'>其他</li>");
var $parent = $("ul");
var $two_li = $("ul li:eq(1)");
$parent.append($li_1);
$parent.prepend($li_2);
$li_3.insertAfter($two_li);
例如利用它们对原有的DOM元素进行移动:
var $one_li = $("ul li:eq(1)"); //获取<ul>节点中第2个<li>元素节点
var $two_li = $("ul li:eq(2)"); //获取<ul>节点中第3个<li>元素节点
$two_li.insertBefore($one_li); //移动节点
3.2.4 删除节点
jQuery 提供了三种删除节点的方法,即remove(),detach()和empty()。
1.remove()方法
作用是从DOM中删除所有匹配的元素,传入的参数用于根据jQuery表达式来筛选元素。例如删除图3-11中<ul>节点中的第2个<li>元素节点,jQuery代码如下:
var $one_li = $("ul li:eq(1)");
$one_li.remove(); //获取第2个<li>元素节点后,将它从网页中删除
当某个节点用remove()方法删除后,该节点所包含的所有后代节点将同时被删除。这个方法的返回值是一个指向已被删除的节点的引用,因此可以在以后再使用这些元素:
var $li = $("ul li:eq(1)").remove();//获取第2个<li>元素节点后,将它从网页中删除
$li.appendTo("ul"); //把刚才删除的节点又重新添加到<ul>元素里
可以直接使用appendTo()方法的特性来简化以上代码:
$("ul li:eq(1)").appendTo("ul");
另外remove()方法也可以通过传递参数来选择性地删除元素:
$("ul li").remove("li[title!=菠萝]");
//将<li>元素中属性title不等于“菠萝”的<li>元素删除
2.detach()方法
detach()和remove()一样,也是从DOM中去掉所有匹配的元素。但需要注意的是,这个方法不会把匹配的元素从 jQuery 对象中删除,因而可以在将来再使用这些匹配的元素。与 remove()不同的是,所有绑定的事件、附加的数据等都会保留下来。
$("ul li").click(function(){
alert( $(this).html() );
})
var $li = $("ul li:eq(1)").detach(); // 删除元素
$li.appendTo("ul"); //重新追加此元素,发现它之前绑定的事件还在,如果使用 remove()方法删除元素的话,那么它之前绑定的事件将失效。
3.empty()方法
严格来讲,empty()方法并不是删除节点,而是清空节点,它能清空元素中的所有后代节点。
$("ul li:eq(1)").empty();
//获取第2个<li>元素节点后,清空此元素里的内容,注意是元素里
当运行代码后,第2个<li>元素的内容被清空了,只剩下<li>标签默认的符号“· ”
3.2.5 复制节点
例如图3-19所示的某个购物网站的效果,用户不仅可以通过单击商品下方的“选择”按钮购买相应的产品,也可以通过鼠标拖动商品并将其放到购物车中。这个商品拖动功能就是用的复制节点,将用户选择的商品所处的节点元素复制一次,并将其跟随鼠标移动,从而达到以下购物效果。
图3-19
继续沿用之前的例子,如果单击<li>元素后需要再复制一个<li>元素,可以使用 clone()方法来完成:
$("ul li").click(function(){
$(this).clone().appendTo("ul");//复制当前单击的节点,并将它追加到<ul>元素中
})
在页面中单击“苹果”后,列表最下方出现新节点“苹果”
复制节点后,被复制的新元素并不具有任何行为。如果需要新元素也具有复制功能(本例中是单击事件),可以使用如下jQuery代码:
$("ul li").click(function(){
$(this).clone(true).appendTo("body"); //注意参数true
})
在clone()方法中传递了一个参数true,它的含义是复制元素的同时复制元素中所绑定的事件。因此该元素的副本也同样具有复制功能(本例中是单击事件)。
3.2.6 替换节点
如果要替换某个节点,jQuery提供了两个方法,即replaceWith()和replaceAll()。
replaceWith()方法的作用是将所有匹配的元素都替换成指定的HTML或者DOM元素。例如要将网页中“<p title="选择你最喜欢的水果.">你最喜欢的水果是?</p>”替换成“<strong>你最不喜欢的水果是?</strong>”,可以使用如下jQuery代码:
$("p").replaceWith("<strong>你最不喜欢的水果是?</strong>");
replaceAll()与replaceWith()方法的作用相同,只是颠倒了replaceWith()操作:
$("<strong>你最不喜欢的水果是?</strong>").replaceAll("p");
注意:如果在替换之前,已经为元素绑定事件,替换后原先绑定的事件将会与被替换的元素一起消失,需要在新元素上重新绑定事件。
3.2.7 包裹节点
如果要将某个节点用其他标记包裹起来,jQuery提供了wrap()。该方法对于需要在文档中插入额外的结构化标记非常有用,而且它不会破坏原始文档的语义。
$("strong").wrap("<b></b>");//用<b>标签把<strong>元素包裹起来
得到的结果如下:
包裹节点操作还有其他两个方法,即wrapAll()和wrapInner()。
1.wrapAll()方法
该方法会将所有匹配的元素用一个元素来包裹。它不同于wrap()方法,wrap()方法是将所有的元素进行单独的包裹。
为了使效果更突出,在网页中再加入一个<strong>元素。
HTML代码如下:
<strong title="选择你最喜欢的水果." >你最喜欢的水果是?</strong>
<strong title="选择你最喜欢的水果." >你最喜欢的水果是?</strong>
<ul>
<li title='苹果'>苹果</li>
<li title='橘子'>橘子</li>
<li title='菠萝'>菠萝</li>
</ul>
如果使用wrap()方法包裹<strong>元素:
$("strong").wrap("<b></b>");
使用wrapAll()方法包裹<strong>元素,jQuery代码如下:
$("strong").wrapAll("<b></b>");
则会得到如下结果:
注意:如果被包裹的多个元素间有其它元素,其它元素会被放到包裹元素之后。
2.wrapInner()方法
该方法将每一个匹配的元素的子内容(包括文本节点)用其他结构化的标记包裹起来。例如可以使用它来包裹<strong>标签的子内容,jQuery代码如下:
$("strong").wrapInner("<b></b>");
运行代码后,发现<strong>标签内的内容被一对<b>标签包裹了,结果如下:
3.2.8 属性操作
在jQuery中,用attr()方法来获取和设置元素属性,removeAttr()方法来删除元素属性。
1.获取属性和设置属性
如果要获取<p>元素的属性title,那么只需要给attr()方法传递一个参数,即属性名称。
var $para = $("p"); //获取<p>节点
var p_txt = $para.attr("title"); //获取<p>元素节点属性title
如果要设置<p>元素的属性title的值,也可以使用同一个方法,不同的是,需要传递两个参数即属性名称和对应的值。
jQuery代码如下:
$("p").attr("title" , "your title"); //设置单个的属性值
如果需要一次性为同一个元素设置多个属性,可以使用下面的代码来实现:
$("p").attr({"title" : "your title" , "name": "test" }); //将一个“名/值”形式的对象设置为匹配元素的属性
注意:jQuery 中的很多方法都是同一个函数实现获取(getter)和设置(setter)的,例如上面的attr()方法,既能设置元素属性的值,也能获取元素属性的值。类似的还有html()、text()、height()、width()、val()和css()等方法。
2.删除属性
删除文档中某个元素的特定属性,可以使用 removeAttr()方法来完成该任务。
删除<p>元素的title属性:
var $para = $("p");
var p_txt = $para.removAttr("title");
运行代码后,<p>元素的title属性将被删除。
注意:jQuery1.6中新增了prop()和removeProp(),分别用来获取在匹配的元素集中的第一个元素的属性值和为匹配的元素删除设置的属性。
3.2.9 样式操作
1.获取样式和设置样式
<p class="myClass" title="选择你最喜欢的水果." >你最喜欢的水果是?</p>
在上面的代码中,class也是<p>元素的属性,因此获取class和设置class都可以使用attr()方法来完成。
var p_class = $("p").attr("class");//获取<p>元素的class
也可以使用attr()方法来设置<p>元素的class:
$("p").attr("class","high"); //设置<p>元素的class为“high”
2.追加样式
jQuery提供了专门的addClass()方法来追加样式。
$("p").addClass("another"); //给<p>元素追加“another”类
此时<p>元素同时拥有两个class值,即“high”和“another”。在CSS中有以下两条规定。
(1)如果给一个元素添加了多个class值,那么就相当于合并了它们的样式。
(2)如果有不同的class设定了同一样式属性,则后者覆盖前者。
attr()和addClass()的区别:
3.移除样式
在上面的例子中,为<p>元素追加了another样式。此时<p>元素的HTML代码变为:
<p class="high another" title="选择你最喜欢的水果.">你最喜欢的水果是?</p>
可以使用如下的jQuery代码来删除<p>元素中值为“high”的class:
$("p").removeClass("high"); //移除<p>元素中值为“high”的class
如果要把<p>元素的两个class都删除,就要使用两次removeClass()方法,代码如下:
$("p").removeClass("high").removeClass("another");
可以以空格的方式删除多个class名,jQuery代码如下:
$("p").removeClass("high another");
另外,还可以利用removeClass()方法的一个特性来完成同样的效果。当它不带参数时,就会将class的值全部删除,jQuery代码如下:
$("p").removeClass(); //移除<p>元素的所有class
4.切换样式
在第2章的案例研究中介绍了一个方法,即toggle(),jQuery代码如下:
$toggleBtn.toggle(function(){
//toggle(),交替一组动作
//显示元素 代码③
},function(){
//隐藏元素 代码④
})
toggle()方法此处的作用是交替执行代码③和代码④两个函数,如果元素原来是显示的,则隐藏它;如果元素原来是隐藏的,则显示它。此时,toggle()方法主要是控制行为上的重复切换。
另外jQuery还提供了一个toggleClass()方法控制样式上的重复切换。如果类名存在则删除它,如果类名不存在则添加它。
例如对<p>元素进行toggleClass()方法操作。
$("p").toggleClass("another"); //重复切换类名“another”
5.判断是否含有某个样式
hasClass()可以用来判断元素中是否含有某个class,如果有,则返回true,否则返回false。
例如可以使用下面的代码来判断<p>元素中是否含有“another”的class:
$("p").hasClass("another");
注意:这个方法是为了增强代码可读性而产生的。在jQuery内部实际上是调用了is()方法来完成这个功能的。该方法等价于如下代码:$("p").is(".another");
3.2.10 设置和获取HTML、文本和值
1.html()方法
此方法类似于JavaScript中的innerHTML属性,可以用来读取或者设置某个元素中的HTML内容。
为了更清楚地展示效果,将<p>元素的HTML代码改成:
<p title="选择你最喜欢的水果." ><strong>你最喜欢的水果是?</strong></p>
然后用html()方法对<p>元素进行操作:
var p_html = $("p").html(); //获取<p>元素的HTML代码
alert(p_html); //打印<p>元素的HTML代码
运行代码后,效果如图
如果需要设置某元素的HTML 代码,那么也可以使用该方法,不过需要为它传递一个参数。例如要设置<p>元素的HTML代码,可以使用如下代码:
$("p").html("<strong>你最喜欢的水果是?</strong>"); //设置<p>元素的HTML代码
注意:html()方法可以用于XHTML文档,但不能用于XML文档。
2.text()方法
此方法类似于JavaScript中的innerText属性,可以用来读取或者设置某个元素中的文本内容。
用text()方法对<p>元素进行操作:
var p_text = $("p").text(); //获取<p>元素的文本内容
alert(p_text); //打印<p>元素的文本内容
运行代码后,效果如图
与 html()方法一样,如果需要为某元素设置文本内容,那么也需要传递一个参数。例如对<p>元素设置文本内容,代码如下:
$("p").text("你最喜欢的水果是?"); //设置<p>元素的文本内容
注意:(1)JavaScript中的innerText属性并不能在Firefox浏览器下运行,而jQuery的text()方法支持所有的浏览器。
(2)text()方法对HTML文档和XML文档都有效。
3.val()方法
此方法类似于 JavaScript 中的value 属性,可以用来设置和获取元素的值。无论元素是文本框,下拉列表还是单选框,它都可以返回元素的值。如果元素为多选,则返回一个包含所有选择的值的数组。
如图3-30所示,这是某网站的邮箱登录界面,默认状态下,邮箱地址文本框和邮箱密码框内分别有“请输入邮箱地址”和“请输入邮箱密码”的提示。
图3-30 默认状态
当将鼠标聚焦到邮箱地址文本框时,文本框内的“请输入邮箱地址”文字将被清空,效果如图3-31所示。
图3-31 当地址文本框获得鼠标焦点时
如果此时未在邮箱地址框中输入任何内容,而将鼠标焦点直接聚焦到密码输入框,则会发现密码框内的提示文字被清空了,同时邮箱地址输入框的提示也被还原了,效果如图3-32所示。
图3-32 当地址框中未输入任何内容时,将鼠标焦点移动到密码框
要实现以上例子展示的功能,可以使用val()方法。实现步骤如下。
第1步:设计网页的基本结构。在页面中添加两个文本框,分别对两个文本框设置id,同时设置它们的默认值为“请输入邮箱地址”和“请输入邮箱密码”。
HTML代码如下:
<input type="text" id="address" value="请输入邮箱地址"/><br>
<input type="text" id="password" value="请输入邮箱密码"/><br>
<input type="button" value="登录"/>
呈现的网页效果如图
第2步:对“输入框”进行操作。
当输入框获取鼠标焦点时,如果地址框的值为“请输入邮箱地址”,则将地址框中的值清空。
$("#address").focus(function(){
var txt_value = $(this).val();
if(txt_value == "请输入邮箱地址"){
$(this).val("");
}
});
$("#address").blur(function(){
var txt_value = $(this).val();
if(txt_value == ""){
$(this).val("请输入邮箱地址");
}
});
$("#password").focus(function(){
var txt_value = $(this).val();
if(txt_value == "请输入邮箱密码"){
$(this).val("");
}
});
$("#password").blur(function(){
var txt_value = $(this).val();
if(txt_value == ""){
$(this).val("请输入邮箱密码");
}
});
注意:focus()方法相当于JavaScript中的onfocus()方法,作用是处理获得焦点时的事件。blur()方法相当于JavaScript中的onblur()方法,作用是处理失去焦点时的事件。
在该例子中,也可以使用表单元素的defaultValue属性来实现同样的功能,defaultValue属性包含该表单元素的初始值。代码如下:
$("#address").focus(function(){ //地址框获得鼠标焦点
var txt_value = $(this).val(); //得到当前文本框的值
if(txt_value==this.defaultValue){ //使用defaultValue属性
$(this).val(""); //如果符合条件,则清空文本框内容
}
});
$("#address").blur(function(){ //地址框失去鼠标焦点
var txt_value = $(this).val(); //得到当前文本框的值
if(txt_value==""){
$(this).val(this.defaultValue); //如果符合条件,则设置内容
}
})
//同理,密码框也类似
注意:this指向当前的文本框,“this.defaultValue”就是当前文本框的默认值。
通过上面的例子可以发现val()方法不仅能设置元素的值,同时也能获取元素的值。另外,val()方法还有另外一个用处,就是它能使select(下拉列表框)、checkbox(多选框)和radio(单选框)相应的选项被选中,在表单操作中会经常用到。
<select id="single">
<option>选择1号</option>
<option>选择2号</option>
<option>选择3号</option>
</select>
<select id="multiple" multiple="multiple" style="height:120px;">
<option selected="selected">选择1号</option>
<option>选择2号</option>
<option>选择3号</option>
<option>选择4号</option>
<option selected="selected">选择5号</option>
</select><br>
<input type="checkbox" value="check1"/> 多选1
<input type="checkbox" value="check2"/> 多选2
<input type="checkbox" value="check3"/> 多选3
<input type="checkbox" value="check4"/> 多选4 <br>
<input type="radio" value="radio1"/> 单选1
<input type="radio" value="radio2"/> 单选2
<input type="radio" value="radio3"/> 单选3
运行代码后,显示效果如图
该网页中一些元素是默认选中的,可以通过 val()方法来改变它们的选中项。如果要使第1个下拉框的第2项被选中,可以用以下jQuery代码实现:
$("#single").val("选择2号");
如果要使下拉列表的第2项和第3项被选中,可以用以下jQuery代码实现:
$("#multiple").val(["选择2号", "选择3号"]); //以数组的形式赋值
依照上面类似的写法,下面的代码可以使多选框和单选框被选中,jQuery代码如下:
$(":checkbox").val(["check2","check3"]);
$(":radio").val(["radio2"]);
注意:在上面这个例子中,可以使用val()方法,也可以使用attr()方法来实现同样的功能。
$("#single option:eq(1)").attr("selected", true );
$("[value=radio2]:radio").attr("checked", true );
3.2.11 遍历节点
1.children()方法
该方法用于取得匹配元素的子元素集合。
此处使用本文开头所画的那颗DOM树的结构,如图
根据DOM树的结构,可以知道各个元素之间的关系以及它们子节点的个数。<body>元素下有<p>和<ul>两个子元素,<p>元素没有子元素,<ul>元素有3个<li>子元素。
下面使用children()方法来获取匹配元素的所有子元素的个数。
var $body = $("body").children();
var $p = $("p").children();
var $ul = $("ul").children();
alert($body.length ); //<body>元素下有2个子元素
alert($p.length ); //<p>元素下有0个子元素
alert($ul.length ); //<ul>元素下有3个子元素
for(var i=0,len=$ul.length;i< len;i++){
alert($ul[i].innerHTML ); //循环输出<li>元素的HTML内容
}
注意:children()方法只考虑子元素而不考虑其他后代元素。
2.next()方法
该方法用于取得匹配元素后面紧邻的同辈元素。
从 DOM 树的结构中可以知道<p>元素的下一个同辈节点是<ul>,因此可以通过next()方法来获取<ul>元素,代码如下:
var $p1 = $("p").next(); //取得紧邻<p>元素后的同辈元素
结果:
<ul>
<li title='苹果'>苹果</li>
<li title='橘子'>橘子</li>
<li title='菠萝'>菠萝</li>
</ul>
3.prev()方法
该方法用于取得匹配元素前面紧邻的同辈元素。
从DOM树的结构中可以知道<ul>元素的上一个同辈节点是<p>,因此可以通过prev()方法来获取<p>元素,代码如下:
var $ul = $("ul").prev(); //取得紧邻<ul>元素前的同辈元素
结果:
<p title="选择你最喜欢的水果." >你最喜欢的水果是?</p>
4.siblings()方法
该方法用于取得匹配元素前后所有的同辈元素。
如果要获取<p>元素的同辈元素,则可以使用如下代码:
var $p2 = $("p").siblings(); //取得<p>元素的同辈元素
结果:
<ul>
<li title='苹果'>苹果</li>
<li title='橘子'>橘子</li>
<li title='菠萝'>菠萝</li>
</ul>
5.closest()
该方法用于取得最近的匹配元素。首先检查当前元素是否匹配,如果匹配则直接返回元素本身。如果不匹配则向上查找父元素,逐级向上直到找到匹配选择器的元素。如果什么都没找到则返回一个空的jQuery对象。
比如,给点击的目标元素的最近的li元素添加颜色,可以使用如下代码:
$(document).bind("click", function (e) {
$(e.target).closest("li").css("color","red");
})
6.parent(),parents()与closest()的区别
除此之外,在 jQuery 中还有很多遍历节点的方法,例如 find()、filter()、nextAll()和prevAll()等。值得注意的是,这些遍历 DOM 方法有一个共同点,都可以使用jQuery表达式作为它们的参数来筛选元素。
3.2.12 CSS-DOM操作
CSS-DOM技术简单来说就是读取和设置style对象的各种属性。style属性很有用,但最大不足是无法通过它来提取到通过外部CSS设置的样式信息,然而在jQuery中,这些都是非常的简单。
可以直接利用css()方法获取元素的样式属性:
$("p").css("color"); //获取<p>元素的样式颜色
无论color属性是外部CSS导入,还是直接拼接在HTML元素里(内联),css()方法都可以获取到属性style里的其他属性的值。
也可以直接利用css()方法设置某个元素的单个样式,例如:
$("p").css("color","red"); //设置<p>元素的样式颜色为红色
与attr()方法一样,css()方法也可以同时设置多个样式属性,代码如下:
$("p").css({"fontSize":"30px" ,"backgroundColor":"#888888"})
//同时设置字体大小和背景色
注意:(1)如果值是数字,将会被自动转化为像素值。(2)在css()方法中,如果属性中带有“-”符号,例如font-size和background-color属性,如果在设置这些属性的值的时候不带引号,那么就要用驼峰式写法,例如:$("p").css({ fontSize : "30px" , backgroundColor : "#888888" })如果带上了引号,既可以写成“font-size”,也可以写成“fontSize”。总之建议大家加上引号,养成良好的习惯。
对透明度的设置,可以直接使用opacity属性,jQuery已经处理好了兼容性的问题,如下代码所示,将<p>元素的透明度设置为半透明:
$("p").css("opacity","0.5");
如果需要获取某个元素的height属性,则可以通过如下jQuery代码实现:
$(element).css("height");
在jQuery中还有另外一种方法也可以获取元素的高度,即height()。它的作用是取得匹配元素当前计算的高度值(px)。jQuery代码如下:
$("p").height(); //获取<p>元素的高度值
height()方法也能用来设置元素的高度,如果传递的值是一个数字,则默认单位为px。如果要用其他单位(例如em),则必须传递一个字符串。jQuery代码如下:
$("p").height(100); //设置<p>元素的高度值为100px
$("p").height("10em"); //设置<p>元素的高度值为10em
注意:(1)在jQuery 1.2版本以后的height()方法可以用来获取window和document的高度。
(2)两者的区别是:css()方法获取的高度值与样式的设置有关,可能会得到"auto",也可能得到"10px"之类的字符串;而 height()方法获取的高度值则是元素在页面中的实际高度,与样式的设置无关,并且不带单位。
与height()方法对应的还有一个width()方法,它可以取得匹配元素的宽度值(px)。同样,width()方法也能用来设置元素的宽度。
此外,在CSS-DOM中,关于元素定位有以下几个经常使用的方法。
1.offset()方法
它的作用是获取元素在当前视窗的相对偏移,其中返回的对象包含两个属性,即top和left,它只对可见元素有效。例如用它来获取<p>元素的的偏移量,jQuery代码如下:
var offset = $("p").offset(); //获取<p>元素的offset()
var left = offset.left; //获取左偏移
var top = offset.top; //获取右偏移
2.position()方法
它的作用是获取元素相对于最近的一个position样式属性设置为relative或者absolute的祖父节点的相对偏移,与 offset()一样,它返回的对象也包括两个属性,即 top和left。jQuery代码如下:
var position = $("p").position(); //获取<p>元素的position()
var left = position.left; //获取左偏移
var top = position.top; //获取右偏移
3.scrollTop()方法和scrollLeft()方法
这两个方法的作用分别是获取元素的滚动条距顶端的距离和距左侧的距离。例如使用下面的代码获取<p>元素的滚动条距离:
var $p = $("p");
var scrollTop = $p.scrollTop(); //获取元素的滚动条距顶端的距离
var scrollLeft = $p.scrollLeft(); //获取元素的滚动条距左侧的距离
另外,可以为这两个方法指定一个参数,控制元素的滚动条滚动到指定位置。例如使用如下代码控制元素内的滚动条滚动到距顶端300和距左侧300的位置:
$("textarea").scrollTop(300); //元素的垂直滚动条滚动到指定的位置
$("textarea").scrollLeft(300); //元素的横向滚动条滚动到指定的位置
3.3案例研究—某网站的超链接和图片提示效果
在这一节中,将以某网站的超链接和图片提示效果为例,来理解和巩固jQuery中的DOM操作。
1.超链接提示效果
在现代的浏览器中,它们已经自带了超链接提示,只需在超链接中加入 title 属性就可以了。HTML代码如下:
< a href="#" title="这是我的超链接提示.">提示</ a>
然而这个提示效果的响应速度是非常缓慢的,考虑到良好的人机交互,需要的是当鼠标移动到超链接的那一瞬间就出现提示。这时就需要移除<a>标签中的title提示效果,自己动手做一个类似功能的提示。
首先在空白的页面上,添加两个普通超链接和两个带有class的超链接。
HTML代码如下:
<p>< a href="#" class="tooltip" title="这是我的超链接提示1.">提示1.</ a></p>
<p>< a href="#" class="tooltip" title="这是我的超链接提示2.">提示2.</ a></p>
<p>< a href="#" title="这是自带提示1.">自带提示1.</ a> </p>
<p>< a href="#" title="这是自带提示2.">自带提示2.</ a> </p>
然后为class为tooltip的超链接添加mouseover和mouseout事件,jQuery代码如下:
$(function(){
$("a.tooltip").mouseover(function(e){
//创建<div>元素
var tooltip="<div id='tooltip'>" + this.title + "</div>";
$("body").append(tooltip); //将它追加到文档中
$("#tooltip")
.css({
"top": e.pageY + "px",
"left": e.pageX + "px"
}).show("fast"); //设置x坐标和y坐标,并且显示
}).mouseout(function(){
$("#tooltip").remove(); //移除
});
})
运行效果,如图
此时的效果有两个问题:首先是当鼠标滑过后,<a>标签中的title属性的提示也会出现;其次是设置x坐标和y坐标的问题,由于自制的提示与鼠标的距离太近,有时候会引起无法提示的问题(鼠标焦点变化引起mouseout事件)。
为了移除<a>标签中自带的title提示功能,需要进行以下几个步骤。
(1)当鼠标滑入时,给对象添加一个新属性,并把title的值传给这个属性,然后清空属性title的值。
jQuery代码如下:
this.myTitle = this.title;
this.title = "";
var tooltip = "<div id='tooltip'>"+ this.myTitle +"</div>";
(2)当鼠标滑出时,再把对象的myTitle属性的值又赋给属性title。
jQuery代码如下:
this.title = this.myTitle;
注意:为什么当鼠标滑出时,要把属性值又赋给属性title呢?因为当鼠标滑出时,需要考虑再次滑入时的属性title值,如果不将myTitle的值重新赋给title属性,当再次滑入时,title的值就为空了。
为了解决第2个问题(自制的提示与鼠标的距离太近,有时候会引起无法提示的问题),需要重新设置提示元素的top和left的值,代码如下所示,为top增加了10px,为left增加了20px。
完整的代码如下:
$(function(){
var x = 10;
var y = 20;
$("a.tooltip").mouseover(function(e){
this.myTitle = this.title;
this.title = "";
var tooltip = "<div id='tooltip'>"+this.myTitle+"</div>";
//创建<div>元素
$("body").append(tooltip); //将它追加到文档中
$("#tooltip")
.css({
"top": (e.pageY+y) + "px",
"left": (e.pageX+x) + "px"
}).show("fast"); //设置x坐标和y坐标,并且显示
}).mouseout(function(){
this.title = this.myTitle;
$("#tooltip").remove(); //移除
});
})
此时,鼠标滑入和滑出显示已经没问题了,但当鼠标在超链接上移动时,提示效果并不会跟着鼠标移动。如果需要提示效果跟随鼠标一起移动,可以为超链接加上一个mousemove事件。完整的jQuery代码如下:
$(function(){
var x = 10;
var y = 20;
$("a.tooltip").mouseover(function(e){
this.myTitle = this.title;
this.title = "";
//创建<div>元素
var tooltip = "<div id='tooltip'>"+this.myTitle+"</div>";
$("body").append(tooltip);//将它追加到文档中
$("#tooltip")
.css({
"top": (e.pageY+y) + "px",
"left": (e.pageX+x) + "px"
}).show("fast"); //设置x坐标和y坐标,并且显示
}).mouseout(function(){
this.title = this.myTitle;
$("#tooltip").remove(); //移除
}).mousemove(function(e){
$("#tooltip")
.css({
"top": (e.pageY+y) + "px",
"left": (e.pageX+x) + "px"
});
});
})