简体   繁体   中英

Javascript and Ajax Calls

I have a couple questions about loading javascript after an ajax call.

So I'm using ruby on rails and I have different pages loaded through ajax calls (I do this because I have an audio player that I want to keep playing as pages reload).

The problem is, when I change pages with ajax, the javascript doesnt reload (or work) on the new page.

For example, I have a grid system that sets the height of the grid image based on the width with javascript. The script doesnt work unless I reload the page or I put the script in a script tag at the bottom of the html file.

Is there any way to reload the javascript? I've tried location.reload() but that just refreshes the page and defeats the whole purpose. Thank you!

Here is an example:

show.js.erb

$('#results').html("<%= escape_javascript(render partial: 'songs/showcard', locals: { song: @song }) %>");

songs_controller

  def show
    respond_to do |format|
      format.js
      format.html
    end
  end

link to show page

<%= link_to song, remote: true do %><%= song.title %><% end %>

Here is the cardSize function I'm loading a in file called cardSize.js

$(document).ready(function cardSize () {
  var cardWidth = $('.card-image').width();
  $('.card-image').css({
    'height': cardWidth + 'px'
  });
});

In the UJS file show.js.erb you need to invoke the global functions that control the view / grid.

For example, if the global method for controlling the height etc. is implement_grid() , then, the file should look like:

$('#results').html("<%= escape_javascript(render partial: 'songs/showcard', locals: { song: @song }) %>");
implement_grid();

Items added to the DOM dynamically do not necessarily trigger any actions unless you specify them. You could look at binding listeners to html modifying on the div/table (grid) which would then invoke the height changes you're looking for if you'd rather keep that code out of the UJS files.

Also, that $('#results') can be considerably shortened:

$('#results').html("<%= j render 'songs/showcard', song: @song %>");

The problem you are having seems to be related to turbolinks. Turbolinks will refresh/change the content within the <body> tags of your document, not the scripts and stylesheets within the <head> tags of your document, which is where Rails loads all your custom written javascript.

So why does it work when you paste the javascript in a <script> tag at the bottom of your file? Because when you do that, the <script> tag is now within the <body> tags of your document. So when you change pages, the script gets freshly loaded in and can bind event handlers properly to the DOM elements on the page.

So how come it also only works when you completely reload the page? Because you have your jquery wrapped in $(document).ready(...) . When you manually refresh the entire page, turbolinks also gets completely refreshed and reloaded back into the DOM, so when you are on that specific page, your $(document).ready(...) handler will bind properly. But when you change pages and the content changes, the document is still technically ready and doesn't bind to that new page, so it won't execute the code inside of itself. Why? Because of how turbolinks works, the entire page isn't technically reloaded, just the content within the <body> tags, which to the code in your $(document).ready(...) call, looks like dynamically generated content that it can't bind to.

So what's the fix?

This may or may not call for the use of the jquery turbolinks gem . This will allow you to keep turbolinks and have your $(document).ready(...) calls everytime you change pages.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM