Turbolinks + lightbox (Rails 5) - ruby-on-rails

I know this question has been asked to death but I still can't resolve things in my app. I'm running a rails 5 app (with turbolinks and the fancybox lightbox gem) and have some page-specific javascript to display images on model show pages:
application.html.erb
<head>
...
<%= javascript_include_tag "application", "data-turbolinks-track" => true %>
...
</head>
<body>
...
<%= yield :page_scripts %>
</body>
show.html.erb
<% content_for :page_scripts do %>
<script type="text/javascript">
$(document).on('turbolinks:load', function() {
$("a.fancybox").fancybox();
})
</script>
<% end %>
I still get the classic response whereby the image loads up nicely upon first page visit or page refresh. Navigating away and back again stops the lightbox from working (seems to just hang in my case).
How do I use the 'turbolinks:load' feature to get this to work properly?

just use {parent: 'body'} and it will fix the issue with Turbolink.
$("a.fancybox").fancybox({parent: 'body'});
credit: Kirill Platonov

You can change into below code.
$(document).ready(function() {
document.addEventListener("turbolinks:load", function() {
$("a.fancybox").fancybox();
})
});
I hope this help you. You can go to details through this link turbolinks.

I'm not sure if this fully qualifies as an answer, but given that the scenario in this link was very similar:
https://github.com/fancyapps/fancybox/issues/1413
....I ended up following their advice and removing turbolinks from the show page using data-turbolinks="false".

I am not familiar with tubolinks, but keep in mind that $("a.fancybox").fancybox() simply binds click event to current elements. So, you probably have to reattach it after navigating. Another possible solution would be to use event delegation using selector option, example (using v3.1):
$().fancybox({
selector : '[data-fancybox="images"]',
animationEffect : "fade"
});

Related

When I use React_component, View_Helper provided by Gem called react-rails in Rails5, the contents of div become empty without reloading

I use react with Rails 5 using Gem called React-Rails.
However, although the component of react is loaded using ViewHelper called react_component, the contents of the div will be empty when the page is transitioned.
However, reloading will create the contents of the div.
I will explain in the code.
index.html.erb
<%= react_component('Hoge') %>
Hoge.js
import React from "react"
class Hoge extends React.Component {
render () {
return (
<React.Fragment>
<div className="row">hello</div>
</React.Fragment>
);
}
}
export default Hoge
The contents of the HTML when the page is transitioned are as follows.
<div data-react-class="Hoge" data-react-props="{}"></div>
There are no error logs in the browser and the Rails console.
When reloading this page
<div data-react-class="Hoge" data-react-props="{}">
<div class="row">hello</div>
</div>
I'm sorry. What you said was correct.
I write <%= javascript_pack_tag 'application' %> application.html.erb in Head tag above turbolinks.
Thank you.

Rails 5.2: How do I use page specific JS scripts when using Turbolinks?

