没有Rails内置帮助程序使用AJAX的最佳实践?

时间:2023-01-15 20:34:50

In my blog application, some posts appear as excerpts -- i.e., the user sees the first (say) 500 characters, and can click a link to view the entire post. Here is the relevant partial:

在我的博客应用程序中,一些帖子显示为摘录 - 即,用户看到第一个(比如说)500个字符,并且可以单击链接以查看整个帖子。以下是相关部分:

<% href = url_for post_path(:id => post) %>

<h1 class="title"><%= post.title %></h1>
<h2 class="published_on"><%= post.author %> wrote this <%= time_ago_in_words(post.published_on)%> ago</h2>
<div class="body">
  <% if defined?(length) %>
    <%= truncate_html(post.body, :length => length, :omission => "&hellip;<h1><a class='more' href=\"#{href}\">Click here for more!</a></h1>") %>
  <% else %>
    <%= post.body %>
  <% end %>
</div>

However, instead of "Click here for more!" taking the user to a separate page, I'd like it to populate the rest of the post inline. Currently, I've been implementing this by putting the above snippet in the following div:

但是,而不是“点击此处了解更多!”将用户带到一个单独的页面,我希望它能够填充内联的其余部分。目前,我已经通过将上面的代码片段放在以下div中来实现这一点:

<div class="post" id="post_<%= post.id %>">
  <%= render :partial => 'post_content', :locals => { :post => post, :length => 500 } %>
</div>

I then use the id of this div in my application.js to do the AJAX:

然后我在我的application.js中使用这个div的id来做AJAX:

$(document).ready(function() {

  $("a.more").click(function() {
    var url = $(this).attr('href');
    var id = url.split("/")[2]
    $.get(url, null, function(data) {
      $("#post_" + id).html(data);     
    });
    return false;
  });

});

This is obviously disgusting -- I don't want my javascript to depend on the location of the post's id in the link's href, but I don't know any other way for the javascript to know which post it is getting and therefore into which div the content should be inserted.

这显然很恶心 - 我不希望我的javascript依赖于链接的href中帖子id的位置,但是我不知道javascript知道哪个帖子得到的任何其他方式因此div应该插入内容。

What's the best way to accomplish this? Should I just go back to using rails' AJAX helpers?

实现这一目标的最佳方法是什么?我应该回到使用rails的AJAX助手吗?

3 个解决方案

#1


7  

Horace, you are correct. You don't need the Rails helpers at all. To achieve unobtrusive JavaScript Nirvana, you will do well to avoid them (sorry Marc!)

霍勒斯,你是对的。你根本不需要Rails助手。为了实现不引人注目的JavaScript Nirvana,你最好避免它们(对不起Marc!)

Unobstrusive JS means avoiding embedded JS where possible. Indeed, try to keep things loosely coupled, but not entirely decoupled. In the example you gave us, it is easy, because we have a URL from the HREF to work with. Your JS does not need to "know" anything about how to request.

不引人注目的JS意味着尽可能避免使用嵌入式JS。实际上,尽量保持松散耦合,但不要完全脱钩。在您给我们的示例中,这很容易,因为我们有一个来自HREF的URL可以使用。您的JS不需要“知道”有关如何请求的任何信息。

Here is how to send through the link from the HREF's blindly, and get Rails to respond with an ajax response (i.e. no layout).

以下是如何通过HREF盲目发送链接,并让Rails响应ajax响应(即没有布局)。

SOLUTION:

<!------- Your HTML ------>
<h1 class="title">Schwein Flu Strikes Again</h1>
<h2 class="published_on">B.Obama wrote this 2 seconds ago</h2>
<div class="body">
    SUMMARY SUMMARY
    <h1><a class='more' href="/post/1234">Click here for more!</a></h1>
