`
guanhuaing
  • 浏览: 1196250 次
文章分类
社区版块
存档分类
最新评论

第八天-Ajax交互

 
阅读更多
Symfony回顾

在七个小时的工作之后,askeet程序已经很好了。主页显示问题列表,问题的详细内容显示其答案,用户具有一个配置页面,而各种主题列表也可以由每一页的侧边栏访问。我们社区加强的FAQ处在其正确的方向上,而现在用户还不可以修改数据。

如果web中数据操作的基础是长长的表单,那么今天的AJAX技术可以改变程序的构建方式。而这也同样适用于askeet。在这个指南中,我们将会显示在askeet中添加加强的AJAX交互。其目标就是允许一个已注册的用户声明其对某一个问题的兴趣。

在布局中添加一个指示器

当一个异步请求发送时,AJAX网站的用户并不需要考虑通常的动作暂停,而结果会很快显示。这就是所有的AJAX交互页面应能够可以显示一个活动的指示器的原因。

正因为如此,在全局的layout.php的<body>顶部添加下面的代码行:

<div id="indicator" style="display: none"></div>

尽管默认情况下这是隐藏的,但是当AJAX请求发送时,<div>就会显示。他是空的,但是main.css样式表指定其形状与内容:

div#indicator
{
position: absolute;
width: 100px;
height: 40px;
left: 10px;
top: 10px;
z-index: 900;
background: url(/images/indicator.gif) no-repeat 0 0;
}

添加AJAX交互来声明兴趣

一个AJAX交互由三部分组成:调用者(一个链接,一个按钮或者是其他的用户启动动作的控件),一个服务器动作,以及页面中向用户显示动作结果的区域。

调用者

让我们回到显示的问题。如果我们还记得第四天,一个问题可以在一个问题列表中显示,也可以在问题详细中显示。

这就是将问题标题与兴趣块重构到一个_interested_user.php片段中的原因。再次打开这个片段,添加一个链接允许用户声明其兴趣:

<?php use_helper('User') ?>

<div class="interested_mark" id="mark_<?php echo $question->getId() ?>">
<?php echo $question->getInterestedUsers() ?>
</div>

<?php echo link_to_user_interested($sf_user, $question) ?>

这个链接所做的不仅是重定向到另一个页面。事实上,如果一个用户已经指定了其对某一个问题的兴趣,他就不可以再一次声明。而且如果这个用户没有被认证,呃,这将是我们后面要讨论的情况。

这个链接是在一个帮助器函数中编写的,这就需要在askeet/apps/frontend/lib/helper/UserHelper.php中创建:

<?php

use_helper('Javascript');

function link_to_user_interested($user, $question)
{
if ($user->isAuthenticated())
{
$interested = InterestPeer::retrieveByPk($question->getId(), $user->getSubscriberId());
if ($interested)
{
// already interested
return 'interested!';
}
else
{
// didn't declare interest yet
return link_to_remote('interested?', array(
'url' => 'user/interested?id='.$question->getId(),
'update' => array('success' => 'block_'.$question->getId()),
'loading' => "Element.show('indicator')",
'complete' => "Element.hide('indicator');".visual_effect('highlight', 'mark_'.$question->getId()),
));
}
}
else
{
return link_to('interested?', 'user/login');
}
}

?>

link_to_remote()函数是AJAX交互的第一个元素:调用者。他声明了当用户点击链接时必须请求哪个动作(在这里为user/interested)以及页面中的哪个区域必须使用动作结果进行更新。两个事件处理器(loding与complete)被添加进来并且与原型javascript函数相关联。原型库提供了手动的javascript工具来使用简单的函数调用实现页面中的可视效果。唯一的不足是文档的缺乏,但是源码是相当直接的。

我们选择使用帮助器而不是partial,是因为这个函数的PHP代码要多于HTML代码。

不要忘记在question/_list片段中添加id id="block_<?php echo $question->getId() ?>"。

<div class="interested_block" id="block_<?php echo $question->getId() ?>">
<?php include_partial('interested_user', array('question' => $question)) ?>
</div>

结果区域

link_to_remote() javascript帮助器的update属性指定了结果区域。在这个例子中,user/interested动作的结果将会替换id为block_XX的元素的内容。如果我们还感到迷惑,我们可以查看一下这个模板片段中所集成的内容:

...
<div class="interested_block" id="block_<?php echo $question->getId() ?>">
<!-- between here -->
<?php use_helper('User') ?>
<div class="interested_mark" id="mark_<?php echo $question->getId() ?>">
<?php echo $question->getInterestedUsers() ?>
</div>
<?php echo link_to_user_interested($sf_user, $question) ?>
<!-- and there -->
</div>
...

两段注释的中间区域即为结果区域。这个动作一旦执行,就会替换这些内容。

第二个id(mark_XX)的兴趣是十分明显的。link_to_remote帮助器的完整事件处理器将高亮显示已点击的兴趣的interested_mark <div>层,在动作返回一个兴趣的增量数。

服务器动作

AJAX调用器指向user/interested动作。这个动作必须在Interest表中为当前的问题以及当前的用户创建新的记录。在Symfony中我们可以这样来做:

public function executeInterested()
{
$this->question = QuestionPeer::retrieveByPk($this->getRequestParameter('id'));
$this->forward404Unless($this->question);

$user = $this->getUser()->getSubscriber();

$interest = new Interest();
$interest->setQuestion($this->question);
$interest->setUser($user);
$interest->save();
}

在这里我们要记住,Interest对象的->save()方法已经被修改来增加相关用户的interested_user域。所以对于当前问题感兴趣的用户数目会在动作调用之后自动增加。

那么结果的interestedSuccess.php模板应如何显示呢?
<?php include_partial('question/interested_user', array('question' => $question)) ?>

他会再一次显示问题模块的_interested_user.php片段。这就是我们编写这个片段的最大好处。

我们必须禁止这个模板的布局(modules/user/config/view.yml):

interestedSuccess:
has_layout: off

最终测试

AJAX兴趣的开发到现在就结束了。我们可以进行相应的测试,在登陆页面输入已存在的用户名与密码,显示问题列表,并且点击'interested?'链接。当请求发往服务器时就会显示指示器。然后,当服务器应答后增加的数目就会高亮显示。我们可以注意到初始的'interested?'链接现在变为'interested'并且没有链接,这样就是我们的link_to_interested帮助器所起的作用。

添加一个内联'sign-in'表单

我们在前面说到只有注册用户可以声明对某一个问题的兴趣。这就意味着如果一个未授权的用户点击一个'interested?'链接时,必须首先显示登陆页面。

但是等一下。为什么用户要装入一个新的页面来登陆,而失去与他所声明的感兴趣的问题失去联系呢?一个更好的办法就是在页面上动态装入一个登陆页面。这就是我们将要做的工作。

在布局中添加一个隐藏登陆表单

打开全局布局(askeet/apps/frontend/templates/layout.php),添加下面的代码(header与content div之间的内容):

<?php use_helper('Javascript') ?>

<div id="login" style="display: none">
<h2>Please sign-in first</h2>

<?php echo link_to_function('cancel', visual_effect('blind_up', 'login', array('duration' => 0.5))) ?>

<?php echo form_tag('user/login', 'id=loginform') ?>
nickname: <?php echo input_tag('nickname') ?><br />
password: <?php echo input_password_tag('password') ?><br />
<?php echo input_hidden_tag('referer', $sf_params->get('referer') ? $sf_params->get('referer') : $sf_request->getUri()) ?>
<?php echo submit_tag('login') ?>
</form>
</div>

再一次说明,这个表单默认是隐藏的。referer隐藏标记包含referer请求参数,或者是当前的URI。

当非授权用户点击interested链接时显示表单

我们还记得在前面编写的User帮助器吗?现在我们将要来处理非授权用户的情况。打开askeet/lib/helper/UserHelper.php文件,将下面的代码行:

return link_to('interested?', 'user/login');return link_to('interested?', 'user/login');

改为:

return link_to_function('interested?', visual_effect('blind_down', 'login', array('duration' => 0.5)));

当用户为非授权时,'interested?'上的链接会载入一个原型javascript效果(blind_down)来为login id留出空间。

登陆用户

user/login动作已经在第五天编写完成了,并且在第六天进行了重构。我们需要再一次进行修改。

public function executeLogin()
{
if ($this->getRequest()->getMethod() != sfRequest::POST)
{
// display the form
$this->getRequest()->getParameterHolder()->set('referer', $this->getRequest()->getReferer());

return sfView::SUCCESS;
}
else
{
// handle the form submission
// redirect to last page
return $this->redirect($this->getRequestParameter('referer', '@homepage'));
}
}

现在的工作已经很完美了,保存的referer将会用户重定向到用户点击以前所在的页面。

现在测试AJAX功能。一个未注册的用户点击时将会显示一个登陆页面而不离开当前页面。如果用户名与密码通过了认证,页面会进行刷新,用户可以点击他之前想要点击的'interested?'链接。

明天见
分享到:
评论

相关推荐

    医疗病历交互系统-医疗病历交互系统的设计与实现代码-java-springboot-代码-源码-项目-系统-毕设-网站-代码

    医疗病历交互系统-医疗病历交互系统的设计与实现代码-java-springboot-基于springboot的医疗病历交互系统项目-代码-源码-项目-系统-毕设-网站 1、技术栈:java,springboot,vue,ajax,maven,mysql,MyBatisPlus等 ...

    医疗病历交互系统的设计与实现代码-java-springboot-基于springboot的医疗病历交互系统项目-代码-源码

    医疗病历交互系统的设计与实现代码-java-springboot-基于springboot的医疗病历交互系统项目-代码-源码-项目-系统-毕设-网站 1、技术栈:java,springboot,vue,ajax,maven,mysql,MyBatisPlus等 2、系统的实现 ...

    java-springboot-基于springboot的医疗病历交互系统项目-代码-源码-项目-系统-毕设-网站-代码

    java-springboot-基于springboot的医疗病历交互系统项目-代码-源码-项目-系统-毕设-网站 1、技术栈:java,springboot,vue,ajax,maven,mysql,MyBatisPlus等 2、系统的实现 用户信息 图片素材 视频素材 摘 要 I ...

    jQuery教程学习

    第一章:基础篇 - 对象的获取 第一节:jQuery速成 - 向jQuery进军!...第八章:高级篇 - Ajax异步请求及调用实战 第三十三节:jQuery速成- Ajax请求 (讲解篇) 第三十四节:jQuery速成- Ajax请求 (实战篇)

    Ajax基础教程(扫描版)

    第8章 万事俱备 209 8.1 模式介绍 209 8.1.1 实现褪色技术 209 8.1.2 实现自动刷新 210 8.1.3 实现部分页面绘制 210 8.1.4 实现可拖放dom 211 8.2 避免常见的陷阱 212 8.3 相关的更多资源 214 8.4 使用框架 ...

    基于springboot的医疗病历交互系统项目-代码-源码-项目-系统-毕设-网站-代码

    基于springboot的医疗病历交互系统项目-代码-源码-项目-系统-毕设-网站 1、技术栈:java,springboot,vue,ajax,maven,mysql,MyBatisPlus等 2、系统的实现 用户信息 图片素材 视频素材 摘 要 I 目 录 III 第1章 ...

    【卷一/共两卷】AJAX实战pdf高清版90M

    第8章 性能 8.1 什么是性能? 8.2 JavaScript的执行速度 8.2.1 测定应用时间的艰难方式 8.2.2 使用Venkman性能分析器 8.2.3 优化Ajax应用的执行速度 8.3 JavaScript的内存使用量 8.3.1 避免内存泄漏 8.3.2 Ajax的特殊...

    原创-javascript服务器交互型可编辑表格和我的js常用库

    自己常用的js库和写的一个交互型可编辑表格: BaseJs库的一点源码: /** * 自定义javascript常用基础库 author zhang_jhai 创建时间 2010/04/10 最后修改时间 2010/05/03 * version 2.0 */ // Base库基础类 BaseJs ...

    JavaScript & jQuery 交互式Web前端开发

    更高效的学习JavaScript和jQuery,快速成为一名Web前端工程师,零基础快速掌握 作者:(美)达科特(Duckett, J.)出版社:...第8章 Ajax与JSON 第9章 API 第10章 错误处理与调试 第11章 内容面板 第12章 筛选、搜索与排序

    Ajax详解.rar

    Ajax 由 HTML、JavaScript™ 技术、DHTML 和 DOM 组成,这一杰出的方法可以将笨拙的 Web 界面转化成交互性的 Ajax 应用程序。本系列的作者是一位 Ajax 专家,他演示了这些技术如何协同工作 —— 从总体概述到细节的...

    PHP培训教程之AJAX技术.docx

    7、AJAX请求总共有多少种CALLBACK Ajax请求总共有八种Callback onSuccess onFailure onUninitialized onLoading onLoaded onInteractive onComplete onException 8.Ajax和javascript的区别 javascript一种在浏览器端...

    [PDF]Ajax.基礎教程

    內容提要: Ajax技術可以提供高度交互的Web應用,給予用戶更豐富的頁面瀏覽體驗。本書重點介紹Ajax及相關的工具和技術,主要內容包括XMLHttpRequest...第8章 萬事俱備 附錄A 開發跨瀏覽器JavaScript 附錄B Ajax框架介紹

    1905-may28-sps-repository:批次储存库

    批次储存库 ... 第八周:春天我们学习的最后一个Java框架 第9周:Web服务和微服务REST,SOAP,Zuul,Eureka,Docker ... 第10-12周:项目3 批处理范围内的项目,我们在内部项目的另一个迭代中进行工作

    javascript服务器交互型可编辑表格和js常用库

    自己常用的js库和写的一个交互型可编辑表格: new BaseJs.EditTable({ // 表对象 table : BaseJs.$("tab"), // 从第几行第几列开始可编辑 start : [2, 1], // 到哪一行哪一列结束编辑 不写默认所有,写一个...

    ExtAspNet v2.2.1 (2009-4-1) 值得一看

    -Button控件将不再自动拥有display:inline属性,如果希望两个按钮在一行显示,请为第一个按钮设置CssStyle="float:left;"属性。 -修正了弹出菜单的位置在Firefox下不正确的BUG(feedback:eroach)。 -为TriggerBox...

    最新Python3.5零基础+高级+完整项目(28周全)培训视频学习资料

    第8周 上节回顾 Socket实现简单的ssh客户端 Socket实现简单的ssh服务端 积极思考正能量 Socket实现简单的ssh2 Socket粘包 Socket粘包深入编码 SocketServer SocketServer多并发 多用户在线Ftp程序 第9周 上节回顾...

    ASP.NET 2.0网络开发详解 源代码 和Net电子书

    第8章 XML编程 第9章 应用程序部署 第10章 时间跟踪系统 4.dot NET学习电子书\dot NET数据库开发技术(154页) 第1章 操作数据库 第2章 使用数据库 第3章 使用数据绑定和DataSet 第4章 SQL Server XML的功能 第5章 ...

    vue.js视频教程及源码(二)

    第八节:vue计算属性 第九节:vue监视属性 第十节:vue样式属性Class与Style绑定 第十一节:vue事件处理器 第十二节:vue表单处理 第十三节:vue生命周期 第十四节:vue-cli脚手架安装 第十五节:基于vue-cli搭建...

    vue.js视频教程及源码(一)

    第八节:vue计算属性 第九节:vue监视属性 第十节:vue样式属性Class与Style绑定 第十一节:vue事件处理器 第十二节:vue表单处理 第十三节:vue生命周期 第十四节:vue-cli脚手架安装 第十五节:基于vue-cli搭建...

    PHP Web开发学习实录PDF下载

    PHP应用篇包括第9-13章,介绍了PHP与MySQL数据库之间的交互、PHP的安全技术、与XML的交互、Smarty技术和与Ajax之间的交互等技术;PHP实例篇包括第15-16章,分别介绍了企业宣传网和电子商务网的开发技术。网站...

Global site tag (gtag.js) - Google Analytics