JavaScript stops working after I load another page - javascript

I am new to JavaScript and trying to see why my on event listeners are not working. I have found similar posts on stackoverflow however the solutions are not working for me.
var search = function( event ) {
alert("bobo")
$.get("http://localhost:3000/search", {"search" : $("#Search-Bar").val()}, function(data, status){
if(status == "success")
$(".centering.text-center").html(data)
})
}
var attachListeners = function(){
$("#Search").on("click", search)
$("#SearchIcon").click( () => search() )
$("#Search-Bar").keypress( event => (event.KeyCode == 13 || event.which == 13) ? search() : undefined )
}
$(document).ready( function(){
attachListeners()
})
My website is not a single page application. I have attached the listeners to my navigation search bar where I load a different view through the nav links and my server(ruby back end) uploads a new html page.
On the first load I have noticed that document ready gets called and everything else works. The on and click. After I use my navigation and load a different html page my events disappear. In my html views my searchbar, searchicon, and a search text have consistent id's through out. I have tried using window.load() and putting an onload attribute for my body <body onload=attachListeners()> but neither worked(perhaps I didn't use them properly). I also noticed that when I render the next html views my docment.ready does not get called. However, if I forcefully refresh the page with an F5 the listeners are active again for that one html page. What am I missing here that I don't understand?

