页面

2008年12月15日

[原创:JScript|Event]面向事件驱动的编程(二)--实例讲解:将span模拟成超连接(页 1)

JScript|Event]面向事件驱动的编程(二)--实例讲解:将span模拟成超连接

在上一篇文章[url=http://bbs.51js.com/viewthread.php?tid=50545]《面向事件驱动的编程》[/url]中我讲了三种将事件绑定到元素的方法,而推荐使用第三种方法,即使用attachEvent/addEventListener来绑定.上一篇文章的主旨是告诉大家如何使用事件,而这一篇文章的主旨是让大家弄懂如何灵活应用事件来批处理某一类的对象行为.

首先讲一讲事件传递的概念.什么是事件传递?举个现实的例子,有个人捏了一下你的手指,你可能会说他捏了你手指,也可能会说他捏了你的手,甚至可能会说他捏了你.事实上三种说法都没错,在浏览器事件的执行中亦有相似的情况,请看下边的例子:

[code]
<html id="HTMLElement" onclick="alert(this.id);">

<head>
<title>测试页面</title>
</head>

<body>
<table id="TABLEElement" onclick="alert(this.id);">
    <tbody id="TBODYElement" onclick="alert(this.id);">
        <tr id="TRElement" onclick="alert(this.id);">
            <td id="TDElement" onclick="alert(this.id);"><input type="button" id="ButtonElement" onclick="alert(this.id);" value="按钮" /></td>
        </tr>
    </tbody>
</table>
<script type="text/javascript">
function Object_Onclick()
{
    alert(this.id);
}
window.id = "windowObj";
window.onclick = Object_Onclick;
window.document.id = "documentObject";
window.document.onclick = Object_Onclick;
window.document.body.id = "bodyObject";
window.document.body.onclick = Object_Onclick;
</script>
</body>
</html>
[/code]

上边的例子给Input[type=button]、td、tr、tbody、table、body、html、document、window都设置了onclick事件处理函数,都是显示当前对象的id值,点击之后IE会依次出现ButtonElement、TDElement、TRElement、TBODYElement、bodyObject、HTMLElement、documentObj,而Firefox则有一点不同,它显示完documentObj之后还会显示windowObj,而IE却不会,这是因为IE的window对象没有onclick事件。从这里可以看出这些对象都受到了点击,执行了onclick事件函数,而且顺序是从事件来源对象一直往上传直到window对象,这就是浏览器的事件传递。

如何对一类元素的事件进行处理,这是本文的重点,而重点知识又在于事件的传递。从上边的例子可以看出,不管是哪里的对象引发了一个事件,最后都会往上传递,我们要做的是在事件的必经之路上处理它,建议使用window.document。再看一个例子:

[code]
<html>

<head>
<title>测试页面</title>
</head>

<body>
<a href="http://www.51js.com" target="_blank">无忧脚本论坛1</a>
<a href="http://www.51js.com" target="_blank">无忧脚本论坛2</a>
<script type="text/javascript">
function Links_Onclick(e)
{
    var src = window.document.all != null ? e.srcElement : e.target; //获取事件来源对象
    alert(src.innerHTML);
}
if(window.document.all != null)
    window.document.attachEvent("onclick", Links_Onclick)
else
    window.document.addEventListener("click", Links_Onclick, false);
</script>
</body>
</html>
[/code]

上边的例子给window.document绑定了一个点击事件处理函数Links_Onclick,在里边我获取了事件来源对象,并且显示它的innerHTML值,可以看出不管在IE还是在Firefox,点击无忧脚本论坛1的时候会显示"无忧脚本论坛1",点击无忧脚本论坛2的时候会无忧脚本论坛2,这下明白为什么我要大费周章讲事件传递了吧?我们正是要利用这一点,实现文章标题所说的:将span元素模拟成连接元素。

分析一下连接元素的一般特点:

1、有下划线
2、鼠标移动上去会变成手型鼠标
3、点击之后会进入某一个页面(href属性)
4、可以设置目标窗口的名称(target属性)

接下来一步一步实现上边所举的特点,首先是下划线和鼠标移动上去会变成手型鼠标,这个很简单,用CSS即可,可以与脚本无关,请看示例:

[code]
<html>

<head>
<title>测试页面</title>
<style type="text/css">
span.link
{
    text-decoration:underline;
    color:blue;
    cursor: pointer;
}
</style>
</head>

<body>
<span class="link">无忧脚本1</span>
<span class="link">无忧脚本2</span>
</body>
</html>
[/code]

接下来是实现"点击之后会进入某一个页面",可以给span元素增加一个属性href保存url,同时处理它的onclick事件,这就要用到刚才我说了半天的事件传递,思路是给window.document对象绑定一个onclick处理函数,如果事件来源对象的标签名(tagName)是span,它的class属性值为link,并且它拥有一个非空href属性,就调用window.open打开href属性所保存的url。

[code]
<html>

<head>
<title>测试页面</title>
<style type="text/css">
span.link
{
    text-decoration:underline;
    color:blue;
    cursor: pointer;
}
</style>
<script type="text/javascript">
function Document_Onclick(e)
{
    var src = window.document.all != null ? e.srcElement : e.target;
    if(src.tagName != null
        && src.className != null
        && src.getAttribute("href") != null
        && src.tagName.toString().toLowerCase() == "span"
        && src.className.toString().toLowerCase() == "link"
        && src.getAttribute("href").toString().length > 0)
    {
        window.open(src.getAttribute("href").toString());
    }
}
if(window.document.all != null)
    window.document.attachEvent("onclick", Document_Onclick);
else
    window.document.addEventListener("click", Document_Onclick, false);
</script>
</head>

<body>
<span class="link" href="http://www.51js.com">无忧脚本1</span>
<span class="link" href="http://www.51js.com">无忧脚本2</span>
</body>
</html>
[/code]

点击上边示例代码所模拟出来的"连接"之后,浏览器会连接到无忧脚本论坛(http://www.51js.com),第三个特点也实现了。[color=red]在这里特别说明一下:Firefox不支持直接使用src.href获取我们自定义的href属性,因此使用了IE和Firefox都支持的getAttribute(attributeName)方法,如果不存在则返回null。[/color]

最后的工作是增加target属性实现设置目标窗口的功能,要注意一点就是target属性是可有可无的,实现方法很简单,利用上边的实例就可以轻松实现,就是在window.open那里做一点点手脚,请看示例代码:

[code]
<html>

<head>
<title>测试页面</title>
<style type="text/css">
span.link
{
    text-decoration:underline;
    color:blue;
    cursor: pointer;
}
</style>
<script type="text/javascript">
function Document_Onclick(e)
{
    var src = window.document.all != null ? e.srcElement : e.target;
    if(src.tagName != null
        && src.className != null
        && src.getAttribute("href") != null
        && src.tagName.toString().toLowerCase() == "span"
        && src.className.toString().toLowerCase() == "link"
        && src.getAttribute("href").toString().length > 0)
    {
        if(src.getAttribute("target") != null
            && src.getAttribute("target").toString().length > 0)
            window.open(src.getAttribute("href").toString(), src.getAttribute("target").toString());
        else
            window.open(src.getAttribute("href").toString());
    }
}
if(window.document.all != null)
    window.document.attachEvent("onclick", Document_Onclick);
else
    window.document.addEventListener("click", Document_Onclick, false);
</script>
</head>

<body>
<span class="link" href="http://www.51js.com" target="_blank">无忧脚本1</span>
<span class="link" href="http://www.51js.com" target="_self">无忧脚本2</span>
</body>
</html>
[/code]

搞定!我们已经初步将拥有特定属性的span元素模拟成了超连接元素,当然这里边还大有文章可做,但这并不是重点,而且将span元素模拟成超连接并没有什么实用价值,毕竟已经有那么好用的A元素可以供我们使用,所以要弄明白一点:搞清楚事件的传递,并且利用它为我们做一些本来很麻烦的工作,这才是本文的重点。

好了,又要告一段落了,下一篇文章的主题还没定,估计是再来一个实例或者另开一个主题,敬请期待。

欢迎有兴趣的同志支持一下无忧脚本论坛的原创行动,一起将您的原创文章贴出来与网友分享,还记得一篇文章里说过这样的话:那些曾经帮助我们的人们,他们没有想过要得到回报,如果硬要说有,那也是希望你能够像他们那样帮助需要帮助的人。

没有评论: