ACHTUNG. Das ist ein Archiv des alten forum.ruby-portal.de. Die aktuelle Mailingliste gibt es auf lists.ruby-lang.org/pipermail/ruby-de.

NOTICE. This is a ready-only copy of the old forum.ruby-portal.de. You can find the current mailing list at lists.ruby-lang.org/pipermail/ruby-de.

Die Programmiersprache Ruby

Blog|

Forum|

Wiki  


Alle Zeiten sind UTC + 1 Stunde [ Sommerzeit ]

Ein neues Thema erstellen Auf das Thema antworten  [ 11 Beiträge ] 
Autor Nachricht
 Betreff des Beitrags: Rails Daten an JavaScript reichen
BeitragVerfasst: 13 Apr 2013, 17:55 
Offline
Geselle

Registriert: 18 Dez 2012, 19:44
Beiträge: 140
In meinem Konkreten Fall habe ich auf der Übersichtsseite eines Spieleeitnrages die Durchschnittswertung, die sich aus der Einzelwertung mehrerer User ergibt




<%= @game.ratings.average(:value) %>


Ich will den Wert grafisch aufhübschen und in einer Art Balkendiagramm wiedergeben. Dazu muss ich den Wert in JavaScript aufrufen können, doch wie genau geht das?

Ich habe den railscast zum Thema gesehen, doch irgendwie hat er mich eher verwirrt.
Ich probiere es mit dem gon Gem, doch wenn ich versuche eine im Controller definierte Variable über jQuery auszugeben ($(".avg").replaceWith("gon.bla");) klappt das nicht, da bleibt der text in der avg klasse unverändert :/

Was wäre denn der simpelste weg (vllt sogar ohne zusatz gem) den von mir gewünschten Wert in javascript verwenden zu können?

Ich freue mich auf eure Tips!


Nach oben
 Profil  
 
BeitragVerfasst: 13 Apr 2013, 19:14 
Offline
Interpreter
Benutzeravatar

Registriert: 21 Mai 2007, 11:30
Beiträge: 1283
Wohnort: Thüringen
Irgendwie denkst du zu kompliziert. Du renderst von Ruby aus eine HTML-Datei. Render doch einfach deine Variable als Javascript da rein.




<script type="application/javascript">var average = <%= @deine_ruby_variable %>;</script>


Du kannst deine Rubyvariable natürlich auch in JSON übersetzen (z.B. falls sie nicht numerisch ist). JSON ist auch gleichzeitig valider Javascript-Code.

Alternativ kannst du den Inhalt deiner Rubyvariable auch in einen HTML Tag einpflanzen.


1
2
3
<div class="balkendiagram" data-average="<%= @deine_ruby_variable %>">

</div>

Den Inhalt kannst du dann von Javascript auslesen lassen.


Nach oben
 Profil  
 
BeitragVerfasst: 13 Apr 2013, 22:49 
Offline
Geselle

Registriert: 18 Dez 2012, 19:44
Beiträge: 140
ah tatsache, so funktioniert es bei mir. Also doch einfacher, als ich dachte.
Also die erste Variante funktioniert, aber bei der Einpflanzung in den html tag, verstehe ich noch nicht ganz wie ich den Wert auslesen lassen kann.

Ich nehme an bei "data-average" ist "average" die selbst definierte variable, die in JS nun verwendet werden kann.

Ich versuche es testweise mit der Funktion $(".balkendiagram").html(average); aber da erhalte ich keine Ausgabe :/


Danke jedenfalls für den Tipp, aber verstößt das eigentlich nicht gegen die Rails 3 Konvention "Unobtrusive JavaScript" ?


Nach oben
 Profil  
 
BeitragVerfasst: 13 Apr 2013, 23:05 
Offline
Metaprogrammierer

Registriert: 20 Nov 2011, 21:51
Beiträge: 693
Unobtrusive JavaScript bedeutet eigentlich nur, dass die Seite auch ohne JavaScrpt nutzbar ist, allerdings die Verfügbarkeit von JavaScript einen gewissen Mehrwert bietet.

UJS wäre erfüllt wenn du ohne JS deine Rankingbuttons nutzen könntest, aber für jedes Abstimmen einen kompletten Page-Reload auslöst, mit verfügbarem JS aber eben nur den entsprechenden Teil der Seite neu lädst.

_________________
Ubuntu Gnome 14.04 LTS
rvm mit App-spezifischer Ruby-Version (meist 2.2.x) und -Gemset

Github ProfilBitbucket Profil


Nach oben
 Profil  
 
BeitragVerfasst: 13 Apr 2013, 23:24 
Offline
Geselle

Registriert: 18 Dez 2012, 19:44
Beiträge: 140
ok dann noch eine weitere Frage.

Mein bewertungssystem läuft ja über ajax. Wenn ich eine wertung abgebe passt sich der numerische Durchschnittswert sofort an.

Meinen Bewertungsbalken manipuliere ich wie folgt:



1
2
3
4
5

var avg_width = (average/5)*200;

$(".rating_filled").css("width", avg_width);