I am writing some exploratory javascript for a page. It includes the following line:
dashboard_settings.addEventListener('ajax:complete', function(){
...
I have placed the script just before the closing body tag.
I notice that when I navigate to the page, the JS works as I expect it to and there are no error messages in the console. However, when I navigate away from the page, an error message displays in the JS console:
Uncaught TypeError: Cannot read property 'addEventListener' of null
I understand that this is something to do with turbolinks. However, I am unsure how to go about avoiding it without turning turbolinks off.
Is there any way at all that I can specify that the script loads for the one page only?
I have tried the following without success:
<%= yield :page_scripts %>
<% content_for :page_scripts do %>
<script>
document.addEventListener('turbolinks:load', function(){
...
You can add the listener only if the element exists.
if (dashboard_settings)
dashboard_settings.addEventListener('ajax:complete', function(){...})
Or, if you wan't to add it only for a specific page, you could add a yield statement on your layout and only set it's content con the desired page
#layout
<html>
<body>
...
</body>
<%= yield(:after_body) -%>
</html>
#your view
<%= content_for :after_body do -%>
<script>
document.addEventListener('turbolinks:load', function(){
dashboard_settings.addEventListener('ajax:complete', function(){...})
})
</script>
<%- end -%>

Loader image for rails controller action

Hi In my rails application on one page I have links which links to another page which will call some APIs, so that page loads slowly. I need some indication till the page renders, how to accomplish this? I have searched most of them says solution for AJAX request but here its not a ajax request.....
Add in your application.js
$(document).ajaxStart(function(){
showloader()
});
$(document).ajaxStop(function(){
hideloader()
});
function showloader(){
$(".main-loader").show()
}
function hideloader(){
$(".main-loader").hide()
}
Add in your application.html.erb
<div class="main-loader" style="display: none;">
<div class="loader-div"> <%= image_tag "loader.gif" %> </div>
</div>
And Also Add loader image in your assets images folder

Using devise gem, how does it prefill form values in the edit form and how can this be replicated elsewhere?

I am attempting to place the sign in, sign up and edit forms (from devise) into Bootstrap modals using partials. I have successfully done this by creating partials for the forms (wrapped in the modal code) and rendering them in application.html.erb as follows:
<%= render 'articles/sign_up_modal' %>
<%= render 'articles/sign_in_modal' %>
<%= render 'articles/edit_profile_modal' %>
At the top of application.html.erb I have:
<script type="text/javascript"> $(function () { $("#sign_up").modal({show:false });</script>
<script type="text/javascript"> $(function () { $("#sign_in").modal({show:false });</script>
<script type="text/javascript"> $(function () { $("#edit_profile").modal({show:false });</script>
Where "sign_up", "sign_in" and "edit_profile" represent the id's of the modals from the partials. The modal is then displayed by clicking a button in the _header.html.erb partial:
<%= link_to '<button type="button" class="btn btn-primary">Edit Profile</button>'.html_safe, "#edit_profile", "data-toggle" => "modal" %>
Everything works great except the Edit Profile modal form does not prefill the form with the appropriate values unless I am also on the edit page when I click the button to display the modal. How can I get the Edit Profile modal form to prefill the users data no matter which page they are on in the background?
Does this make sense? Please tell me how I might clarify my question. Thanks!
The answer was provided to me by u/alec5216 on reddit.
He said:
Take a look at the devise source.
https://github.com/plataformatec/devise/blob/master/app/views/devise/registrations/edit.html.erb
You'll see the form is bound to the "resource" variable which is going to be an instance of a user model. I bet if you use current_user in the partial instead of resource you'll have the desired effect.
This worked. See HERE for the full conversation.
In this case you will probably have to make an AJAX call to fetch the required data.
The data itself can either be JSON (for client-side rendering) or the complete html form rendered with the layout: false option. I usually go for the former because it is faster and easier to implement, unless your project is a single-page js application.
You can find more information on bootstrap ajax modals here on StackOverflow.

Best way to include javascript in Rails via content_for

I have some pages in my Rails application that need one off bits of javascript to be included, ideally just before the </body> tag. There is no real need to have this javascript included on EVERY page since most don't use it. I've found a way to make this work, but I think the code is terrible.
How would you do the same thing or how would you refactor the existing code?
View simplified, sample code on gist.github.com:
https://gist.github.com/scottswezey/ffc7bf52041b976b710a
(Or see the same code below:)
application.html.erb (Layout):
<!DOCTYPE html>
<html lang="en">
<head>
...
</head>
<body>
...
<script>
$(function() {
<%= yield(:js) %>
});
</script>
</body>
</html>
some_view_file.html.erb (View):
<%
str = <<END_OF_STRING
$('.modal').modal()
END_OF_STRING
content_for :js do
str.html_safe
end
%>
Don't ever do it this way: JavaScript doesn't belong in HTML. Just put an appropriate <script> tag in the page, referring to an external JS file, something like this:
application.html.haml
!!!
%html
%head
= yield :javascript
%body
= yield
view file
- content_for :javascript do
= javascript_include_tag 'modal'
app/assets/modal.js
$(document).ready(function() {
$('.modal').modal();
}
This keeps everything nicely separated.
Is it possible to add a .js.erb partial with your JS and render it under the body?
edit: Check out this answer: https://stackoverflow.com/a/10113547/1283742

Resources