59218


## 発生している問題

jQueryをhtmlファイルに`<script>`タブで記述する場合と  
jsファイルに別途記述する場合では、挙動に差があるのでしょうか？

Bootstrapの練習のために[こちらのサンプル](https://startbootstrap.com/templates/simple-
sidebar/)をRuby on Railsで試しに使ってみたのですが、  
以下のjQueryを`index.html.erb`に`<script>`タブで記述した場合は正常に動作しますが、  
`application.js`に記述するとToggleMenuボタンを押してもうまく動作しませんでした。

[code]

    $("#menu-toggle").click(function (e) {
        e.preventDefault();
        $("#wrapper").toggleClass("toggled");
    });
    
[/code]

jQuery自体が問題なく動作しているか確認のため試しに以下のスクリプトを`application.js`に  
記述してみたところ正常に動作していることが確認できましたので、jQuery自体の書き方の問題なのかなと思っています。

[code]

    $(document).ready(function () {
        $(".a").text("jQuery稼働テスト");
    });
    
[/code]

**application.js**

[code]

    //= require rails-ujs
    //= require activestorage
    //= require jquery
    //= require jquery3
    //= require popper
    //= require bootstrap-sprockets
    //= require_tree .
    
    $("#menu-toggle").click(function (e) {
        e.preventDefault();
        $("#wrapper").toggleClass("toggled");
    });
    
    $(document).ready(function () {
        $(".a").text("jQuery稼働テスト(稼働中)");
    });
    
[/code]

**application.html.erb**

[code]

    <!DOCTYPE html>
    <html lang="ja">
      <head>
        <title><%= full_title(yield(:title)) %></title>    
        <%= csrf_meta_tags %>
        <%= stylesheet_link_tag    'application', media: 'all' %>
        <%= javascript_include_tag 'application' %>
        <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
        <%= render 'layouts/shim' %>
      </head>
      <body>
        <div class="d-flex" id="wrapper">
          <%= render 'layouts/sidebar' %>
          <div id="page-content-wrapper">
            <%= render 'layouts/header' %>
            <div class="container-fluid">
              <%= render 'layouts/search' %>
              <%= yield %>
            </div>
          </div>
        </div>
      </body>
    </html>
    
[/code]

**index.html.erb**

[code]

    <div class="container-fluid">
        <h1 class="mt-4">Simple Sidebar</h1>
        <p class="a">The starting state of the menu will appear collapsed on smaller screens, and will appear non-collapsed on larger screens. When toggled using the button below, the menu will change.</p>
        <p>Make sure to keep all page content within the <code>#page-content-wrapper</code>. The top navbar is optional, and just for demonstration. Just create an element with the <code>#menu-toggle</code> ID which will toggle the menu when clicked.</p>
    </div>
    
[/code]

* * *

## 開発環境

  * Ruby 2.5.5
  * Ruby on Rails 5.2.3
  * Bootstrap4

フロントエンドは初学者でかなり基礎的な質問かもしれませんが、よろしくおねがいします。  
不足している情報があれば、お手数ですがコメントください。


CC BY-SA 4.0
2019-09-23T07:42:14.603
59216
2020-11-17T03:34:43.763
2019-12-15T06:31:51.290
32986
35942
question
ruby-on-rails jquery twitter-bootstrap bootstrap4
jQueryの<script>内の記述とファイルの記述の違い


インラインスクリプト (`<script> ~ </script>`) や、 `async`, `defer` 属性または `type="module"`
を持たない `script` 要素は、 **ブラウザがページの解析を続ける前に、読み込みと実行が行なわれます** 。

今回のスクリプトとファイルの読み込み箇所を見ると、 `application.js` は、ページの読み込みが完了することを待たずに `head`
要素で読み込まれ、実行されます。すると、スクリプト実行時点では `#menu-toggle`
を持つ要素が存在しないため、クリックイベントは期待したとおりに動作しません。

今回の場合、 `script` 要素に `defer` 属性を付与するか、

[code]

    <%= javascript_include_tag "blah.js", :defer => "defer" %>
    
[/code]

DOM の読み込みが完了してからクリックイベントを設定するなどの方法で、この問題を解決出来ると思います。

[code]

    $(function() {
      $("#menu-toggle").click(function (e) {
        e.preventDefault();
        $("#wrapper").toggleClass("toggled");
      });
    });
    
[/code]


CC BY-SA 4.0
2019-09-23T08:34:28.483
59218
2020-11-17T03:34:43.763
2020-11-17T03:34:43.763
32986
32986
59216
answer