Лучший способ добавить JavaScript на странице в приложении Rails 3?

У Rails 3 есть ненавязчивый JavaScript, который довольно крут.

Но мне было интересно, как лучше всего добавить дополнительный JavaScript для конкретной страницы.

Например, где я мог бы сделать это раньше:

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

Теперь мы можем сделать это ненавязчивым с чем-то вроде

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

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

Итак, я думаю, мой вопрос: где/как включить этот JavaScript? Я не хочу заполнять файл application.js, потому что этот JavaScript применим только к этому представлению. Должен ли я включать пользовательский файл JavaScript для каждой страницы каким-либо образом или вставлять его в переменную экземпляра, которую ищет заголовок?

Ответ 1

Что мне нравится делать, это включить Javascript для каждого просмотра в блок content_for :head, а затем yield к этому блоку в макете приложения. Например

Если это довольно коротко, то:

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

или, если дольше, то:

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

Затем в вашем файле макета

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

Ответ 2

Если вы хотите включить javascript только на одной странице, вы можете включить его на встроенную страницу, конечно, однако, если вы хотите сгруппировать свой javascript и воспользоваться конвейером активов, minified js и т.д., это можно сделать и имеют дополнительные js-активы, которые объединены и загружаются только на определенные страницы, разбивая js на группы, которые применяются только в определенных контроллерах/представлениях/разделах сайта.

Переместите js в активах в папки с отдельным файлом манифеста для каждого, поэтому, если у вас есть библиотека js admin, которая используется только на сервере, вы можете сделать это:

  • активы
    • JavaScripts
      • админ
        • ... JS
      • admin.js(манифест для группы администратора)
      • application.js(манифест для глобальной группы приложений)
      • глобальный
        • ... JS

в существующей application.js

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

в новом файле манифеста admin.js

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

Убедитесь, что этот новый манифест js загружен путем редактирования config/production.rb

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

Затем настройте макет страницы так, чтобы вы могли добавить некоторые дополнительные js для заголовка страницы:

<%= content_for :header %>   

Затем в представлениях, где вы хотите включить эту конкретную группу js (а также обычную группу приложений) и/или любые js, css и т.д. для страницы:

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

Вы можете, конечно, сделать то же самое с css и сгруппировать его аналогичным образом для применения только к определенным областям сайта.

Ответ 3

Я предпочитаю следующее...

В файле application_helper.rb

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

а затем в вашем конкретном представлении (app/views/books/index.html.erb в этом примере)

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

... похоже, работает для меня.

Ответ 4

Эти ответы помогли мне тонну! Если кто-то хочет немного больше...

  • Вам нужно поместить javascripts в манифесты, если вы хотите, чтобы они были предварительно скомпилированы. Однако, если вам нужен каждый файл javascript из application.js.coffee, тогда все javac-скрипты будут загружаться каждый раз, когда вы переходите на другую страницу, а цель выполнения javascripts для страницы будет проиграна.

Следовательно, вам необходимо создать свой собственный файл манифеста (например, speciifc.js), для которого потребуются все файлы javascript, относящиеся к странице. Кроме того, измените require_tree из application.js

приложение/активы/JavaScripts/application.js

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

приложения/активы/JavaScripts/specific.js

//= require_tree ./specific

Затем в environments/production.rb добавьте этот манифест в предварительно скомпилированный список с опцией config,

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

Готово! Все общие javascripts, которые всегда должны быть загружены, будут помещены в папку app/assets/javascripts/global и javascripts с помощью страницы в app/assets/javascripts/specific. Вы можете просто вызвать javascripts с конкретным текстом из представления, например

<%= javascript_include_tag "specific/whatever.js" %>//.js не является обязательным.

Этого достаточно, но я тоже хотел использовать javascript_include_tag params[:controller]. Когда вы создаете контроллеры, связанный файл coffeescript генерируется в app/assets/javascripts, как и другие упомянутые люди. Существуют действительно специфичные для контроллера javascripts, которые загружаются только тогда, когда пользователь достигает определенного вида контроллера.

Итак, я создал еще один манифест controller-specific.js

приложение/активы/JavaScripts/Контроллер-specific.js

//= require_directory .

Это будет включать все автоматически генерируемые кофейни, связанные с контроллерами. Кроме того, вам нужно добавить его в предварительно скомпилированный список.

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

Ответ 5

Если вы не хотите использовать конвейер активов или сложную работу , чтобы получить этот необходимый javascript (я сочувствую), самый простой и надежный путь, который достигает того же, что и ответы выше, но с меньшим количеством кода - это просто:

<%= javascript_include_tag "my_javascipt_file" %>

Примечание. Для этого требуется еще один HTTP-запрос на тег включения, чем ответы, которые используют content_for :head

Ответ 6

Взгляните на pluggable_js gem. Вы можете найти это решение более простым в использовании.

Ответ 7

