Intercept hyperlink clicks - javascript

I'm trying to intercept clicks on this link:
<a id="test-button" href="#">Test</a>
with this js:
(function() {
$('#test-button').click(function (event) {
console.log("This code never gets called.")
event.preventDefault();
$('#alert-placeholder').html(['<div class="alert"><a class="close"',
'data-dismiss="alert">×</a>',
'<span>"+message+"</span></div>'].join())
return false;
})
console.log("yes, this code loads");
debugger;
})();
but the URL '#' loads and the code in the click() function doesn't run. What am I missing?
I'm using this code in a flask app using bootstrap.

Seems like you're trying to attach an event handler to the element that doesn't exist yet
(function() {
})();
only creates a local scope but doesn't guarantee DOM to load. To confirm it - add console.log($('#test-button').length); to your code.
What you need is to wrap your code with
$(function() {
// your code is here
});
instead

Related

Invoke a javascript function after page loading is finished?

I use CookieBot in our html pages. CookieBot javascript doesn't load in test environment and throws a net::ERR_ABORTED 404 error.
When this happens, the loading spinner in the page keeps displaying after the page loading has been completed.
I tried following options to invoke a listener after page loading is completed. But none of them works:
document.addEventListener("load", (e) => {
console.log("document load");
});
document.addEventListener("DOMContentLoaded", function(event) {
console.log("DOMContentLoaded");
});
$(document).ready(function() {
console.log("ready!");
});
$(document).ready(function() {
console.log("document is ready");
});
$(window).on("load", function(){
console.log("window load!");
});
window.onload = function () {
console.log("window onload!");
};
I guess CookieBot script overrides my listeners. Here is an example where listener is not invoked. When you remove the CookieBot script it runs: https://jsfiddle.net/hkarakose/4by26Lr3/1/
How can I invoke a function after page loading is finished?
You can invoke a function after page loading with:
window.onload = function() {
//here you can write your function and invoke it.
}
Edit:
Maybe I didn't understand your request, but now I'm reading more carefully.
The problem is in the script, right? If you insert the script on HEAD, it will be loaded first.
You could insert the type of the script in this way:
type = "text / plain" with a data-attribute: data-attribute = "script-cookie".
Then change the type once everything has been loaded, like this:
window.onload = function () {
       var allPrefScript = document.querySelectorAll ("script [data-attribute =" script-cookie "]");
allPrefScript [0] .setAttribute ("type", "text / javascript");
}
Although #davilink92's answer works, I solved this issue in a more practical way.
I attached external script loading to window load event:
window.addEventListener('load', function () {
$.getScript("https://consent.cookiebot.com/uc.js?cbid=d180eb7a-8f13-4549-bacc-6d4a6dfb5da8&culture=en");
$("#global-loader").fadeOut("slow");
});
In this way, the script couldn't prevent the window load event listener to be invoked by the browser. And thus, I was able to remove the loading spinner after page is loaded.
I have the habit to use document.addEventListener("load", (e) => {console.log("loaded"); })
Can you show us more code to see if your problem is here? I think all of yours tests are correct and I dont understand why it isnt working.

How to wait to finish loading page on button click using JavaScript/JQuery?

I am having an Anchor link, on click of Anchor link, I am registering new JavaScript file html page.
On registering the JavaScript file dynamically, document is reloaded partially (As I see reload icon in browser for some time).
I want to call my JavaScript function once the script got registered (Obviously when reload icon get stopped in the browser). But the function MyJavaScriptFunction got called while document is still reloading.
Using setTimeOut resolves the issue but I don't want to use it as page loading time is not fixed. Please help.
The code I am using is as follow:
function addScriptDynamically(src, callback) {
var s = document.createElement('script');
s.setAttribute('src', src);
s.onload = callback;
document.body.appendChild(s);
}
addScriptDynamically('URL Of JS File',function(){
MyJavaScriptFunction();
})
What I tried so far...
Option-1:
addScriptDynamically('URL Of JS File',function(){
$(document).ready(function(){
MyJavaScriptFunction();
});
})
Option-2:
addScriptDynamically('URL Of JS File',function(){
$(window).load(function(){
MyJavaScriptFunction();
});
})
jquery has a function for this purpose.
Using jquery
$(function () {
//write your function code here.
})
This function is called only when the content of the page are first loaded.
2)
Using Javascript
window.onload = function(){
//write your function code here.
}

Moving inline Javascript to external .js file