(die maximal größe des balkens beträgt 200px und es gibt eine wertung von 1 bis 5)

Jedenfalls erscheint der gefüllte Balken nur bei einem kompletten seiten refresh. Wenn ich bewerte verschwindet zunächst der Balken und erscheint eben erst (mit aktualisierter länge) nach dem refresh.

Also die html, die den balken erzeugt befindet sich im selben partial, wie die anderen zu refreshenden Werte bei einem ajax post. Anscheinend wird die Variable dabei nicht übergeben, oder woran kann das liegen?

den javaScript Tag habe ich im game#show


Nach oben
 Profil  
 
BeitragVerfasst: 14 Apr 2013, 01:22 
Offline
Interpreter
Benutzeravatar

Registriert: 21 Mai 2007, 11:30
Beiträge: 1283
Wohnort: Thüringen
Zitat:
Also die erste Variante funktioniert, aber bei der Einpflanzung in den html tag, verstehe ich noch nicht ganz wie ich den Wert auslesen lassen kann.
Ich nehme an bei "data-average" ist "average" die selbst definierte variable, die in JS nun verwendet werden kann.
Nö, data-average ist einfach nur ein Attribut des HTML-Knotens. Attribute, die mit data- anfangen, sind sozusagen zur "freien Benutzung" freigegeben. Auslesen kannst du dieses Attribut, wie auch jedes andere Attribut.



var average = parseFloat( $(".balkendiagram").attr("data-average") );


Der Vorteil bei der HTML-Variante ist imo, dass du keine globale Javascriptvariable definieren musst. Komplexere Objekte (im JSON Format) würde ich dann aber doch in Javascript einbetten.

Zur Ajax-Frage: Da müsstest du schon etwas mehr Code zeigen. Generell würde ich empfehlen, die aktualisierten Daten per JSON zu übergeben und dann den Balken neu zu zeichnen.
Das könnte in etwa so aussehen:

HTML: game/rating.html.erb


1
2
<div class="rating_filled" style="width:<%=@average%>px;" />
<button id="aktualisiereBalkenDiv" value="Aktualisiere Balken" type="button" data-url="<%= game_rating_url(@game, :format => 'json') %>"/>


Javascript:
game/rating.js


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

$(function(){

// definiere Balken-Funktion
var aktualisiereBalken = function(wert) {
$(".rating_filled").css("width", wert);
}

// wenn auf Button geklickt wird
$("#aktualisiereBalkenDiv").click(function() {
// schicke einen Ajax Request los
$.getJSON($("#aktualisiereBalkenDiv").attr("data-url"), function(newAverage){
// aktualisiere Balken mit neuem Wert
aktualisiereBalken(newAverage);
});
});

});


Und im Controller dann eben
game_controller.rb


1
2
3
4
5
6
7
8
9
class GameController < ApplicationController
def rating
@average = Game.find(params[:id]).ratings.average(:value)
respond_to do |format|
format.html # rating.html.erb
format.json { render :json => @average}
end
end
end


Wenn der Nutzer nun auf den Button klickt, schickt er einen Ajax-Request ab, der die Methode GameController#rating mit format JSON aufruft. Dort schickst du dann als Antwort den neuen Wert. Das Javascript setzt diesen Wert dann gleich in den Balken um.
Die Methode rating kannst du gleichzeitig auch für deine HTML-Anzeige nutzen. Dann brauchst du nichtmal zwei verschiedene Actions dafür.


Nach oben
 Profil  
 
BeitragVerfasst: 14 Apr 2013, 16:35 
Offline
Geselle

Registriert: 18 Dez 2012, 19:44
Beiträge: 140
In meinem Falle ist es ein wenig komplizierter, da ich keinen submit button habe und den post (bzw put) bereits durch klicken auf einen wert veranlasse.

Also das ist die Form



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<div class="rating_form">
<% if user_signed_in? %>
<%= form_for(create_rating, :remote => true, :html => { :class => 'create_rating' }) do |f| %>
<%= f.label("value_1", content_tag(:span, '1'), {:class=>"rating", :id=>"1"}) %>
<%= radio_button_tag("rating[value]", 1, current_user_rating == 1, :class => 'rating_button') %>

<%= f.label("value_2", content_tag(:span, '2'), {:class=>"rating", :id=>"2"}) %>
<%= radio_button_tag("rating[value]", 2, current_user_rating == 2, :class => 'rating_button') %>

<%= f.label("value_3", content_tag(:span, '3'), {:class=>"rating", :id=>"3"}) %>
<%= radio_button_tag("rating[value]", 3, current_user_rating == 3, :class => 'rating_button') %>

<%= f.label("value_4", content_tag(:span, '4'), {:class=>"rating", :id=>"4"}) %>
<%= radio_button_tag("rating[value]", 4, current_user_rating == 4, :class => 'rating_button') %>

<%= f.label("value_5", content_tag(:span, '5'), {:class=>"rating", :id=>"5"}) %>
<%= radio_button_tag("rating[value]", 5, current_user_rating == 5, :class => 'rating_button') %>

