Najlepszy sposób na dodanie specyficznego dla strony JavaScript w aplikacji Rails 3?

Rails 3 ma trochę dyskretnego JavaScript, który jest całkiem fajny.

Ale zastanawiałem się, jaki jest najlepszy sposób, aby dołączyć dodatkowy JavaScript dla konkretnej strony.

Na przykład, gdzie mogłem wcześniej zrobić:

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

Możemy teraz zrobić to dyskretnie z czymś takim jak

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

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

Więc moje pytanie brzmi, gdzie/jak włączyć ten JavaScript? Nie chcę wypełniać pliku application.js, ponieważ ten JavaScript ma zastosowanie tylko do tego jednego widoku. Czy Powinienem Dołącz niestandardowy plik JavaScript dla każdej strony w jakiś sposób, lub trzymać go w zmiennej instancji, że nagłówek szuka?

Author: Xufox, 2010-08-09

10 answers

To, co lubię zrobić, to włączyć JavaScript per-view w bloku content_for :head, a następnie yield do tego bloku w układzie aplikacji. Na przykład

Jeśli jest dość krótki to:

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

Lub, jeśli dłużej, to:

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

Następnie w pliku układu

<head>
  ...
  <%= yield :head %>
</head>
 148
Author: bjg,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-11-29 18:57:53

Jeśli chcesz włączyć javascript tylko na jednej stronie, można to na stronie inline oczywiście, jednak jeśli chcesz zgrupować swój javascript i skorzystać z potoku zasobów, minified js itp, Jest to możliwe, aby to zrobić i mieć dodatkowe zasoby js, które są połączone i ładowane tylko na określonych stronach, dzieląc js na grupy, które mają zastosowanie tylko w niektórych kontrolerów / widoki / sekcje witryny.

Przenieś swoje js w zasobach do folderów, z osobnym plikiem manifestu dla każdy, więc jeśli masz bibliotekę admin js, która jest używana tylko w backendzie, możesz to zrobić:

  • aktywa
    • javascripts
      • admin
        • ...js
      • admin.js (manifest for Admin group)
      • zastosowanie.js (manifest dla App global group)
      • global
        • ...js

W istniejącej aplikacji.js

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

W Nowym adminie.js manifest plik

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

Upewnij się, że nowy manifest js jest ładowany przez edycję config / production.rb

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

Następnie Dostosuj układ strony, aby można było dodać dodatkowe js dla nagłówka strony:

<%= content_for :header %>   

Następnie w widokach, w których chcesz dołączyć tę konkretną grupę js (jak również normalną grupę aplikacji) i / lub dowolne specyficzne dla strony js, css itp:

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

Możesz oczywiście zrobić to samo z css i grupować go w podobny sposób, aby zastosować tylko do pewnych obszarów miejscu.

 102
Author: Kenny Grant,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-02-22 12:34:04

Wolę następujące rzeczy...

W Twoim application_helper.plik rb

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

A następnie w twoim konkretnym widoku (app/views/books / index.html.erb w tym przykładzie)

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

... wygląda na to, że mi pasuje.

 11
Author: cailinanne,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-05-17 18:41:26

Te odpowiedzi Bardzo mi pomogły! Jeśli ktoś chce trochę więcej...

  1. musisz umieścić Skrypty javascripts w manifestach, jeśli chcesz je wstępnie skompilować. Jeśli jednak potrzebujesz KAŻDEGO pliku javascript z application.js.coffee, to wszystkie skrypty javacs będą ładowane za każdym razem, gdy przejdziesz do innej strony, a cel wykonywania skryptów javascripts dla danej strony zostanie pokonany.

Dlatego musisz utworzyć własny plik manifestu (np. speciifc.js), który będzie wymagał wszystkich pliki javascript specyficzne dla strony. Również zmodyfikować require_tree z application.js

App / assets/javascripts / application.js

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

App / assets/javascripts / specific.js

//= require_tree ./specific