I have some inline Javascript in my <body> that I'm trying to export to a .js file. I know that normally you would just copy/paste it over, sometimes including it in a document ready function, but something about this one is different. I'm not super fluent in JS and the code wasn't written by me (but was provided free online).
This is how the code is in my file. If you need any more info just ask!
<body>
<script>
(function (window, document) {
var menu = document.getElementById('menu')
, WINDOW_CHANGE_EVENT = ('onorientationchange' in window) ? 'orientationchange' : 'resize';
function toggleHorizontal() {
[].forEach.call(document.getElementById('menu').querySelectorAll('.custom-can-transform'), function (el) {
el.classList.toggle('pure-menu-horizontal');
});
};
function toggleMenu() {
// set timeout so that the panel has a chance to roll up
// before the menu switches states
if (menu.classList.contains('open')) {
setTimeout(toggleHorizontal, 500);
}
else {
toggleHorizontal();
}
menu.classList.toggle('open');
document.getElementById('toggle').classList.toggle('x');
};
function closeMenu() {
if (menu.classList.contains('open')) {
toggleMenu();
}
}
document.getElementById('toggle').addEventListener('click', function (e) {
toggleMenu();
e.preventDefault();
});
window.addEventListener(WINDOW_CHANGE_EVENT, closeMenu);
})(this, this.document);
</script>
</body>
UPDATE:
I was able to wrap the script in a scope (foo = function() {}) and get it to work externally by adding window.onload = function to the HTML page. This was suggested by #marmeladze and worked.
As suggested by #marmeladze, I was able to wrap the script in a scope (foo = function() {}) and get it to work externally by adding window.onload = function to the HTML page.
So what is the real problem to export it in an external js file?
As always i would copy and past code in a new js. Link it to HTML page and write functions that i need as attribute of HTML's tag (ex. "onload=functioname();" in body's tag).
As marmeladze said you can wrap all in an unique scope so you can call it in body.
Maybe you are doing it so if you maybe can explain better your problem would be great.

How to test the Knockout.js click binding with Jasmine

I'm having a problem with a jasmine test together with a knockout-template:
The html is similar to this:
<body>
<my-widget params="value: $data></my-widget>
</body>
the widget has a click-binding:
<div class="my-widget">
<a id="#clickme" data-bind="click: doSomething">Click me</a>
</div>
the widget-javascript is like this:
ko.components.register('my-widget', {
viewModel : function(params) {
this.doSomething = function() {
// doing something
};
},
template: {
require: 'text!../../templates/my-widget.html'
}
});
All of this works perfectly in production, but in Jasmine/Jquery, triggering a click on $('#clickme') does not execute the doSomething.
The following is an excerpt from my jasmine test (It's been greatly simplified but should contain the essentials):
beforeEach(function (done) {
require(['specHelpers', 'knockout'],
function (specHelpers, knockout) {
specHelpers.loadFixtureIntoPage("page.html", "myPage"); // template and id to use
expect($('#myPage')).toExist();
done();
});
});
it("WILL NOT TRIGGER MY CLICK", function (done) {
ko.applyBindings(myPage.pageViewModel, $('#myPage'))[0]);
setTimeout(function() {
$('#clickme').click();
// doSomething is not called :(
done();
}, 300);
});
When console.logging the #clickme element I can see that it is present.
It seems that the click binding in the widget does not get applied properly. However, when I run the test in bdd and it's over and failed - I can manually click this element and doSomething does get called.
What am I doing wrong? As I said, running the actual application works perfectly. It just seems that jasmine cannot handle the click bindings properly - I don't have this problem with the regular click events that are set in the document.ready
You really shouldn't be testing button clicks like that - you can be more certain if you just call the function doSomething() directly. Same way that you don't test any internals of JQuery yourself.
If you really really want to test events on a fixture, have you tried just
$("#clickme").trigger('click');
Also, double check that fixture is inserted into DOM in when you debug the test (say via browser)

How to replace $(document).ready function?

I got a problem and dont know how to fix it.
A have the following js script:
$(function () {
$.ajaxSetup({ cache: false });
var timer = window.setTimeout(function () {
$(".alert").fadeTo(1000).slideUp(1000, function () {
$(this).hide();
});
}, 3000);
$(document).on("click", "[data-hide]", function () {
if (timer != null) {
clearTimeout(timer);
$(this).closest("." + $(this).attr("data-hide")).hide();
}
});
});
<div class="well">
<h3>
<strong>#Model.Name</strong>
<span class="pull-right label label-primary">#Model.AverageRaiting.ToString("# stars")</span>
</h3>
<span class="lead">#Model.Description</span>
#Html.DialogFormLink("Update", Url.Action("UpdatePhoto", new {id = #Model.PhotoId}), "Update Photo", Url.Action("Photo"))
#Html.Action("InitializeAlerts")//When this action is executing the document was already ready (by the first time when full page was loading), so I have no chanse to catch any .alerts in js alert file after updating this partial for another one.
</div>
Sometimes I have a situation when document is ready ealier than I have any .alert classes im my partial view. So, how to rewrite the function to execute it after my partial view is updated with valid .alert?
You either need to wait around for $(",alert") to exist first, or you need to add your code inside the loading processing.
If you do not wish to couple your JS files tightly, you can broadcast a "panel loaded" event from the other script, which you catch at the document level.
e.g.
$.ajax({...}).done(function(loadedhtml){
$somepanel.html(loadedhtml);
$(document).trigger("panelloaded", $somepanel);
});
and listen for the generic "panel loaded" event in your main:
e.g.
$(document).on('panelloaded', function(panel){
// Do stuff here to the newly loaded panel
});
If you reload your Partial View i suppose the best thing is to place your code in .ajaxComplete() function.
It will be ready rigth after your ajax request done.

Categories