</div>
/********* Your JavaScript ***********/
$(document).ready(function() {

$("a.more").click(function() { $containing_div = $(e).parents('div.body'); var url = $(this).attr('href'); $.ajax({ beforeSend : function(request) { request.setRequestHeader("Accept", "text/javascript"); }, /* Included so Rails responds via "format.js" */ success : function(response) { $(containing_div).empty.append(response); }, type : 'get', url : url }); return false; });

$(“a.more”)。click(function(){$ containing_div = $(e).parents('div.body'); var url = $(this).attr('href'); $ .ajax ({beforeSend:function(request){request.setRequestHeader(“Accept”,“text / javascript”);},/ *包含所以Rails通过“format.js”响应* / success:function(response){$(containing_div ).empty.append(response);},type:'get',url:url}); return false;});

});

########### Your Controller ###########
def show
  @article = Post.find(param[:id])
  respond_to do |format|
    format.html { render :action => "show" and return  }
    format.js { render :partial => "post_content", :layout => false and return }
  end
end

This also assumes you have RESTful routes or similar to handle /post/:id

这也假设你有RESTful路由或类似handle / post /:id

And we're done! I believe there is something in that for all of us. :D

我们完成了!我相信对我们所有人来说都有一些东西。 :d

#2


1  

In this case, I don't think you should have the AJAX call at all. You already have the original post's entire content in post.body (you didn't fetch just the 500 characters from the db) Instead of using JQuery to make an ajax call, use it to hide the content past 500 characters and then when the user clicks the 'more' link it shows the rest of the div. You can do this entirely on the client side and save yourself the ajax.

在这种情况下,我认为你根本不应该进行AJAX调用。你已经在post.body中拥有了原始帖子的全部内容(你没有从db中获取500个字符)而不是使用JQuery进行ajax调用,使用它来隐藏超过500个字符的内容然后当用户点击“更多”链接,它会显示div的其余部分。您可以在客户端完全执行此操作并保存自己的ajax。

In your partial:

在你的部分:

<div class="body">
  <%= post.body %>
</div>

Your JQuery:

var fullText = $('div.body').html();
$('div.body').html(fullText.slice(0,499) + '<a class="more" href=\"#\">Click here for more!</a>');
$('a.more').live('click', function(event) {
  this.parent().html(fullText);
  return false;
}

#3


0  

In my opinion for this kind of problems you should use rails' helpers.

在我看来,对于这类问题你应该使用rails的助手。

HTML would go like :

HTML会像:

My post bla bla bla <span id="more_of<%=post.id%>">more</span>

The more link would be :

链接越多:

<%= link_to_remote( "more",:update => "more_of_#{your_post.id}",:url =>{:controller => "myposts", :action=>"show_more", :id => your_post.id}, %>

And the controller would do something like :

控制器会做类似的事情:

post = Post.find_by_id(params[:id])
render :text => post.content.slice(100..post.content.size) 

The other way that could be just as good is to load everything and then hide it :

另一种可能同样好的方法是加载所有内容然后隐藏它:

bla bla bla this is my post blah <div style="display:none" onclick="this.style.display='block';">and this is the rest of the article</div>

(the onclick on a div tag might break in IE but this is to give you the idea)

(关于div标签的onclick可能会在IE中中断,但这是为了给你这个想法)

To me that would be the best way to go unless you have a good reason of avoiding rails' helpers.

对我来说这将是最好的方式,除非你有充分的理由避免铁路的助手。

Hope that helps

希望有所帮助

#1


7  

Horace, you are correct. You don't need the Rails helpers at all. To achieve unobtrusive JavaScript Nirvana, you will do well to avoid them (sorry Marc!)

霍勒斯,你是对的。你根本不需要Rails助手。为了实现不引人注目的JavaScript Nirvana,你最好避免它们(对不起Marc!)

Unobstrusive JS means avoiding embedded JS where possible. Indeed, try to keep things loosely coupled, but not entirely decoupled. In the example you gave us, it is easy, because we have a URL from the HREF to work with. Your JS does not need to "know" anything about how to request.

不引人注目的JS意味着尽可能避免使用嵌入式JS。实际上,尽量保持松散耦合,但不要完全脱钩。在您给我们的示例中,这很容易,因为我们有一个来自HREF的URL可以使用。您的JS不需要“知道”有关如何请求的任何信息。

Here is how to send through the link from the HREF's blindly, and get Rails to respond with an ajax response (i.e. no layout).

以下是如何通过HREF盲目发送链接,并让Rails响应ajax响应(即没有布局)。

SOLUTION:

<!------- Your HTML ------>
<h1 class="title">Schwein Flu Strikes Again</h1>
<h2 class="published_on">B.Obama wrote this 2 seconds ago</h2>
<div class="body">
    SUMMARY SUMMARY
    <h1><a class='more' href="/post/1234">Click here for more!</a></h1>
</div>
/********* Your JavaScript ***********/
$(document).ready(function() {

$("a.more").click(function() { $containing_div = $(e).parents('div.body'); var url = $(this).attr('href'); $.ajax({ beforeSend : function(request) { request.setRequestHeader("Accept", "text/javascript"); }, /* Included so Rails responds via "format.js" */ success : function(response) { $(containing_div).empty.append(response); }, type : 'get', url : url }); return false; });

$(“a.more”)。click(function(){$ containing_div = $(e).parents('div.body'); var url = $(this).attr('href'); $ .ajax ({beforeSend:function(request){request.setRequestHeader(“Accept”,“text / javascript”);},/ *包含所以Rails通过“format.js”响应* / success:function(response){$(containing_div ).empty.append(response);},type:'get',url:url}); return false;});

});

########### Your Controller ###########
def show
  @article = Post.find(param[:id])
  respond_to do |format|
    format.html { render :action => "show" and return  }
    format.js { render :partial => "post_content", :layout => false and return }
  end
end

This also assumes you have RESTful routes or similar to handle /post/:id

这也假设你有RESTful路由或类似handle / post /:id

And we're done! I believe there is something in that for all of us. :D

我们完成了!我相信对我们所有人来说都有一些东西。 :d

#2


1  

In this case, I don't think you should have the AJAX call at all. You already have the original post's entire content in post.body (you didn't fetch just the 500 characters from the db) Instead of using JQuery to make an ajax call, use it to hide the content past 500 characters and then when the user clicks the 'more' link it shows the rest of the div. You can do this entirely on the client side and save yourself the ajax.

在这种情况下,我认为你根本不应该进行AJAX调用。你已经在post.body中拥有了原始帖子的全部内容(你没有从db中获取500个字符)而不是使用JQuery进行ajax调用,使用它来隐藏超过500个字符的内容然后当用户点击“更多”链接,它会显示div的其余部分。您可以在客户端完全执行此操作并保存自己的ajax。

In your partial:

在你的部分:

<div class="body">
  <%= post.body %>
</div>

Your JQuery:

var fullText = $('div.body').html();
$('div.body').html(fullText.slice(0,499) + '<a class="more" href=\"#\">Click here for more!</a>');
$('a.more').live('click', function(event) {
  this.parent().html(fullText);
  return false;
}

#3


0  

In my opinion for this kind of problems you should use rails' helpers.

在我看来,对于这类问题你应该使用rails的助手。

HTML would go like :

HTML会像:

My post bla bla bla <span id="more_of<%=post.id%>">more</span>

The more link would be :

链接越多:

<%= link_to_remote( "more",:update => "more_of_#{your_post.id}",:url =>{:controller => "myposts", :action=>"show_more", :id => your_post.id}, %>

And the controller would do something like :

控制器会做类似的事情:

post = Post.find_by_id(params[:id])
render :text => post.content.slice(100..post.content.size) 

The other way that could be just as good is to load everything and then hide it :

另一种可能同样好的方法是加载所有内容然后隐藏它:

bla bla bla this is my post blah <div style="display:none" onclick="this.style.display='block';">and this is the rest of the article</div>

(the onclick on a div tag might break in IE but this is to give you the idea)

(关于div标签的onclick可能会在IE中中断,但这是为了给你这个想法)

To me that would be the best way to go unless you have a good reason of avoiding rails' helpers.

对我来说这将是最好的方式,除非你有充分的理由避免铁路的助手。

Hope that helps

希望有所帮助