<%= hidden_field_tag("game_id", @game.id) %>
<!--%= f.submit :Submit, class: "btn" %-->
<% end %>

<% end %>
</div>


Und mit folgendem Javascript Code veranlasse ich den post bei direktem click auf einen Wert (die übrigens mit grafiken ausgeschmückt wurden)


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
$(function () {
var checkedId = $('.create_rating > input:checked').attr('id');

$('.create_rating > label[for=' + checkedId + ']').prevAll().andSelf().addClass('bright');
});

$(document).ready(function() {

// Makes stars glow on hover.
$('.create_rating > label').hover(
function() { // mouseover
$(this).prevAll().andSelf().addClass('glow');
},function() { // mouseout
$(this).siblings().andSelf().removeClass('glow');
});

// Makes stars stay glowing after click.
$('.create_rating > label').click(function() {
$(this).siblings().removeClass("bright");
$(this).prevAll().andSelf().addClass("bright");
});

// Submits the form (saves data) after user makes a change.
$('.create_rating').change(function() {
$('.create_rating').submit();
});

});

Soll ich dann am besten das "data-url" attribut in die einzelnen radio tags einbetten?


Nach oben
 Profil  
 
BeitragVerfasst: 19 Mai 2013, 00:49 
Offline
Geselle

Registriert: 18 Dez 2012, 19:44
Beiträge: 140
ich hatte den bug mal für einige Zeit ruhen lassen aber heute mal wieder in Angriff genommen.
Ich habe es mir nochmal genau angesehen und festgestellt, dass der neue durchschnittswert in dem data-attribut des Balkens vertreten ist, nur der style wird nicht geladen.

ich denke es liegt daran, dass ja das partial bei anfrage neu geladen wird, aber nicht die javascript datei, in der diese style zuweisung definiert ist.

Die Lösung mit JSON klingt ganz sinnvoll, aber das läuft bei mir noch nicht so ganz.



1
2
3
4
5
6
7
8
9
10
11
12
13
14
        var average = parseFloat( $(".rating_filled").attr("data-average") );

var avg_width = (average/5)*200;


var reloadBar = function(avg_width){
$(".rating_filled").css("width", avg_width);
}

$(".rating_button").click(function(){
$.getJSON(average.function(newAverage){
reloadBar(newAverage);
});
});

So habe ich das für meinen Fall angepasst und meine rating_create methode um das json format und die "@average"-variable ergänzt, doch in diesem Falle wird der Balken einfach noch mit gar keinem Wert gefüllt.

Ich denke ich bin mit meiner ersten Lösung schon nah dran, brauche aber noch eben den kleinen Tipp, wie ich die Zuweisung aus der JS ebenfalls neu laden kann.


Nach oben
 Profil  
 
BeitragVerfasst: 25 Mai 2013, 11:23 
Offline
Geselle

Registriert: 18 Dez 2012, 19:44
Beiträge: 140
ok auch das problem konnte ganz simpel gelöst werden.

ich hab den javaScript Code ganz einfach in das neu zu landende partial eingebettet und dadurch wird es automatisch mit neu ausgeführt.

Leider weiß ich nur nicht, wie elegant das ist und ob das evtl zu Schwierigkeiten führen könnte ôô


Nach oben
 Profil  
 
BeitragVerfasst: 25 Mai 2013, 12:33 
Offline
Metaprogrammierer

Registriert: 20 Nov 2011, 21:51
Beiträge: 693
Vielleicht solltest du dir auch die jquery API etwas genauer ansehen. In der aktuellen jquery Version müsste bind das tun was du willst, wenn ich es richtig im Kopf habe. Damit kannst du viele events auch dann ohne ewiges neusetzen binden, auch wenn das zugehörige Element ständig ersetzt wird.

*edit*
Hab noch mal nachgesehen, ich meine nicht bind, sondern on. Auf github findest du in NobbZ/Mountains in der session. js. coffee ein Beispiel (auskommentiert). Ich nutze es inzwischen nicht mehr sondern habe es in dem Fall anders gelöst.

_________________
Ubuntu Gnome 14.04 LTS
rvm mit App-spezifischer Ruby-Version (meist 2.2.x) und -Gemset

Github ProfilBitbucket Profil


Nach oben
 Profil  
 
BeitragVerfasst: 25 Mai 2013, 13:19 
Offline
Geselle

Registriert: 18 Dez 2012, 19:44
Beiträge: 140
cool danke, werde es ausprobieren!


Nach oben
 Profil  
 
Beiträge der letzten Zeit anzeigen:  Sortiere nach  
Ein neues Thema erstellen Auf das Thema antworten  [ 11 Beiträge ] 

Alle Zeiten sind UTC + 1 Stunde [ Sommerzeit ]


Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 6 Gäste


Du darfst keine neuen Themen in diesem Forum erstellen.
Du darfst keine Antworten zu Themen in diesem Forum erstellen.
Du darfst deine Beiträge in diesem Forum nicht ändern.
Du darfst deine Beiträge in diesem Forum nicht löschen.
Du darfst keine Dateianhänge in diesem Forum erstellen.

Suche nach:
cron