Мое понимание заключается в том, что конвейер активов предназначен для уменьшения времени загрузки страницы путем сглаживания всех ваших js вместе в один (уменьшенный) файл. Хотя это может показаться отвратительным на поверхности, это на самом деле функция, которая уже существует в популярных языках, таких как C и Ruby. Такие вещи, как теги "include", предназначены для предотвращения множественного включения файла и для того, чтобы помочь программистам организовать их код. Когда вы пишете и компилируете программу на C, весь этот код присутствует в каждой части вашей запущенной программы, но методы загружаются только в память, когда этот код используется. В некотором смысле, скомпилированная программа не содержит ничего, чтобы гарантировать, что код хорошо модульный. Мы делаем код модульным, записывая наши программы таким образом, и операционная система только загружает в память объекты и методы, которые нам нужны для данной локальности. Существует ли даже такая вещь, как "включение метода"? Если ваше приложение для рельсов является спокойным, это, по сути, то, о чем вы просите.

Если вы пишете свой javascript, чтобы он улучшал поведение элементов HTML на странице, то эти функции являются "специфичными для страницы" по дизайну. Если есть сложный код, который вы написали таким образом, что он будет выполняться независимо от его контекста, возможно, в любом случае можно связать этот код с элементом html (вы можете использовать тег body, как описано в Гарбер-ирландский метод). Если функция выполняется условно, производительность, вероятно, будет меньше, чем все те дополнительные теги script.

Я думаю об использовании paloma gem, как описано в проект приложений rails. Затем вы можете сделать свою страницу на странице javascript, включив функции, связанные с страницей, в обратном вызове paloma:

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

Вы используете рельсы, поэтому я знаю, что вы любите драгоценные камни:)

Ответ 8

Нельзя загружать файлы JS или CSS за пределы конвейера, потому что вы теряете важные функции, которые делают Rails таким замечательным. И вам не нужен другой камень. Я верю в использование как можно большего количества драгоценных камней, и использование драгоценного камня здесь не обязательно.

То, что вы хотите, известно как "Специфичный Javascript для контроллера" ( "Специфичный для JavaScript Javascript включен внизу" ), который позволяет загружать определенный файл JavaScript для определенного КОНТРОЛЛЕРА. Попытка подключения вашего Javascript к представлению является доброй из... назад и не соответствует шаблону проектирования MVC. Вы хотите связать его с вашими контроллерами или действиями внутри ваших контроллеров.

К сожалению, по какой-то причине разработчики Rails решили, что по умолчанию каждая страница загружает каждый JS файл, расположенный в вашем каталоге ресурсов. Почему они решили сделать это вместо включения "Специфичного Javascript-контроллера" по умолчанию, я никогда не узнаю. Это делается через файл application.js, который по умолчанию включает следующую строку кода:

//= require_tree .

Это называется директивой. Это то, что sprockets использует для загрузки каждого JS файла в каталог assets/javascripts. По умолчанию звездочки автоматически загружают application.js и application.css, а директива require_tree загружает каждый файл JS и Coffee в соответствующие каталоги.

ПРИМЕЧАНИЕ.. Когда вы строите леса (если вы не являетесь подмостками, сейчас самое подходящее время для запуска), Rails автоматически создает файл кофе для вас, для этого контроллер леса. Если вы хотите создать файл стандартного JS вместо файла кофе, затем удалите кофе-камень, который по умолчанию включен в вашем Gemfile, а ваш эшафот будет создавать JS файлы.

Итак, на первом шаге, чтобы включить "Специфический Javascript для контроллера", необходимо удалить код require_tree из файла application.js или изменить его в папку в вашем каталоге assets/javascripts, если вы все еще нужны глобальные JS файлы. То есть:.

//= require_tree ./global

Шаг 2: Перейдите в файл config/initializers/assets.rb и добавьте следующее:

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

Вставьте имена контроллеров, которые вы хотите.

Шаг 3: Замените javascript_include_tag в файле application.html.erb с этим (обратите внимание на часть params [: controller]:

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

Перезагрузите сервер и альта! JS файл, который был сгенерирован вашим эшафотом, теперь будет загружаться только при вызове этого контроллера.

Необходимо загрузить определенный JS файл в конкретном ACTION в контроллере, I.E./articles/new? Сделайте это вместо:

application.html.erb:

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

конфигурации/Инициализаторы/assets.rb:

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

Затем добавьте новую папку с тем же именем, что и ваш контроллер, в папку assets/javascripts и поместите файл js с тем же именем, что и ваше действие внутри. Затем он загрузит это действие.

Ответ 9

Хорошо, возможно, это похоже на худшую работу, но я создаю метод контроллера, который просто отобрал файл .js

контроллер

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

Вид

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

если по какой-то причине мы не хотим этого делать, дайте мне знать.

Ответ 10

Предпочтительный способ добавления JS находится в нижнем колонтитуле, поэтому вы можете сделать это следующим образом:

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