VB.net 2010 视频教程 VB.net 2010 视频教程 python基础视频教程
SQL Server 2008 视频教程 c#入门经典教程 Visual Basic从门到精通视频教程
当前位置:
首页 > Python基础教程 >
  • 加点JavaScript魔法(2)

<div> ... popover elements here ... </div></span>

 

<div><span>元素是不可见的,因此它们是用于帮助组织和构建DOM的重要元素。 div元素是块元素,有点像HTML文档中的段落,而<span>元素是行内元素,它可以用于字词级别。本处,我决定使用<span>元素,因为我要包装的<a>元素也是行内元素。

因此,我将继续并重构我的app/templates/_post.html子模板以包含<span>元素:

  •  
  •  
  •  
  •  
  •  
  •  
  •  
{% set user_link %}    <span class="user_popup">        <a href="{{ url_for('main.user', username=post.author.username) }}">            {{ post.author.username }}        </a>    </span>{% endset %}

 

如果你想知道弹出式HTML元素在哪里,好消息是我不必操心这一点。当我在刚刚创建的<span>元素上调用popover()初始化函数时,Bootstrap框架会为我动态地插入弹出组件

 

06

鼠标悬停事件

正如我上面提到的,Bootstrap中的popover组件使用的悬停行为不够灵活,无法满足我的需求,但如果你查看trigger选项的文档,则hover只是其中一个可能的值。一个引起我注意的是manual模式,在这种模式下,可以通过JavaScript调用手动显示或删除弹出窗口,这种模式可以让我自由地实现悬停逻辑,所以我将使用该选项并实现我自己的悬停事件处理程序,并以我需要的方式工作。

所以我的下一步是将一个“hover”事件附加到页面中的所有链接。使用jQuery,可以通过调用element.hover(handlerIn, handlerOut)将悬停事件附加到任何HTML元素。如果在元素集合上调用这个函数,jQuery方便地将事件附加到所有元素上。这两个参数是两个函数,分别在用户将鼠标指针移入和移出目标元素时调用对应的函数。

app/templates/base.html:悬停事件

  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
$(function() {        $('.user_popup').hover(            function(event) {                // mouse in event handler                var elem = event.currentTarget;            },            function(event) {                // mouse out event handler                var elem = event.currentTarget;            }        )    });

事件参数是一个事件对象,它包含了一些有用的信息。在本处,我使用event.currentTarget来提取事件的目标元素。

浏览器在鼠标进入受影响的元素后立即调度悬停事件。针对弹出行为,你只想鼠标停留在元素上一段时间才能激活,以防当鼠标指针短暂通过元素但不停留在元素上时出现弹出闪烁。由于该事件不支持延迟,因此这是我需要自己实现的另一件事情。所以我打算在“鼠标进入”事件处理程序中添加一秒计时器:

app/templates/base.html:悬停延迟

  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
$(function() {        var timer = null;        $('.user_popup').hover(            function(event) {                // mouse in event handler                var elem = event.currentTarget;                timer = setTimeout(function() {                    timer = null;                    // popup logic goes here                }, 1000);            },            function(event) {                // mouse out event handler                var elem = event.currentTarget;                if (timer) {                    clearTimeout(timer);                    timer = null;                }            }        )    });

setTimeout()函数在浏览器环境中才可用。它需要两个参数,函数和毫秒单位的时间。 setTimeout()的效果是函数在给定的延迟后被调用。所以我添加了一个函数(现在是空的),将在悬停事件的一秒钟后被调用。由于JavaScript语言中的闭包机制,此函数可以访问在外部作用域中定义的变量,例如elem

我将timer对象存储在hover()调用之外定义的timer变量中,以使timer对象也可以被“mouse out”处理程序访问。我需要这么做的原因是为了获得良好的用户体验。如果用户将鼠标指针移动到其中一个用户链接中,并在移动它之前停留了半秒钟,我不希望该timer继续运行并调用显示弹出窗口的函数。所以我的鼠标移出事件处理程序检查是否有一个活动的timer对象,如果有,就取消它

07

Ajax 请求

 

Ajax请求不是一个新话题了,因为我已经在第十四章中已介绍过这个主题,来作为实时语言翻译功能。当使用jQuery时,$.ajax()函数向服务器发送一个异步请求。

我要发送到服务器的请求将具有类似 /user/<username>/popup 模式的URL,在本章开始时我已经将该URL添加到应用程序中。这个请求的响应将包含我需要在弹出窗口中插入的HTML。

关于这个请求的直接问题是我需要知道包含在URL中的“username”的值是什么。鼠标进入的事件处理函数是通用的,它将在页面中找到的所有用户链接,所以该函数需要从其上下文中确定用户名。

elem变量包含悬停事件中的目标元素,它是包裹<a>元素的<span>元素。为了提取用户名,我可以从<span>开始浏览DOM,移至第一个子元素,即<a>元素,然后从中提取文本,这就是在网址中要使用的用户名 。使用jQuery的DOM遍历函数,可以很简单地做到:

  •  
elem.first().text().trim()

 

应用于DOM节点的first()函数返回其第一个子节点。 text()函数返回节点的文本内容。该函数不会对文本进行任何修剪,例如,如果在一行中有<a>,在下一行中有文本,在另一行中有</a>text()将返回文本周围的所有空白。为了消除所有空白并只留下文本,我使用了名为trim()的JavaScript函数。

这就是我需要向服务器发出请求的所有信息:

app/templates/base.html:XHR请求

  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
 $(function() {        var timer = null;        var xhr = null;        $('.user_popup').hover(            function(event) {                // mouse in event handler                var elem = $(event.currentTarget);                timer = setTimeout(function() {                    timer = null;                    xhr = $.ajax(                        '/user/' + elem.first().text().trim() + '/popup').done(                            function(data) {                                xhr = null                                // create and display popup here                            }                        );                }, 1000);            },            function(event) {                // mouse out event handler                var elem = $(event.currentTarget);                if (timer) {                    clearTimeout(timer);                    timer = null;                }                else if (xhr) {                    xhr.abort();                    xhr = null;                }                else {                    // destroy popup here                }            }        )    });

代码中,我在外部范围中定义了一个新变量xhr。这个变量将保存我通过调用$.ajax()来初始化的异步请求对象。不幸的是,当直接在JavaScript端构建URL时,我无法使用Flask中的url_for(),所以在这种情况下,我必须显式连接URL的各个部分。


相关教程