3

在我的博客应用程序中,一些帖子显示为摘录——即,用户看到前 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>

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

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

然后我在 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.

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

4

3 回答 3

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!)

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.

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).

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; });

});

########### 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

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

于 2009-05-02T16:50:03.297 回答
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.

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;
}
于 2011-06-18T06:54:22.173 回答
0

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

HTML would go like :

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)

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

Hope that helps

于 2009-04-29T18:48:40.057 回答