【问题标题】:Calling a CoffeeScript function across all views (Ruby on Rails)在所有视图中调用 CoffeeScript 函数(Ruby on Rails)
【发布时间】:2016-09-25 03:06:51
【问题描述】:

这是我的第一个 * 问题,所以我希望我问对了!

我有一个 Ruby on Rails Web 应用程序,在我们的 javascript 文件中,我有以下 CoffeeScript 代码,它检测何时按下 id="submit" 的按钮,然后滚动到出现的第一个错误(如果有)(我们的表单中使用了“提交”按钮):

@scroll_to_error = ->
  document.getElementById('submit').onclick = ->
  	if $('.alert-danger:visible:first').length > 0
      $('html, body').animate { scrollTop: $('.alert-danger:visible:first').offset().top - 220 }, '1000'
  	return

我在 config 文件夹中的 application.rb 文件中包含该文件,因此可以在视图部分的任何 HTML 文件中调用它~~但是,我想知道是否有办法让它可以召集了我所有的观点。有没有特定的方法可以做到这一点?

希望这是足够的信息 - 抱歉,我无法提供更多代码 sn-ps,因为我正在为一家公司编码(因此是“我们的”)。

【问题讨论】:

    标签: javascript jquery ruby-on-rails ruby coffeescript


    【解决方案1】:

    一种方法是在函数中公开您的代码,以便您可以从视图中调用它。

    咖啡脚本文件:

    window.SomeNamespace ||= {}
    window.SomeNamespace.scroll_to_error = ->
      document.getElementById('submit').onclick = ->
        if $('.alert-danger:visible:first').length > 0
          $('html, body').animate { scrollTop: $('.alert-danger:visible:first').offset().top - 220 }, '1000'
    

    查看文件:(假设您正在使用 erb)

    <script>
      $(function(){ 
        window.SomeNamespace.scroll_to_error()
      });
    </script>
    

    不过,更好的方法是将视图代码和 JavaScript 代码分开。 elementaljs 为 Rails 提供了一个小型 Javascript 行为库,我非常喜欢它。您可以通过 data 属性将 javascript 行为“附加”到特定的 html 元素,该库会为您完成上述工作。

    【讨论】:

    • 谢谢 - 但是我需要在所有视图中自动调用此函数,因为手动将其添加到每个视图很乏味,如果添加了其他视图,我正在与之合作的团队必须记住添加更多。 ://
    • 更简单!只需在您的application.js 中说#= require &lt;insert_relative_file_path&gt; 并在您的coffeescript 文件中放置您的侦听器而不将其包装到命名函数中,即$ -&gt; document.getElementById('submit').onclick = -&gt; ... 此代码将在每个页面加载时运行。
    • 哦,太棒了!但是,这与使用 $(document).ready 相同 -> 我有点想要它,以便它不仅会在页面加载时运行,而且还会在用户浏览时运行(比如用户单击 #再次提交按钮并得到另一个错误)
    • 如果我可以,例如,在每个页面上用 调用它,只要用户在页面上,那就太好了,或者如果我可以调用在 之后通过修改 函数本身,它也可以工作(f 是一个表单,不幸的是每个表单都有不同的 id,但是,它们确实有 classes 。 btn 和 .btn-primary)
    • 你试过了吗?这将在页面加载时设置 listener,并且每次单击元素时,listener 中的代码都会运行。我想我不明白你的意思。
    【解决方案2】:

    试试这样的?

    scrollToError = ->
      $('*[data-scroll-to-error="true"]').click ->
        alertElement = $('.alert-danger:visible:first')
    
        if alertElement.length > 0
          $('html, body').animate { 
            scrollTop: alertElement.offset().top - 220 
          }, '1000'
    
    # Run with turbolinks.
    $(document).on 'page:change', scrollToError
    

    还有一个带有data-scroll-to-error 属性集的提交按钮。

    <input type="submit" data-scroll-to-error="true" />
    

    我觉得你的这种说法令人困惑:

    我在配置中的 application.rb 文件中包含该文件 文件夹,以便可以在视图部分的任何 HTML 文件中调用它

    假设这是一个标准的 Rails 项目,您应该在 assets/javascripts/application.js(清单文件)中包含包含 Coffeescript 代码的文件,并且由于 application.js 是布局中需要的 JS 文件(不是吗? :-/),此代码将在您的所有视图上执行。我不明白config/application.rb 是如何参与其中的。

    更新:添加更多信息。

    如果您不确定如何使用 application.js 文件(清单文件),请花时间阅读 Rails 的官方文档(尤其是关于清单的部分)。

    http://guides.rubyonrails.org/asset_pipeline.html#manifest-files-and-directives

    在您的情况下,您需要修改 application.js 以包括:

    ...
    //= require error
    ...
    

    基本上,您列出所有要加载的资产文件以及使用布局的所有页面(可能是application.html.erb),然后仅提及布局的清单文件。这样,Rails 可以连接和缩小以生成单个资产文件。默认的 application. 清单文件会自动预编译 - 因此您无需手动将新资产添加到预编译列表中。

    我将选择器写为*[data-scroll-to-error="true"] 的原因是个人喜好——这样我的代码读起来更好。如果您确定 ID submit (并且将来会)仅应用于需要滚动到错误的元素,那么可以将第一个选择器更改为 $('#submit').click -&gt;

    【讨论】:

    • 有一个 application.js 文件,但是老实说我不太确定如何包含该功能。函数是scroll_to_error,文件位于assets/javascripts/error.coffee。至于 config/application.rb 文件,它是使用 config.assets.precompile 包含的
    • 另外,我实际上是在为一家公司编写的数据库上编写代码~~因此已经有太多按钮无法将所有数据滚动到错误更改为 true
    • @keyan.r 我已更新答案以包含与您的 cmets 相关的更多信息。