Rails 4 Delete link influenced by Template JS - javascript

I am using rails 4 with devise. All the Devise functionality works as expected including the "Sign Out" link given by the following piece of code:
= link_to "<span class= 'fa fa-power-off'></span> Sign Out".html_safe, destroy_user_session_path, method: :delete
I have since installed a template and ran into some issues. The JS in the template file seems to be causing some difficulty when I place my "Sign Out" link in a dropdown on the Navbar.
If I place the link in my normal body content, it does work. This led me to the template source code to try and figure out why this link was sending a GET request instead of a DELETE request when placed in a Template navbar dropdown. After I deleted the following piece of code, my link started working:
$('.dropdown-menu').on('click', function(e) {
e.stopPropagation();
var Target = $(e.target);
var TargetGroup = Target.parents('.btn-group');
var SiblingGroup = Target.parents('.dropdown-menu').find('.btn-group');
// closes all open multiselect menus. Creates Toggle like functionality
if (Target.hasClass('multiselect') || Target.parent().hasClass('multiselect')) {
SiblingGroup.removeClass('open');
TargetGroup.addClass('open');
}
else { SiblingGroup.removeClass('open'); }
e.stopPropagation();
var Target = $(e.target);
var TargetGroup = Target.parents('.btn-group');
var SiblingGroup = Target.parents('.dropdown-menu').find('.btn-group');
});
When I added the remainder of the Template js files, it stops working again, so I assume that something similar is done in one of the other files. Instead of removing pieces of JS, I am trying to understand what's happening. I understand that Rails uses it's ujs to trigger a DELETE request but why is the above piece of JS code hindering Rails from doing what it's supposed to?
PS. I am not fluent in JS so this might seem simple to somebody who knows JS extremely well.

I think the problem is with e.stopPropagation(); lines in the js code. These are likely not really needed. However, it may depend of kinds of other links in the dropdown menu. Just try to remove those two lines and check if everything works fine.

Related

Rails 6 Bootstrap v3.4.1, jQuery 1.12.4 popover function is showing the Title but not the Body?