Następnie w environments/production.rb Dodaj ten manifest do wstępnie skompilowanej listy za pomocą opcji config,

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

Zrobione! Wszystkie współdzielone javascripts, które powinny być zawsze załadowane, zostaną umieszczone w folderze app/assets/javascripts/global, a page-spcific javascripts w app/assets/javascripts/specific. Możesz po prostu wywołanie skryptów JavaScript specyficznych dla strony z widoku jak

<%= javascript_include_tag "specific/whatever.js" %> //.js jest opcjonalne.

To wystarczy, ale ja też chciałem skorzystać z javascript_include_tag params[:controller]. Podczas tworzenia kontrolerów, skojarzony plik coffeescript jest generowany w app/assets/javascripts, tak jak inne osoby wymienione. Istnieją Skrypty javascripts specyficzne dla kontrolera , które są ładowane tylko wtedy, gdy użytkownik dotrze do określonego widoku kontrolera.

Więc stworzyłem kolejny manifest controller-specific.js

App/assets/javascripts / Controller-specific.js

//= require_directory .

Będzie to obejmować wszystkie Automatycznie generowane coffeescripts powiązane z kontrolerami. Musisz również dodać go do wstępnie skompilowanej listy.

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

 11
Author: Maximus S,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-06-12 03:10:10

Jeśli nie chcesz korzystać z potoku zasobów lub złożonych wokół pracy , Aby uzyskać niezbędny javascript specyficzny dla strony (współczuję), najprostszym i najbardziej solidnym sposobem, który osiąga to samo, co odpowiedzi powyżej, ale z mniejszą ilością kodu jest po prostu użyć:

<%= javascript_include_tag "my_javascipt_file" %>

Uwaga: Wymaga to jednego żądania http więcej na znacznik include niż odpowiedzi, które używają content_for :head

 9
Author: AJP,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 10:31:30

Spójrz na pluggable_js gem. Rozwiązanie to może okazać się łatwiejsze w użyciu.

 7
Author: peresleguine,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-07-25 12:58:58

Rozumiem, że potok zasobów ma na celu skrócenie czasu ładowania strony poprzez połączenie wszystkich plików js w jeden (zminifikowany) plik. Chociaż może to wydawać się odrażające na powierzchni, jest to w rzeczywistości funkcja, która istnieje już w popularnych językach, takich jak C i Ruby. Znaczniki typu "include" mają na celu zapobieganie wielokrotnemu włączaniu pliku oraz pomoc programistom w organizowaniu ich kodu. Kiedy piszesz i kompilujesz program w C, cały ten kod jest obecny w każdej części twojego działania program, ale metody są ładowane do pamięci tylko wtedy, gdy ten kod jest używany. W pewnym sensie skompilowany program nie zawiera niczego, co gwarantowałoby, że kod jest ładnie modułowy. Uczynimy kod modularnym pisząc w ten sposób nasze programy, a system operacyjny ładuje do pamięci tylko te obiekty i metody, których potrzebujemy dla danej miejscowości. Czy istnieje w ogóle coś takiego jak "włączenie specyficzne dla metody"? Jeśli Twoja aplikacja rails jest restful, to właśnie o to prosisz.

Jeśli napisz swój javascript tak, że zwiększa zachowanie elementów HTML na stronie, a następnie funkcje te są "specyficzne dla strony" z założenia. Jeśli istnieje jakiś skomplikowany kod, który napisałeś w taki sposób, że będzie wykonywany niezależnie od kontekstu, może rozważ powiązanie tego kodu z elementem html (możesz użyć tagu body, jak opisano w metodzie Garber-Irish ). Jeśli funkcja jest wykonywana warunkowo, wydajność prawdopodobnie będzie mniejsza niż wszystkie Dodatkowe skrypty tagi.

Myślę o użyciu gem paloma , jak opisano w rails apps project . Następnie możesz skonfigurować swoją stronę javascript, włączając funkcje specyficzne dla strony w wywołaniu zwrotnym paloma:

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

