现在我们既然有了这么帅气的页面,不如我们加点Ajax效果进去吧!修改下index.rhtml模板:
<%= link_to_remote
"Check Time",
:update => 'current_time',
:url => { :action => 'get_time' } %>
<div id= "current_time"></div>
:update => 'current_time',
:url => { :action => 'get_time' } %>
<div id= "current_time"></div>
这次改变是将link_to换成了link_to_remote, 添加了一个新的选项, :update. :update后面跟的的是HTML的标签元素的ID值,Ajax的回应会插入到这个标签中,这个例子中使用了DIV, 那么生成的HTML大概是这样:
<a href="#"
Ajax.Updater('current_time', '/chapter3/get_time',
{asynchronous:true, evalScripts:true});
return false;">Check Time </a>
< div id ="current_time" > </div>
Ajax.Updater('current_time', '/chapter3/get_time',
{asynchronous:true, evalScripts:true});
return false;">Check Time </a>
< div id ="current_time" > </div>
看看这段生成的HTML代码, 你会发现这里用到了Prototype的Ajax.Updater方法,所有的Rails中的Ajax helper实现途径都一样:都是在HTML模板中插入Ruby方法,生成Javascript代码,调用Prototype.
Ajax链接的核心机制就是 helper要在最后的 false了。
=====================================================
tip: 你也许已经注意到这里生成了一个HTML链接:href="#".从技术上来讲,这种“不链接到任何地方”的方法在实践中使用很不好的。如果用户浏览器屏蔽了Javascript, 或者一个搜索引擎正在索引页面,这个链接就变得没有意义了。所以无论何时,有可能的话,最好提供一个有用的链接,给没有Ajax支持的浏览器提供一条退路。
-
3.2.1. Callbacks
继续前进。link_to_remote提供了一种显示调用信号的方法。这样你可以在Javascript代码执行Ajax请求的生命周期中使用这个信号。例如:
<%= link_to_remote "Check Time",
:update => 'current_time',
:url => { :action => 'get_time' },
:before => "$('current_time').update('Loading...')" %>
< div id ="current_time" > </div>
:update => 'current_time',
:url => { :action => 'get_time' },
:before => "$('current_time').update('Loading...')" %>
< div id ="current_time" > </div>
加上了:before这个选项后,当点击链接之后,结果返回之前,在current_time这个标签中的内显示"loading..."这么做会让用户感觉到这个链接点击之后在工作,这种显示调用的信号可以在请求的生命周期中每个阶段使用。常见的有:before, :success, 和:failure.你可以对多个阶段的信号加以描述,来处理不同的响应情况。常用的有加载指示和错误处理显示。如下例:
<%= link_to_remote "Check Time",
:update => 'current_time',
:url => { :action => 'get_time' },
:before => "$('indicator').show( )",
:success => "$('current_time').visualEffect('highlight')",
:failure => "alert('There was an error. ')",
:complete => "$('indicator').hide( )" %>
<span id="indicator" style="display: none;">Loading...</span>
<div id="current_time"></div>
:update => 'current_time',
:url => { :action => 'get_time' },
:before => "$('indicator').show( )",
:success => "$('current_time').visualEffect('highlight')",
:failure => "alert('There was an error. ')",
:complete => "$('indicator').hide( )" %>
<span id="indicator" style="display: none;">Loading...</span>
<div id="current_time"></div>
在这个例子中,:before后面的代码说明在Ajax请求开始时,显示"Loading..."如果请求成功(意思是HTTP状态代码是200), :success在current_time这个标签内容上使用视觉效果。否则,:failure执行,给用户一个警示信息。对于任意一种情况(成果或失败),:complete 用来管理"Loading"元素是否隐藏。整套的这种可用的callback列表如表3-1所示
这是我们第一次见到Prototype的hide()和show()方法,借此机会我们可以来探讨一个问题:通过 Javascript动态的显示一个元素该怎么做? 必须在CSS中定义display: none的属性,相反在外部的stylesheet中定义就会不起作用。例如下面的代码是不会工作的:
<
style
type
="text/css"
>
#indicator { display: none; }
</style>
< div id ="indicator" >Hidden DIV </div>
< script type ="text/javascript" >
$("indicator").show( ); // won't work
</script>
#indicator { display: none; }
</style>
< div id ="indicator" >Hidden DIV </div>
< script type ="text/javascript" >
$("indicator").show( ); // won't work
</script>
下面的代码会正常工作:
<
div
id
="indicator"
style
="display: none"
>Hidden DIV
</div>
< script type ="text/javascript" >
$("indicator").show( ); // will work
</script>
< script type ="text/javascript" >
$("indicator").show( ); // will work
</script>
用同样的规则来请求任意一个JavaScript方法会改变元素的显示属性,例如Prototype的toggle()方法和script.aculo.us的可视化效果。通常情况下,把CSS规则放在外面,但是display: none是一个例外。
Table 3-1. Ajax helper的callback和相应情况的属性
------------------------------------------------------------------------------------------------------------------------
Helper callback | Prototype callback | 状态 | 描述 |
------------------------------------------------------------------------------------------------------------------------
:before | | | 请求对象还没有创建完毕 |
-----------------------------------------------------------------------------------------------------------------------
:after | | 0(未初始化) | 请求对象的open()方法未被调用 |
------------------------------------------------------------------------------------------------------------------------
:loading | onLoading | 1(正在加载) | 请求对象的send()方法未被调用 |
------------------------------------------------------------------------------------------------------------------------
:loaded | onLoaded | 2(加载完毕) | 请求已完成初始化 |
------------------------------------------------------------------------------------------------------------------------
:interactive | on Interactive | 3(交互) | 正在接收响应 |
------------------------------------------------------------------------------------------------------------------------
:success | onSuccess | | 响应就绪并且状态在200的范围 |
------------------------------------------------------------------------------------------------------------------------
:failure | onFailure | | 响应就绪但是状态不在200的范围 |
------------------------------------------------------------------------------------------------------------------------
:complete | onComplete | 4(完成) | 响应就绪 |
------------------------------------------------------------------------------------------------------------------------
3.2.2 Other Options
除了callback之外,link_to_remote还有另外一些选项来指定它的行为。首先,它也支持和link_to选项里面的:method和:confirm功能。
:condition选项和:confirm一样:允许你有选择的执行请求,这是基于一些Javascript的功能。例如:
<li><%= check_box_tag 'get_time' %> get time</li>
<%= link_to_remote "get time",
:condition => "$('get_time').checked",
:url => { :action => 'get_time' },
:update =>"current_time",
:before=> "$('indicator').show()",
:success=>"$('current_time').visualEffect('highlight')",
:complete=>"$('indicator').hide()"%>
<span id="indicator" style="display: none">Loading...</span>
<div id="current_time"></div>
:condition => "$('get_time').checked",
:url => { :action => 'get_time' },
:update =>"current_time",
:before=> "$('indicator').show()",
:success=>"$('current_time').visualEffect('highlight')",
:complete=>"$('indicator').hide()"%>
<span id="indicator" style="display: none">Loading...</span>
<div id="current_time"></div>
当点击链接后,:condition 中的表达式会执行,如果执行的返回结果是true, 那么请求继续执行(在这个case中,checkbox被选中即返回true)。
:submit选项:允许你模仿表单提交,当你提供了一个页面元素的ID时,这个元素的内容会和请求一起发送出去,这意思就是说你没必要在使用submit时,必须使用一个<form>标签,任意的标签都可以,例如div或者是tr。例如:
<
div
id
="fakeForm"
>
< input type ="text" name ="foo" value ="bar" />
</div>
<%= link_to_remote "Submit fake form",
:submit => "fakeForm",
:url => { :action => 'repeat' },
:complete => "alert(request.responseText)" %>
< input type ="text" name ="foo" value ="bar" />
</div>
<%= link_to_remote "Submit fake form",
:submit => "fakeForm",
:url => { :action => 'repeat' },
:complete => "alert(request.responseText)" %>
点击这个链接后,会扫描fakeForm DIV并且把里面的数据连带Request,通过HTTP POST发送到repeater这个action,模拟一个规则的表单提交,虽然这个过程没有<form>标签存在于页面上。这个模拟表单提交的功能在不允许嵌套表单时非常有用,使用:submit选项,你可以很轻易的在这种限制下工作。
当然,:submit选项对于表单来说也是非常有用的,当你用多种方式提交的时候。例如:
<
form
id
="myForm"
>
< input type ="text" name ="text_to_reverse" id ="text_to_reverse" />
<%= link_to_remote "Reverse field",
:url => { :action => 'reverse' },
:submit => "myForm",
:complete => "$('text_to_reverse').value=request.responseText" %>
< input type ="submit" />
</form>
< input type ="text" name ="text_to_reverse" id ="text_to_reverse" />
<%= link_to_remote "Reverse field",
:url => { :action => 'reverse' },
:submit => "myForm",
:complete => "$('text_to_reverse').value=request.responseText" %>
< input type ="submit" />
</form>
这里我们有一个规则的,没有Ajax的表单,但是"Reverse field"这个链接使用了Ajax在幕后提交表单并且利用回应改变表单中的值。
:with选项用来构建查询字段,跟request一起发送,在服务器端变成params对象。例如:
<%= link_to_remote "Link with params",
:url => { :action => 'repeat' },
:complete => "alert(request.responseText)",
:with => "'foo=bar'" %>
:url => { :action => 'repeat' },
:complete => "alert(request.responseText)",
:with => "'foo=bar'" %>
注意这里,:with的值有两个引号。这是因为它是作为Javascript表达式来执行的,这个case中,我们希望提供一个字符串表达式。这是helper的输出:
<a href="#"
new Ajax.Request('/chapter3/repeat',
{ parameters:'foo=bar',
onComplete:function(request){
alert(request.responseText)
}
}); return false;">Link with params </a>
new Ajax.Request('/chapter3/repeat',
{ parameters:'foo=bar',
onComplete:function(request){
alert(request.responseText)
}
}); return false;">Link with params </a>
在:with选项中你也可以使用Javascript变量或者DOM元素:
<input id=
"myElement" type=
"text" value=
"bar" />
<%= link_to_remote "Link with dynamic params",
:url => { :action => 'repeat' },
:complete => "alert(request.responseText)",
: with => "'foo='+escape($F('myElement'))" %>
<%= link_to_remote "Link with dynamic params",
:url => { :action => 'repeat' },
:complete => "alert(request.responseText)",
: with => "'foo='+escape($F('myElement'))" %>
在这个示例中,点击链接会将当前在myElement中的值发送出去。
3.2.2.1 Link to an arbitrary function
我们来看看link_to_remote的大哥哥link_to_function. 它的功能是生成一个执行某个Javascript功能块的链接。在index.rhtml中加入下面的代码:
<%= link_to_function
"Toggle DIV",
"$('indicator').toggle( )" %></p>
第一个参数是链接显示的文字,第二个是要执行的Javascript代码块的名字。现在这个代码块使用了Prototype的toggle()方法,这个方法实现隐藏或显示页面上的元素。它控制着我们以前创建的indicator 这个DIV标签内容。这个link_to_function的HTML是这样:
<
a
href
="#"
onclick
="$('indicator').toggle( ); return false;"
>Toggle DIV
</a>
本文转自 fsjoy1983 51CTO博客,原文链接:http://blog.51cto.com/fsjoy/91222,如需转载请自行联系原作者