It looks like you might be using Turbolinks, from the Readme for the project:
When you follow a link, Turbolinks automatically fetches the page, swaps in its <body>, and merges its <head>, all without incurring the cost of a full page load.
Since this library makes it so the page ever only loads once, normal javascript window.onload, DOMContentLoaded, and jQuery ready events don't function after the initial page load and you have to use
document.addEventListener("turbolinks:load", function() {
instead of those. If you're new to turbo links, I suggest reading through that README to see what it's all about.
I've never understood why the Rails team would put something like this in rails and enable it by default, and in every single project I've made since they made that change the first thing I do is uninstall it, and when I forgot to do so, I spend several hours later in the project wondering why my javascript is broken.

Related

How to make DOM manipulation work on SPA view change and load?

I am currently working on a single page application (following this tutorial) and face two obstacles.
When changing the view of the SPA I try to execute functions and manipulate some elements (CSS, Text etc.) when the hash is changing and the location hash equals the mentioned names. Problem: it doesn't change the elements as expected. It appears to a problem with the views loading, because I was able to make changes to the whole body, like changing the background color. But not to the views the router is loading into a div with id app.
Solved. As a function, it does not execute when reloading the app.
window.addEventListener('hashchange', function(e){
if(location.hash=='#profile')
{
console.log('#profile');
}
else if(location.hash=='#cvedit')
{
console.log('#cvedit');
}
else if(location.hash=='#poll')
{
console.log('#poll');
$("#question_text").css("color","blue");
$("#question_text").text("Where's Waldo?");
}
else if(location.hash=='#about')
{
console.log('#about');
}
else if(location.hash='#home')
{
console.log('#home');
}})
When you reload the page browser does not fire hashchange event (MDN), that's why your code is not working as supposed to. You can use DOMContentLoaded event to catch reloads.
window.addEventListener('hashchange', yourCallbackFunction)
window.addEventListener('DOMContentLoaded', yourCallbackFunction)

How to invoke jquery that was called on $(document).ready(), when making pjax call?

I am a pjax beginner and not sure if the way I am implementing it, is correct. I had an old project with a lot of jquery. To organize it a little, the method that I followed was, to assign a unique ID to the body of each page <body id="Login">. In my layout, I had written the code:
var page = $('body').attr('id');
if(page !== '' && typeof self[page] != 'undefined')
self[page].init();
For page specific jquery, I had written something like this:
var Login = (function() {
var funct = {};
//any variables, only required on this page
funct.someFunction = function(){
//code
}
funct.init = function(){
//all the functions that are to be called on page load
}
return funct;
})();
Now, on each page load, only the code required on the page is executed. However, I am now making most of the link to a pjax link. So, on login page, there is a link:
<a data-pjax href="/register">Register</a>
and the layout has the code:
$(document).pjax('a[data-pjax]', '#pjax-container');
This opens up the register page. However, since the body id was still "Login", it didn't load Register.init().
How do I get past this?
I have never used pjax but according to their documentation you can add an event listener to run some code after a page change is complete
$(document).on('pjax:end', function(event) {
//
})
You should be able to do something with event.target, which should hopefully be the link that was clicked, in order to figure out what the new page is.

How to call a Greasemonkey function when a JavaScript link is clicked

So I recently started working on Greasemonkey scripts without much prior experience in JavaScript. It was going fine until I hit this roadbloack.
I'm writing a script for a page that has a small table of information. If a link at the bottom is clicked, the table expands fully in the page to display all information. I need to call a function in Greasemonkey when this happens, however, the link doesn't appear to have an ID or anything I can actually reference to watch it. It's simply this:
When it's clicked, the table expands and it then shows as true. I initially used the following to expand the table upon loading the page, but that broke several things:
window.location.href = ('javascript: expandFullTable(false)');
I've attempted using "click", "onclick", and even "mouseover" to have Greasemonkey detect when it's pressed but nothing seems to work. From what I can tell it's simply a link that calls a function, but after some significant searching I wasn't able to find out anything about how to reference it in my script. I'm sure it's incredibly simple, but it's frustrated me to no end.
You can hijack the function like this:
var oldExpandFullTable = unsafeWindow.expandFullTable;
unsafeWindow.expandFullTable = function() {
// Do something
alert("You clicked on that thing!");
// Call the original function
oldExpandFullTable.apply(this, arguments);
};
But since you tagged this jquery this should let you retrieve the link:
var link = $("a[href^=\"javascript: expandFullTable\"]);
It should work if jQuery is injected into your script with #require. If it's already in the page, you can add this before to access it: var $ = unsafeWindow.jQuery;.
And by the way, perhaps you should learn more about unsafeWindow to avoid security holes.

AJAX stop working on loading same site different PHP id

So i have a website that I'm doing for a school project. It's supposed to be like PasteBin. So on the right theres a different div (Uued koodid) that shows newest pastes. On click, they are supposed to show what they include using AJAX to refresh the left div. This only works for 4 times and then stops, but URL is still changing. After refresh it changes again and works again for 4 more times.
In main.js i have
...
$.ajaxSetup({ cache: false });
...
$(".uuedKoodid").click(function () {
$(".left-content").load(document.location.hash.substr(1));
});
...
EDIT:
Also other AJAX functions work. If I log in, I can switch between settings and profile perfectly but still cannot watch new codes
When you replace right menu with new code (from ajax call) you don't attach click event again on .uuedKoodid items so they don't do anything. You need to attach event again or attach it like this:
$(document).on('click', '.uuedKoodid', function () {
$(".left-content").load(document.location.hash.substr(1));
});
Edit:
As you noticed this will cause small problem. onclick event run before browser run standard link action. First you load ajax and then browser changes address. This way you are 1 action behind. Better solution than reading with delay (setTimeout) i think would be to read address directly from link:
$(document).on('click', '.uuedKoodid', function () {
var url = $(this).attr('href');
$(".left-content").load(url.substring(url.indexOf("#")+1));
});

Duplicate javascripts are getting loaded ajax

I'm developing a web based document management for my final year project. The user interacts with only one page and the respective pages will be called using AJAX when the user click the respective tabs (Used tabs for navigation).
Due to multiple user levels (admin, managers, etc.) I've put the javascripts into the correspondent web pages.
When user requests the user request everythings work perfectly except some situations where some functions are triggered multiple times. I found the problem. It is each time the user clicks a tab it loads same scripts as new instance and both of them will be triggered when I call a function.
to load the content I tired
.load and $.ajax(); non of them address the issue.
I tried to put all into the main page at that time my jQueryUI does not work. I tired
$(document).load('click', $('#tab_root li'), function(){});
Same issue remain.
Can anyone help me out this issue?
--Edit--
$(function){
$(document).on('click','#tabs',function(e){
getAjax($(this))
});
}
//method to load via AJAX
function getAjax(lst){
var cont = $(lst).text();
$.ajax({
url:'../MainPageAjaxSupport',
data: {
"cont":cont
},
error: function(request, status, error){
if(status==404){
$('#ajax_body').html("The requested page is not found. Please try again shortly");
}
},
success: function(data){
$('#ajax_body').html(data);
},
});
}
You can't undo JavaScript after it has been executed by simply unloading the file or removing the script element.
The best solution would probably be to set a variable in each JavaScript file you include in your ajax data and include them from an online inline JavaScript inside the ajax data along with a conditional like such:
<script>
if(!tab1Var) $.getScript("filename");
<script>
Older Solutions
You can manually unbind each event before setting them with off.
$(function){
$('#tabs').off('click');
$('#tabs').on('click',function(e){
getAjax($(this));
});
}
Alternatively you can initialize a global variable (eventsBound1=false) for each tab in the main html:
$(function){
if(!eventsBound1){
$('#tabs').on('click', function(e){
getAjax($(this));
});
eventsBound1 = true;
}
}
The tabs click event is only an example you have to do this for each time you bind an event in the scripts that are being reloaded.
if all the events are bound to things inside ajax_body, a final thing you can try is:
success: function(data){
$('#ajax_body').empty();
$('#ajax_body').html(data);
},
You have bind an event click on 'document' so getAjax() only replace the '#ajax_body' not the 'document'.
This means old event is still attached to the 'document' all you need is to unbind event by using $(document).off('click'); or change 'document' to other elements.

Categories