Używasz railsów, więc wiem, że kochasz klejnoty:)

 3
Author: Ziggy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-03-29 22:08:39

Nie powinieneś ładować plików JS lub CSS poza potokiem zasobów, ponieważ tracisz na ważnych funkcjach, które sprawiają, że Rails jest tak świetny. I nie potrzebujesz kolejnego klejnotu. Wierzę w używanie jak największej liczby klejnotów, a używanie klejnotu nie jest tutaj konieczne.

To, co chcesz, jest znane jako "JavaScript specyficzny dla kontrolera" ("Javascript specyficzny dla akcji jest zawarty na dole). Pozwala to na załadowanie określonego pliku JavaScript dla określonego kontrolera. Próbuje połączyć swoje Javascript to a View is some of... Wstecz i nie podąża za wzorcem projektowym MVC. Chcesz powiązać go z kontrolerami lub akcjami wewnątrz kontrolerów.

Niestety, z jakiegokolwiek powodu, deweloperzy Rails zdecydowali, że domyślnie każda strona załaduje każdy plik JS znajdujący się w katalogu assets. Dlaczego zdecydowali się to zrobić zamiast włączać domyślnie "Controller Specific Javascript" nigdy się nie dowiem. Odbywa się to za pośrednictwem aplikacji.plik js, który zawiera domyślnie następujący wiersz kodu:

//= require_tree .

Jest to znane jako dyrektywa. Tego używa sprockets do załadowania KAŻDEGO pliku JS w katalogu assets / javascripts. Domyślnie koła łańcuchowe automatycznie ładują aplikację.js i aplikacji.css i dyrektywa require_tree ładują każdy plik JS i Coffee w odpowiednich katalogach.

Uwaga: gdy rusztujesz (jeśli nie rusztujesz, teraz jest dobry moment, aby zacząć), Rails automatycznie generuje / Align = "center" bgcolor = "# e0ffe0 " / cesarz Chin / / align = center / Jeśli chcesz, aby wygenerował standardowy plik JS zamiast pliku coffee , Usuń coffee gem, który jest domyślnie włączony w twoim Gemfile, a twoje rusztowanie utworzy Pliki JS.

Ok, więc pierwszym krokiem do włączenia "Controller Specific Javascript" jest usunięcie kodu require_tree z Twojej aplikacji.pliku js lub zmień go na folder w swoim katalog assets / javascripts jeśli nadal potrzebujesz globalnych plików JS. I. E.:

//= require_tree ./global

Krok 2: przejdź do konfiguracji / initializers / assets.plik rb i dodać:

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

Wstaw nazwy kontrolerów, które chcesz.

Krok 3: Zastąp javascript_include_tag w aplikacji.html.plik erb z tym (zwróć uwagę na Część params [: controller]:

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

Restart serwera i viola! Plik JS, który został wygenerowany za pomocą Twojego rusztowania, będzie teraz ładuje się tylko wtedy, gdy ten kontroler jest wywołany.

Potrzebujesz załadować konkretny plik JS na określoną akcję w kontrolerze , tj. / articles / new ? Do this instead:

podanie.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(*/*)

Następnie dodaj nowy folder o tej samej nazwie co kontroler w folderze assets/javascripts i umieść plik js o tej samej nazwie, co twoja akcja. Następnie załaduje go na to konkretne działanie.

 3
Author: Erick Maynard,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-10-03 03:50:21

Ok więc może to jest najgorsza praca w historii, ale stworzyłem metodę kontrolera, która właśnie wyrenderowała .plik js

Controller

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

Widok

%script{:src => @script, :type => "text/javascript"}
Jeśli z jakiegoś powodu nie chcemy tego robić, daj mi znać.
 1
Author: Bill,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-11-15 22:00:05

Preferowany sposób dodawania JS jest w stopce, więc możesz to zrobić w ten sposób:

Pokaż.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
Author: Syed,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-09-22 08:21:46