web-dev-qa-db-fra.com

Meilleure façon d’ajouter du code JavaScript spécifique à une page dans une Rails 3 app?

Rails 3 a du JavaScript discret qui est plutôt cool.

Mais je me demandais quel était le meilleur moyen d'inclure du code JavaScript supplémentaire pour une page donnée.

Par exemple, où j'aurais peut-être déjà fait:

<%= f.radio_button :rating, 'positive', :onclick => "$('some_div').show();" %>

Nous pouvons maintenant le rendre discret avec quelque chose comme

<%= f.radio_button :rating, 'positive' %>

# then in some other file
$('user_rating_positive').click(function() {
  $('some_div').show();
}

Donc, je suppose que ma question est où/comment inclure ce JavaScript? Je ne veux pas remplir le application.js fichier car ce JavaScript est uniquement applicable à cette vue. Devrais-je inclure un fichier JavaScript personnalisé pour chaque page ou le coller dans une variable d'instance recherchée par l'en-tête?

156
Brian Armstrong

Ce que j'aime faire, c'est inclure le code Javascript per-view dans un content_for :head, puis yield à ce bloc dans la présentation de votre application. Par exemple

Si c'est assez court alors:

<% content_for :head do %>
  <script type="text/javascript">
    $(function() {
      $('user_rating_positve').click(function() {
        $('some_div').show();
      }
    });
  </script>
<% end %>

ou, si elle est plus longue, alors:

<% content_for :head do %>
  <script type="text/javascript">
    <%= render :partial => "my_view_javascript"
  </script>
<% end %>

Ensuite, dans votre fichier de mise en page

<head>
  ...
  <%= yield :head %>
</head>
150
bjg

Si vous souhaitez inclure du code javascript sur une seule page, vous pouvez l’inclure sur la page en ligne bien sûr. Toutefois, si vous souhaitez regrouper votre code javascript et tirer parti du pipeline d’actifs, du fichier js minifié, etc., il est possible de le faire et de bénéficier de fonctions supplémentaires. Actifs js qui sont combinés et chargés uniquement sur des pages spécifiques en divisant votre js en groupes qui ne s'appliquent que dans certains contrôleurs/vues/sections du site.

Déplacez vos fichiers js dans des fichiers dans des dossiers, avec un fichier manifeste distinct pour chacun. Par conséquent, si vous avez une bibliothèque admin js utilisée uniquement sur le backend, procédez comme suit:

  • les atouts
    • javascripts
      • admin
        • ... js
      • admin.js (manifeste pour le groupe admin)
      • application.js (manifeste pour le groupe global de l'application)
      • global
        • ... js

dans le fichier application.js existant

//= require jquery
//= require jquery_ujs
//= require_tree ./global // requires all js files in global folder

dans un nouveau fichier manifeste admin.js

//= require_tree ./admin // requires all js files in admin folder

Assurez-vous que ce nouveau manifeste js est chargé en modifiant config/production.rb

config.assets.precompile += %w( admin.js )

Puis ajustez la mise en page de sorte que vous puissiez inclure des js supplémentaires pour l’en-tête de la page:

<%= content_for :header %>   

Ensuite, dans les vues où vous souhaitez inclure ce groupe js spécifique (ainsi que le groupe d'applications normales) et/ou tout fichier js, css, etc. spécifique à une page:

<% content_for :header do %>
  <%= javascript_include_tag 'admin' %>  
<% end %>

Vous pouvez bien sûr faire la même chose avec css et le regrouper de manière similaire pour ne l'appliquer qu'à certaines zones du site.

102
Kenny Grant

Je préfère ce qui suit ...

Dans votre fichier application_helper.rb

def include_javascript (file)
    s = " <script type=\"text/javascript\">" + render(:file => file) + "</script>"
    content_for(:head, raw(s))
end

puis dans votre vue particulière (app/views/books/index.html.erb dans cet exemple)

<% include_javascript 'books/index.js' %>

... semble fonctionner pour moi.

12
cailinanne

Ces réponses m'ont aidé une tonne! Si quelqu'un veut un peu plus ...

  1. Vous devez insérer des javascripts dans les manifestes si vous souhaitez les précompiler. Cependant, si vous avez besoin de tous les fichiers javascript de application.js.coffee, Tous les javacsripts seront chargés chaque fois que vous naviguerez sur une page différente et l'objectif de création de javascripts spécifiques à une page sera vaincu.

Par conséquent, vous devez créer votre propre fichier manifeste (par exemple, speciifc.js) Qui nécessitera tous les fichiers javascript spécifiques à la page. Aussi, modifiez require_tree De application.js

app/assets/javascripts/application.js

//= require jquery
//= require jquery_ujs
//= require_tree ./global

app/assets/javascripts/specific.js

//= require_tree ./specific

Ensuite, dans votre environments/production.rb Ajoutez ce manifeste à la liste précompilée avec l’option config,

config.assets.precompile += %w( specific.js )

Terminé! Tous les javascripts partagés qui doivent toujours être chargés seront placés dans le dossier app/assets/javascripts/global, Et les javascripts spécifiques à la page dans app/assets/javascripts/specific. Vous pouvez simplement appeler les javascripts spécifiques à la page à partir de la vue, comme

<%= javascript_include_tag "specific/whatever.js" %> //.Js est facultatif.

C'est suffisant, mais je voulais aussi utiliser javascript_include_tag params[:controller]. Lorsque vous créez des contrôleurs, un fichier coffeescript associé est généré dans app/assets/javascripts Comme les autres personnes mentionnées. Il existe vraiment des javascripts spécifiques à l'automate , qui ne sont chargés que lorsque l'utilisateur atteint la vue spécifique de l'automate.

J'ai donc créé un autre manifeste controller-specific.js

app/assets/javascripts/controller-specific.js

//= require_directory .

Cela inclura tous les scripts de café générés automatiquement associés aux contrôleurs. En outre, vous devez l'ajouter à la liste précompilée.

config.assets.precompile += %w( specific.js controller-specific.js )

11
Maximus S

Si vous ne souhaitez pas utiliser le pipeline d'actifs ou le solutions de rechange complexes pour obtenir le code javascript spécifique à la page (je sympathise), le moyen le plus simple et le plus robuste qui permet d'obtenir les mêmes résultats que les réponses ci-dessus. mais avec moins de code c'est juste à utiliser:

<%= javascript_include_tag "my_javascipt_file" %>

Remarque: cela nécessite une demande http supplémentaire par balise include que les réponses utilisant content_for :head

9
AJP

Jetez un oeil à pluggable_js gem. Vous pouvez trouver cette solution plus facile à utiliser.

7
peresleguine

D'après ce que je comprends, le pipeline d'actifs est conçu pour réduire le temps de chargement d'une page en écrasant tous vos fichiers js dans un seul fichier (minifié). Bien que cela puisse sembler répugnant à première vue, il s'agit en fait d'une fonctionnalité déjà existante dans les langages populaires tels que C et Ruby. Des choses comme les balises "include" ont pour but d'empêcher l'inclusion multiple d'un fichier et d'aider les programmeurs à organiser leur code. Lorsque vous écrivez et compilez un programme en C, tout ce code est présent dans chaque partie de votre programme en cours d'exécution, mais les méthodes ne sont chargées en mémoire que lorsque ce code est utilisé. En un sens, un programme compilé n'inclut rien pour garantir que le code est bien modulaire. Nous rendons le code modulaire en écrivant nos programmes de cette manière, et le système d'exploitation ne charge en mémoire que les objets et les méthodes dont nous avons besoin pour une localité donnée. Existe-t-il même une "inclusion spécifique à une méthode"? Si votre application Rails est reposante, c’est essentiellement ce que vous demandez.

Si vous écrivez votre code javascript de manière à augmenter le comportement des éléments HTML sur la page, ces fonctions sont "spécifiques à la page" par nature. Si vous avez écrit du code compliqué de manière à ce qu’il s’exécute quel que soit son contexte, envisagez peut-être tout de même de le lier à un élément html (vous pouvez utiliser la balise body, comme décrit dans le Garber). Méthode irlandaise ). Si une fonction s'exécute de manière conditionnelle, les performances seront probablement inférieures à toutes ces balises de script supplémentaires.

Je pense à utiliser la gemme paloma , comme décrit dans le projet d'applications Rails . Ensuite, vous pouvez rendre votre page javascript spécifique en incluant des fonctions spécifiques à une page dans un rappel paloma:

Paloma.callbacks['users']['new'] = function(params){
    // This will only run after executing users/new action
    alert('Hello New Sexy User');
}; 

Vous utilisez Rails, alors je sais que vous aimez les pierres précieuses :)

3
Ziggy

Vous ne devriez pas charger vos fichiers JS ou CSS en dehors du portefeuille d’actifs, car vous perdez des fonctionnalités importantes qui rendent Rails génial. Et vous n’avez pas besoin d’un autre joyau. Je crois en utiliser le moins de gemmes possible et utiliser un gemme n'est pas nécessaire ici.

Ce que vous voulez est connu sous le nom de "Javascript spécifique au contrôleur" ("Le code Javascript spécifique à l'action est inclus en bas). Cela vous permet de charger un fichier JavaScript spécifique pour un CONTRÔLEUR spécifique. Essayer de connecter votre Javascript à une vue est une sorte de .. Ne pas suivre le modèle de conception MVC, vous voulez l'associer à vos contrôleurs ou aux actions à l'intérieur de vos contrôleurs.

Malheureusement, pour une raison quelconque, Rails devs a décidé que, par défaut, chaque page chargerait chaque fichier JS situé dans votre répertoire d’actifs. Pourquoi ont-ils décidé de le faire au lieu d’activer "Contrôleur Javascript spécifique" par Je ne le saurai jamais par défaut, par le biais du fichier application.js, qui inclut la ligne de code suivante par défaut:

//= require_tree .

Cela s'appelle une directive . C'est ce que sprockets utilise pour charger chaque fichier JS dans le répertoire assets/javascripts. Par défaut, sprockets charge automatiquement application.js et application.css, et la directive require_tree charge tous les fichiers JS et Coffee dans leurs répertoires respectifs.

NOTE: Lorsque vous échafaudez (si vous n'êtes pas un échafaudage, le moment est venu de commencer), Rails génère automatiquement un café fichier pour vous, pour le contrôleur de cet échafaudage. Si vous voulez qu'il génère un fichier JS standard au lieu d'un fichier café, supprimez le fichier gem café = activé par défaut dans votre Gemfile, et votre échafaudage créera des fichiers JS à la place.

Ok, la première étape pour activer "Contrôleur Javascript spécifique" consiste à supprimer le code require_tree de votre fichier application.js, OR le changer dans un dossier de votre Répertoire assets/javascripts si vous avez toujours besoin de fichiers JS globaux.

//= require_tree ./global

Étape 2: Allez dans votre fichier config/initializers/assets.rb et ajoutez ce qui suit:

%w( controllerone controllertwo controllerthree ).each do |controller|
  Rails.application.config.assets.precompile += ["#{controller}.js", "#{controller}.css"]
end

Insérez les noms de contrôleur que vous voulez.

Étape 3: Remplacez le javascript_include_tag dans votre fichier application.html.erb par ceci (notez la partie params [: controller]:

<%= javascript_include_tag 'application', params[:controller], 'data-turbolinks-track': 'reload' %>

Redémarrez votre serveur et votre alto! Le fichier JS généré avec votre échafaudage ne se charge que lorsque ce contrôleur est appelé.

Besoin de charger un fichier JS spécifique sur une ACTION spécifique dans votre contrôleur, I.E. /articles/new ? Faites ceci à la place:

application.html.erb :

<%= javascript_include_tag "#{controller_name}/#{action_name}" if AppName::Application.assets.find_asset("#{controller_name}/#{action_name}") %>

config/initializers/assets.rb :

config.assets.precompile += %w(*/*)

Ajoutez ensuite un nouveau dossier portant le même nom que votre contrôleur dans votre dossier assets/javascripts et insérez votre fichier js portant le même nom que votre action. Il le chargera ensuite pour cette action spécifique.

3
Erick Maynard

Ok, c’est peut-être le pire travail de tous les temps, mais j’ai créé une méthode de contrôleur qui vient de restituer le fichier .js.

Manette

def get_script
   render :file => 'app/assessts/javascripts/' + params[:name] + '.js'
end
def get_page
   @script = '/' + params[:script_name] + '.js?body=1'
   render page
end

Vue

%script{:src => @script, :type => "text/javascript"}

si, pour une raison quelconque, nous ne voulons pas faire cela, faites-le-moi savoir.

1
Bill

Le moyen préféré pour ajouter JS est dans le pied de page, vous pouvez donc procéder comme suit:

show.html.erb:

<% content_for :footer_js do %>
   This content will show up in the footer section
<% end %>

layouts/application.html.erb

<%= yield :footer_js %>
1
Syed