I am re-writing an application called FILTERtrak and it has been going great so far. I have added a subscription model to it, enhanced it in all kinds of ways and have really started to like Ruby and Rails a LOT. It was originally written with Ruby 2.2.2 and Rails 4.2. I have upgraded it to Ruby 2.7.2 and Rails 6.1.5 (recently). Both versions of the APP I have running on Bootstrap v3.4.1 and jQuery 1.12.4
Of all of the issues I have run into and have SOLVED that are way more complicated it just seems so silly I can't seem to figure out WHY it is happening.
The old version of FILTERtrak is still up and running on Heroku. I haven't switched the APP to my new version as of yet because I am still upgrading it.
This Filter Condition Guide button when you hover over it on the old version of the APP shows the popover just fine. The VERY SAME CODE for some reason on the NEw version of this APP is popping up JUST the title but not the BODY?!? Which is really confusing to me???!?.
That tells me Rails is working, JavaScript is working, jQuery is working and bootstrap is working otherwise the popover title wouldn't come up. So why would it work for the title and NOT the Body when the code hasn't changed?!?
I have been trying everything I can think of today and searched about 1000 times. Seems silly I can't seem to resolve this small issue but I need to get this figured out as I need to use more popovers in the app in other places.
I tried writing another popover in another area of the APP and it worked fine?!? So I don't know if it is something due to the newer version of Ruby on Rails that is preventing the body part from not coming up or what it is.
I am NOT very good yet with the frontend stuff. I am just kind of starting to get used to HAML. The HAML line that deals with the toggling seems very complicated to me (starts with .btn.btn-xs). I tried using some online convertors to change that one line from HAML to HTML so I could better see what is going on but no convertor was able to successfully convert it. So out of luck that way. I re-wrote the line in HTML myself and it did the very same thing so I am not sure if it has anything to do with the HAML line that starts with .btn.btn-xs or not. Since it is still working with that haml line the way it is written I assume it isn't the issue but I have long run out of things to try.
Here is the HAML View that has the Button on it. (I am just including the relevant part of the view and other code, if anyone needs to see more to help let me know).
.text-center
.btn.btn-xs.btn-block.btn-primary{data: { popover: { content: "#condition-popover" }, placement: "top", toggle: "popover", trigger: "hover click"}, tabindex: "0" } Filter Condition Guide
#condition-popover.hidden
.popover-heading
What do the conditions mean?
.popover-content
%dl
%dt Operational
%dd
%ul
%li No soot on outlet/bypass
%li No cracks
%li Wire test passes
%dt Potentially Compromised
%dd
%ul
%li 0-20% soot on outlet/bypass
%li No cracks
%li Dents or impact damage
%dt Compromised
%dd
%ul
%li 20%+ soot on outlet/bypass
%li Any cracks observed
%li Wire test fails
Here is the JavaScript/jQuery file
(function() {
var ready;
ready = function() {
$('[data-toggle=popover]').popover({
container: 'body',
html: true,
content: function() {
var content;
content = $(this).attr('data-popover-content');
return $(content).children('.popover-content').html();
},
title: function() {
var title;
title = $(this).attr('data-popover-content');
return $(title).children('.popover-heading').html();
}
});
return $('#service_filter_condition').on('change', function() {
var selection;
selection = $(this).val();
switch (selection) {
case 'operational':
$('#customer_notified_container').fadeOut();
break;
case 'potentially_compromised':
$('#customer_notified_container').fadeIn();
break;
case 'compromised':
$('#customer_notified_container').fadeIn();
break;
default:
$('#customer_notified_container').fadeOut();
}
});
};
$(document).ready(ready);
$(document).on('turbolinks:load', ready);
}).call(this);
Here is a pic of what is currently coming up. You can see the heading and it even has it's correct styling for the title section.
Here is a picture of the very same code WORKING on the older version of the APP:
What it even more strange to me is if I inspect the html page, the data is all there! It is just not toggling the body section and I just am at a loss to understand WHY?!? I tried adding in container: 'body' in various places as I saw that can solve the body not coming up sometimes. All of the other examples I was able to find were not even similar to my own.
If anyone wants to see anything else please let me know.
I appreciate ANY input as to what could be causing this minor irritant from occurring.
It took me less time to re-write some DB queries that getting this tiny issue fixed, driving me crazy.
Thank You,
Scott
UPDATE: Here is the now working code:
JS
(function() {
var ready;
ready = function() {
$('[data-toggle=popover]').popover({
html: true,
trigger: 'hover click',
placement: 'top',
title: 'What do the conditions mean?',
content: function() {
return $('#popover-body').html();
}
});
return $('#service_filter_condition').on('change', function() {
var selection;
selection = $(this).val();
switch (selection) {
case 'operational':
$('#customer_notified_container').fadeOut();
break;
case 'potentially_compromised':
$('#customer_notified_container').fadeIn();
break;
case 'compromised':
$('#customer_notified_container').fadeIn();
break;
default:
$('#customer_notified_container').fadeOut();
}
});
};
HAML:
.btn.btn-xs.btn-block.btn-primary{"data-toggle": "popover", "tabindex": "0", "html": "true" } Filter Condition Guide
#popover-body.hidden{"data-toggle": "popover", "html": "true"}
= render 'filter_conditions_popover'
It now works properly. I ended up keeping the render line as I like having the information in a partial, much cleaner. I also kept the re-written Javascript as I think it is much simpler to read.
Ok I will have to file this one under What the Heck?!?
The issue was the popover would NOT display anything with the < dl > if HTML tag or %dl tag if HAML.
If you put the < dl > tag if HTML or the %dl if HAML the popover will IGNORE everything from that point forward. I proved this about 20 times over because I simply couldn't believe it. I can't make ANY sense of it but that it was it was. I even changed having the haml code under the #condition-popover.hidden line to use = render 'filter_condition_popover' and I tried using HTML instead of HAML thinking maybe it was some strange bug with HAML. Nope, HTML or HAML it will simply not allow the < dl > tag.
I figured this out by being frustrated. I put in To heck with you (I think I put something stronger than that actually) under the line where the body portion wasn't showing up and refreshed and to my complete surprise the line I put in under the #popover-content line showed up?!?
I then realized the code would return plain text?!? So I then tried using HTML instead of HAML and got the same results. So I started from plain text and then tried adding the tags back in and as soon as I put in the dl on HTML or HAML it stopped working. I did some Google/Bing searching and I can't find anyplace where that is a known issue. Even more bizarre as I said in my initial post the same code with the same tags are working on an older version of Ruby on Rails on the very same APP. Go figure that one out, I can't.. I don't know if it is one of the gems that has some bizarre conflict or WHAT the issue could be.
So I ended up using < h6 > in place of the < dl > and I added a bold in there as well and it looks almost identical. I also moved some of the HTML elements into the JavaScript side to simply the HAML portion. Lastly I ended up putting the pop over body data into a partial.
So if anyone runs into this I hope this information will help you. I will update my post with the new code I used. I even simplified the original JavaScript some hoping that would fix it but it didn't; that darn dl tag!

How do you make JS EventListeners work in Rails 6 / webpacker?

I'm trying to build a web app using Ruby 2.7.1 and Rails 6.0.3.2. On a page, I want an html popover to appear when the user clicks a button. I have some vanilla JS code that just removes a is-hidden class from my popover div as the user clicks the button, thus making the popover visible.
app/javascript/packs/project.js:
document.addEventListener('turboLinks:load', function () {
const createProjectButton = document.getElementById('create-project-button')
const projectPopover = document.getElementById('create-project-popover')
if (createProjectButton && projectPopover) {
createProjectButton.addEventListener('click', function () {
return projectPopover.classList.contains('is-hidden') ? projectPopover.classList.remove('is-hidden') : null
}, false)
const cancelProjectPopover = document.getElementById('cancel-project-popover')
cancelProjectPopover.addEventListener('click', function () {
return projectPopover.classList.add('is-hidden')
}, false)
}
})
I only want this functionality on one specific page of my application right now, so I've included project.js in the respective html file using a pack tag.
app/views/project/index.html.erb:
<html>
<body>
...
<%= javascript_pack_tag 'project' %>
</body>
</html>
However, this code does not work as intended. Clicking the corresponding button does not make my popover appear. I can confirm that the js file is correctly included in my application, as any console.log statement that I place in project.js will appear in the browser console. The js code in project.js is from a tutorial that used Rails 5, so I'm guessing it could have something to do with the recent switch from the asset pipeline to webpack.
Take a look at this line:
document.addEventListener('turboLinks:load', function () {
As you can see, it listens for the 'turboLinks:load' event, which won't happen in an application without TurboLinks.
Remember that javascript will execute immediately if you don't specify triggers (at which time your button will simply be unknown to your browser), so change this line to something like:
window.addEventListener('load', (event) => {
And your code will run as intended. Also note that I'm adding a listener to 'window' and not 'document', pay attention to which objects have which available event triggers.

Hash link disables relative link in HTML

I'm building a webapp that basically its an one-page webapp so to link to another part of the app is like this:
This is possible because I used JavaScript that contains animations and different stuff, the problem is that somehow, this method disables the possibility to link like this:
How can I have both links, without disabling the hash links?
EDIT: To be honest I dont know which part of the js its causing this behaviour because I took a template, but here is the js:
https://github.com/gomobile/template-list-view/blob/master/www/lib/appframework/appframework.ui.min.js
I believe you have a code like this
$('a').on('click', function(e) {
e.preventDefault();
});
You need to have an if like
if ($(this).attr('href').indexOf('#') == 0) {
e.preventDefault();
}
OR better change the selector to:
$("a[href^=#]").on('click', function(e) {
e.preventDefault();
// your animation here.
});
This code will just apply to anchor elements that have the href starting with #
------- update --------
You added a minified js :).
If you don't have the problem in your code, you can fix it with a hack like this:
$('a:not([href^=#])').on('click', function(e) {
window.location.href = $(this).attr('href');
});
But you should really find the issue, not fix it like this :)

How to make this grid work

I purchased a html5 theme that I am customizing for my church website. It has two cool features:
A tab script that allows for multiple items to displayed on one page.
a grid that will allow me to display sermons in a series in a neat and orderly way.
Both of these work well when used alone, but when I try to use the grid inside the tabs, no dice.
I am a design guy and know very little about Javascript functions and need help. Here is what the developer, who has not got back with me said to do:
"The grid function is built to run on page load and when you put it inside a tab it doesn’t initialize on page load so don’t work when you change tabs. A custom function needs to be built for this which will run the isotope grid on tabs change. Like:"
$(".nav-tabs li")click(function(e){
ADORE.IsoTope();
e.preventDefault();
}
I do not know where to add this or even if something else needs to be added. I have also attached a link where you can download my code (html/php and .js file) so you can see what is going on. Any help would be appreciated. Remember, I know very little about Javascript.
https://www.dropbox.com/s/jypfjz3a89soxh7/example.zip?dl=0
Add:
$(".nav-tabs li a").click(function(e){
$('a[href="' + $(this).attr('href') + '"]').tab('show');
var IsoTopeCont = $(".isotope-grid");
IsoTopeCont.isotope({
itemSelector: ".grid-item",
layoutMode: 'sloppyMasonry'
});
});
at Line 469 of your init.js and it should work for you. Thanks
You can try the following: inside your init.js add the following:
$(".nav-tabs li").click(function(e){
e.preventDefault();
ADORE.IsoTope();
});
e.g. in the first line after var ADORE = window.ADORE || {};
As you mentioned that you don't know much about javascript: the first line starts with
jQuery(function($){ ...
This takes care about that everything inside the { will get executed when jQuery is loaded.
I'm not sure if the e.preventDefault(); is necessary - this is used e.g. to prevent links from getting executed and attach a different function to the click() event, so it could be possible that Isotope is working when a tab is clicked, but the tab is not working anymore.
If this won't work, you can check with web dev tools if there are any script errors. In case you're unfamiliar with web dev tools, find some details for Firefox here: https://developer.mozilla.org/en-US/docs/Tools/Web_Console and for Chrome here: https://developer.chrome.com/devtools/docs/console

JQuery isn't recognising a #id selector, seems to be dependent on the URL

I'm writing a Ruby on Rails app. The following jQuery code is included in the head tag of the index.html.erb file, which is the template for all pages on the site.
<script>
$(document).ready(function() {
$("#select_mailshot").click(function () {
alert('mailshot');
document.location.href = "/products/1";
});
$("#select_blog").click(function () {
alert('blog');
document.location.href = "/messages";
});
$("#select_contact").click(function () {
alert('contact');
document.location.href = "/contacts/1";
});
});
</script>
(the alert steps are in there for debugging)
The following html code in index.html.erb
<ul>
<li id="select_mailshot">Mailshot</li>
<li id="select_blog">Blog</li>
<li id="select_contact">Contact us</li>
</ul>
The intention is that this effectively creates 3 buttons.
When clicking on any button from http://myurl.com/ it all works.
When clicking on any button from http://myurl.com/messages (get to this via the middle button) it all works
When starting from http://myurl.com/products/1 it all stops working (the alerts do not trigger). In fact when starting from http://myurl.com/anything/id it stops working.
I've been trying to solve this for hours now and the only difference between the working and non-working conditions is the url as far as I can see.
Can anyone shed any light as to what's going on here?
What does firebug tell you? Do you have javascript errors on the page? if so, what are they? Are you sure the jQuery library is included correctly in the deeper pages ( i.e. is it a relative path? )
Is this javascript inlined?
If not, then maybe the link is relative so when you try to load it from messages/40 you need ../script.js. Another solution is to use absolute URLs (http://myurl/script.js) or virtual (/script.js).
Thanks to cherouvim and digitaljoel.
This was due to javascript files being included relative to the current URL.
The following was included in the head tag
<script type="text/javascript" src="javascripts/jquery-1.3.2.js"></script>
I changed it to
<script type="text/javascript" src="/javascripts/jquery-1.3.2.js"></script>
(note the extra "/" in the src attribute) and everything works as expected.
I worked this out after checking the error logs on the server and in the browser.
Feeling a little dumb but a lesson well learned.
I was using FaceBox to create modal overlays and I couldn't figure out why I was having the same problem.
I turns out that the listener wasn't being attached to HTML elements until it was visible. (The items were available if I viewed source, but jQuery seemed not to attach a listener until it was visible.)
For anyone having the same problem, I'd suggest moving your click() code to a point where the HTML element you're attaching to is visible.
Also, I've found selecting by ID does give more problems than class. I have no idea why. (No, there were not duplicate IDs.)
Hope this helps someone with the same problem!

Categories