2009-04-29 6 views
3

In meiner Blog-Anwendung erscheinen einige Posts als Auszüge - d. H. Der Benutzer sieht die ersten (sagen wir) 500 Zeichen und kann auf einen Link klicken, um den gesamten Post anzuzeigen. Hier ist der relevante Teil:Best Practices für die Verwendung von AJAX ohne integrierte Rails-Helfer?

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

Jedoch statt "Hier klicken für mehr!" Wenn ich den Benutzer auf eine separate Seite bringe, möchte ich, dass der Rest des Posts in die Zeile eingefügt wird. Zur Zeit habe ich das schon Umsetzung durch das obige Snippet in der folgenden div setzen:

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

ich dann die ID des div in meinem application.js verwenden, um die AJAX zu tun:

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

}); 

Das ist offensichtlich ekelhaft - ich möchte nicht, dass mein Javascript von der Position der ID des Beitrags in der href des Links abhängt, aber ich weiß keine andere Möglichkeit, dass das Javascript weiß, welchen Beitrag es bekommt und daher in welchen div sollte der Inhalt eingefügt werden.

Was ist der beste Weg, dies zu erreichen? Sollte ich einfach wieder AJAX-Helfer von Rails benutzen?

+0

Warum Sie keine Schienen Helfer verwenden? – marcgg

+0

Halten Sie mein Javascript unauffällig/aus der Präsentationslogik heraus? Auf der anderen Seite könnte es die am wenigsten schlechte Option sein. Wenn "die Schienenhelfer benutzen" die Antwort ist, dann sei es so. –

+0

Ich gab Ihnen zwei Lösungen mit oder ohne Schienen Helfer – marcgg

Antwort

7

Horace, Sie sind richtig. Sie brauchen die Rails-Helfer überhaupt nicht. Um unaufdringliches JavaScript Nirvana zu erreichen, werden Sie es gut tun, sie zu vermeiden (tut mir leid, Marc!)

Unobtrusive JS bedeutet, Embedded JS wo möglich zu vermeiden. Versuchen Sie in der Tat, die Dinge lose gekoppelt zu halten, aber nicht vollständig entkoppelt. In dem Beispiel, das Sie uns gegeben haben, ist es einfach, weil wir eine URL vom HREF haben, mit der wir arbeiten können. Ihr JS muss nichts darüber wissen, wie es angefordert wird.

Hier ist, wie über den Link von den HREF blind zu senden, und erhalten Sie Schienen mit einer Ajax-Antwort (d. H. Kein Layout) zu reagieren.

LÖSUNG:

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

Dies auch vorausgesetzt, dass Sie RESTful Routen oder ähnlich zu handhaben/post/haben: id

Und wir sind fertig! Ich glaube, da ist etwas für uns alle. : D

+0

Danke - das Ziel für die Einfügung durch Iterieren durch die Eltern des Ankers ist der Trick, den ich suchte. (In der Praxis möchten Sie wahrscheinlich den "setRequestHeader" -Stuff als Teil eines ajaxSetup-Aufrufs tun, so dass Sie ihn nur einmal ausführen müssen). –

+0

Hallo Horace, ich stimme deinem Kommentar über den AjaxSetup Anruf zu, aber in meiner App war es nicht gut, also nahm ich es heraus. Ich werde es nochmal untersuchen müssen. Viel Glück mit Ihrer App, und viva la unaufdringlichen JS! – pchap10k

0

Meiner Meinung nach sollten Sie für diese Art von Problemen die Helfer der Schienen benutzen.

HTML gehen würde wie:

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

Je mehr Link wäre:

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

Und der Controller würde wie etwas tun:

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

Die andere Art und Weise, die sein könnte genauso gut ist es, alles zu laden und dann zu verstecken:

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> 

(das Onclick auf einem div-Tag könnte in IE brechen, aber das ist Ihnen die Idee zu geben)

mir, dass der beste Weg wäre, zu gehen, wenn Sie einen guten Grund zu vermeiden Schienen Helfer.

Hoffe, dass hilft

1

In diesem Fall denke ich nicht, dass Sie den AJAX-Aufruf überhaupt haben sollten. Sie haben bereits den gesamten Inhalt des ursprünglichen Posts in post.body (Sie haben nicht nur die 500 Zeichen aus der db abgerufen) Anstatt JQuery für einen Ajax-Aufruf zu verwenden, verwenden Sie ihn, um den Inhalt nach 500 Zeichen und dann beim Benutzer auszublenden klickt auf den 'mehr' Link, der den Rest des divs anzeigt. Sie können dies vollständig auf der Clientseite tun und sich den Ajax sparen.

In Ihrem Teil:

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

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