javascript - externe - exemple fichier js



Comment rester au sec lorsque vous utilisez les modèles Javascript et ERB(Rails) (4)

Je construis une application Rails qui utilise Pusher pour utiliser les sockets Web pour envoyer les mises à jour directement au client. En javascript:

channel.bind('tweet-create', function(tweet){ //when a tweet is created, execute the following code:
  $('#timeline').append("<div class='tweet'><div class='tweeter'>"+tweet.username+"</div>"+tweet.status+"</div>");
});

C'est un mauvais mélange de code et de présentation. Donc la solution naturelle serait d'utiliser un template javascript. Peut-être éco ou moustache:

//store this somewhere convenient, perhaps in the view folder:
tweet_view = "<div class='tweet'><div class='tweeter'>{{tweet.username}}</div>{{tweet.status}}</div>"

channel.bind('tweet-create', function(tweet){ //when a tweet is created, execute the following code:
    $('#timeline').append(Mustache.to_html(tweet_view, tweet)); //much cleaner
});

C'est bon et tout, sauf que je me répète . Le modèle de moustache est identique à 99% aux modèles ERB que j'ai déjà écrits pour rendre HTML à partir du serveur. La sortie / l'objectif des modèles moustache et ERB sont identiques à 100%: transformer un objet tweet en tweet html.

Quelle est la meilleure façon d'éliminer cette répétition?

MISE À JOUR: Même si j'ai répondu à ma propre question, je veux vraiment voir d'autres idées / solutions d'autres personnes - d'où la prime!


Jusqu'à présent, la meilleure solution que j'ai trouvée était Isotope .

Il vous permet d'écrire des modèles en utilisant Javascript qui peut être rendu par le client et le serveur.


Je n'ai pas essayé cela, mais cela m'est venu à l'esprit comme une solution possible:

À votre avis, créez un div caché qui contient un exemple de modèle (j'utilise HAML ici pour la brièveté):

#tweet-prototype{:style => "display:none"}
    = render :partial => Tweet.prototype

Votre tweet partiel peut afficher un tweet comme vous le faites maintenant.

.tweet
    .tweeter
        = tweet.username
    .status
        = tweet.status

Lors de la création d'un prototype de tweet, vous définissez les champs que vous voulez à la syntaxe de remplacement de js-template, vous pouvez certainement sécher cela, mais je l'inclus ici dans son intégralité à titre d'exemple.

# tweet.rb
def self.prototype
    Tweet.new{:username => "${tweet.username}", :status => "${tweet.status}"}
end

Sur le client, vous feriez quelque chose comme:

var template = new Template($('#tweet-prototype').html());
template.evaluate(.. your tweet json..);

La dernière partie dépendra de la façon dont vous faites votre template, mais ce serait quelque chose comme ça.

Comme je l'ai déjà dit, je n'ai pas essayé cette technique, et je ne vais pas vous laisser faire des trucs comme des boucles ou des mises en forme conditionnelles directement dans le modèle, mais vous pouvez le contourner avec une certaine créativité.

Ce n'est pas si éloigné de ce que vous cherchez à faire en utilisant Isotope, et de bien des façons, c'est inférieur, mais c'est certainement une solution plus simple. Personnellement, j'aime le haml, et j'essaie d'écrire autant que possible sur ma note, donc ce serait une meilleure solution pour moi personnellement.

J'espère que ça aide!


Je rendrais tous les tweets avec Javascript. Au lieu de rendre le HTML sur le serveur, définissez les données initiales comme JS dans la tête de votre page. Lorsque la page se charge, affichez les Tweets avec JS.

Dans ta tête:

%head
  :javascript
    window.existingTweets = [{'status' : 'my tweet', 'username' : 'glasner'}];

Dans un fichier JS:

$.fn.timeline = function() {
  this.extend({
    template: "<div class='tweet'><div class='tweeter'>{{tweet.username}}</div>{{tweet.status}}</div>",
    push: function(hash){
      // have to refer to timeline with global variable
      var tweet = Mustache.to_html(timeline.template, hash)     
      timeline.append(tweet);
    }
  });  

  window.timeline = this;

  channel.bind('tweet-create', this.push);  

  // I use Underscore, but you can loop through however you want
  _.each(existingTweets,function(hash) {
    timeline.push(hash);
  });

  return this
};  


$(document).ready(function() {
  $('#timeline').timeline();
});





mustache