jQuery mouse events don't fire - javascript

I have a really strange problem. My example code works [here][1] quite fine, but I have the exactly same code in my aptana studio editor and when I try it in Chrome or the Eclipse browser the events just don't fire. I can't imagine what's the problem, because it's exactly the same code ...
HTML
<!DOCTYPE html>
<html>
<head>
<title>OrderScreen</title>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
<script src="js/script.js" type="text/javascript"></script>
</head>
<body>
Test
</body>
</html>
jQuery
$("a").mouseup(function() {
clearTimeout(pressTimer);
// Clear timeout
return false;
}).mousedown(function() {
// Set timeout
pressTimer = window.setTimeout(function() {
alert("hcbdhaf")
}, 1000);
return false;
}).click(function() {
alert("dfsdg");
});

If your code is really as quoted, the problem is that the elements don't exist as of when you try to hook event handlers to them. jsFiddle's default settings hide this problem from you. (Look on the left, and you'll see that your code isn't run until the load event fires — which is very, very late in the page load process.)
To fix it, either:
Move your script tags to the end of your document, just before or after the closing </body> tag. By the time the browser runs your script, the elements will exist. This is the recommendation of the YUI team and Google's web engineers like it too.
Use jQuery's ready event.
In conjunction with either of those, you might also look at using event delegation instead of directly hooking up events on the elements. Your mouseup and mousedown handlers will get attached to each a element individually. That's a lot of hookups. If there's a container that all of those a elements are in (body or better yet, something nearer), you might instead hook the event on that container (since those events bubble) and then check to see if the event originated in an a element. jQuery supports event delegation, doing most of the hard work for you, via delegate (which I like because it's so explicit) and more recently, one of the half-dozen variations of arguments you pass to on.

Related

How to add client DOM javascript event handler when using Blazor Server?

...yes I know... Blazor Server is served side, and I can handle DOM events with my C# code at server side... still it makes sense to add a pure client side javascript event handler and surprisingly it seems it is not possible, because _framework/blazor.server.js swallows them...
Here are the simplest isolated steps to reproduce what am I doing.
Create a Blazor App using VS 2019 template, choose Blazor Server App in the next step.
In Index.razor add a line anywhere <div id="test">Hello, click me!</div>
In _Host.cshtml add the following script after or before the already existing <script src="_framework/blazor.server.js"></script> line:
... pulling my hair out, I can not insert code block, here, see after the step 4...
Run the app, and press F12 to see the console output.
here is the script in step 3:
<script>
console.log("script is executing...");
console.log("element found, its innerText is: " + document.getElementById("test").innerText);
document.getElementById("test").addEventListener("click",
function() {
console.log("click handler called");
});
</script>
Question
Am I missing something? Is it possible to make this work, without a server roundtrip? If it is not possible, then many of the existing javascript widgets, and jQuery plugins how will initialize themself?
What I've tried so far?
Use other event for example mouseup: does not work.
Change the order of my custom script and the <script src="_framework/blazor.server.js"></script> : neither order is working...
Comment out the line <script src="_framework/blazor.server.js"></script> for diagnostic reasons: The event handler now called and I see the console output in the browser: "click handler called"
To answer in advance "why I would like to do this?":
I would like for example implement a DOM behavior where clicking on an element it changes something in its attributes. I do know, I can attach a C# handler, then call a back javascript function but I would not like this roundtrip. Besides of that, maybe there are many existing javascript plugin and lib which relies on that its initialization script attaches event handler on DOM.
...based on the documentation what agua from mars pointed to in his comment:
(If anyone has better idea then please answer or comment)
If I run my client side script which is attaching the event handlers after the server OnAfterRender event, then it works. If I run it any way before (for example in OnInitialized event) it will not work:
So here is a working solution:
Index.razor
#code
{
protected override void OnAfterRender(bool firstRender)
{
_jsRuntime.InvokeVoidAsync("attachHandlers");
}
}
_Host.cshtml:
window.attachHandlers = () => {
document.getElementById("test").addEventListener("click", function()
{
console.log("click handler called");
});
};

How to reinitialize button that has been removed from the DOM?

So I'm running into an issue using a program called XCrud, that is supposed to help with database management. The gist of the issue is that the program removes and reinserts its buttons into the DOM, causing my click functions in JQuery to stop working.
$('a[class="btn btn-warning xcrud-action"]').on('click', function() {
intvId = window.setInterval(cleanup, 200);
});
This button is supposed to reset an interval that helps the user along the workflow of the database, but as aforementioned, the button will only trigger once.
Thanks for the help everyone
Use this syntax instead, to delegate the event handler to all members of the class, present and future:
$('parent').on('click', 'a.btn.btn-warning.xcrud-action', function() {
intvId = window.setInterval(cleanup, 200);
});
Where parent is an element higher up in the DOM tree than the a element you're targeting. (I'm assuming with this selector that all the classes in your example apply to a single a element.) This syntax supersedes the older delegate method.
The point is that you are attaching the handler to an element that isn't going to come and go (no matter how volatile your DOM is, you can always use document if you have to), and applying a filter (in terms of a selector) to the element to only apply the handler to the type of contained element that you want. As the doc states:
Delegated events have the advantage that they can process events from descendant elements that are added to the document at a later time. By picking an element that is guaranteed to be present at the time the delegated event handler is attached, you can use delegated events to avoid the need to frequently attach and remove event handlers.
Unfortunately, the doc also fails to spell out that the [selector] argument of the on method delegates the handler to members of the classes in the selector. You can find that out by looking at the older delegate doc, and examining the examples that they give to convert from delegate to on.
Here's a little working example:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>
Test
</title>
<!--jQuery and jQuery-UI files-->
<script src="includes/jquery/jquery-2.2.3.js"></script>
<script src="includes/jquery-ui/external/jquery/jquery.js"></script>
<script type="text/javascript">
$(document).ready(function () {
$('form').on('click', 'button.test1.test2', function(e, ui){
$('form').append('<button type="button" class="test1 test2">"Test"</button>')
alert('click');
});
});
</script>
</head>
<body>
<form>
<button type="button" class="test1 test2">Test</button>
</form>
</body>
</html>
Any new button will have the same behavior as the original one.

jQuery is not catching click on some content loaded

I'm using jQuery 1.7.2 with Zoomy and jmpress plugins. Also I'm using boilerplate+bootstrap downloaded from initializr.com
I'm trying to create a "game" like [Waldo/Wally] when you have to find some character in a photo. Each photo has a different character to find.
I'm using jmpress as a presentation plugin to go from one photo to another every time the character is found. jmpress loads the content trough ajax (and I need that behavior) because I want a pretty fast load of the web.
Problem: The .on("click") event is not being caught on one of the elements that exist inside the content loaded.
As an example, I'll explain my problem with one of this characters (just taking parts of code).
I have in my index.html some divs to load the characters, I'll take the nurse character:
<div id="nurse" class="step container" data-src="women/nurse.html" data-x="7500">
Loading...
</div>
The jmpress load the data-src (women/nurse.html) trough ajax when the user is near to that div (step). It loads great.
This is the code of nurse.html
<script type="text/javascript">
new Image().src = "img/nurse_big.jpg";
</script>
<div class="descripcion">
<p>Bla, bla, bla.</p>
</div>
<div class="imagen">
<img src="img/nurse.jpg" alt="Find the nurse" />
</div>
As you can see, I have two divs loaded inside the #nurse div (that has .step class).
I have this code on my js/script.js file when I try to catch the click event:
$(".step").on("click", function(event){
console.log(event.target);
});
I'm also trying with "body" tag to see what happens
$("body").on("click", function(event){
console.log(event.target);
});
If you check the console while the message is showing (div.descripcion) it catch the event and print. But, after the div.descripcion is removed and the image appears, it dosen't. Like if that div.imagen or even elements inside it dosen't exist. The click event is not catched. I tried to catch mousemove event and It does.
Why is not catching the click? any idea?
You can see a working version: [Removed]
And the not working version: [Removed]
UPDATE: I forgot, if I use .on("click") it dosen't work. But if I use .on("mousemove") for example, it works. That's the weird part. .on() is working, but not for the click event.
UPDATE 2: I have removed the links of the live examples because they where dev versions. I'll publish the link to the final work when is published. Thanks to all of you for taking the time. Specially to #Esailija that gives me the answer.
Once again, you need to use on for content loaded later on:
$("body").on("click", ".step", function(event){
console.log(event.target);
});
Replace body with the closest static element that holds the .step elements.
Static means exist in the DOM when the you execute the line:
$(...).on("click", ".step", function(event){
Example:
$('#ContainerId').on("click", ".step", function(event){
// Do what you want.
});
Delegated events have the advantage that they can process events from descendant elements that are added to the document at a later time. By picking an element that is guaranteed to be present at the time the delegated event handler is attached, you can use delegated events to avoid the need to frequently attach and remove event handlers
on docs
The zoomy plugin you are using does this:
'click': function () {
return false;
}
Since the element you are clicking when you are on the image, is actually the zoomy elements, those get to handle the events first. They handle it by returning false, which means doinge.stopPropagation() as well as e.preventDefault(). So the event won't even come to .imagen.
There is also unterminated multi-line comment in your code, not sure what that does but it can't be good. Consider just deleting code instead of commenting it out.
Anyway, clearing everything like this:
$.cache = {}; //Can also do $("*").off() I think
And then doing:
$(".step").on("click", ".imagen", function(event){
console.log(event.target);
event.preventDefault();
});
And it works fine. You might wanna edit the plugin to do this instead:
'click': function (e) {
e.preventDefault();
}
Alternatively you could look for a plugin that is developed by someone who knows what the hell they are doing or write it yourself.
In the documentation in http://zoomy.me/Options.html you can allow the plugin to have a clickable area by adding in true to the clickable option.
So when calling zoomy() on a element all you have to do is add a little bit of code inside the zoomy function.
$('.element').zoomy({clickable:true});
and that should fix everything,
The alternative way to catch the function on click event is just like below.
<div onclick="fireClickEvent();" > Just firing the click event!</div>
function fireClickEvent() {
console.log(event.target);
}

Why the jQuery events are not fired?

I thinkg I doing something wrong, but the events only works if the selector is document. Otherwise, not happens.
HTML
<html>
<head>
<!-- the libraries references here -->
</head>
<body>
<div id="canvas"></div>
</body>
</html>
Javascript
/* Click on canvas */
canvasClickEvent = function(e){
if(e.shiftKey){
selectedElement = $(this).attr("id");
}
}
/* Events */
$(document).ready(documentLoadEvent);
$(document).click(canvasClickEvent); //this works, but is wrong
//$("#canvas").click(canvasClickEvent); --this is what I want, but not works
$(document).dblclick(canvasDblClickEvent);
If I replace the document by the div name like $('#canvas').click(canvasClickEvent);, the click event is not called. It's only works if the selector is document, but the element passed to the function always has the attibs like undefined.
What might be happening?
What is happening is that event is attempting to bind the event before the DOM element exists.
If you wrap the events inside of the ready() method you guarantee that the domain exists before your event attempts to bind.
$(document).ready( function () {
$("#canvas").click(canvasClickEvent);
}
The ready() method is dependent on the browsers DOMContentLoaded event which basically means the DOM is completely loaded in the browser, but does not necessarily mean all the media on the page has completely loaded. Once all media is loaded the onLoad browser event fires.
It seems like you put your JavaScript code BEFORE the html code. So, when the JavaScript code runs, the elements to be dealt with is not loaded into the DOM yet. (That's why you got "undefined")
Just put your script AFTER the related HTML code. Or put it inside the pageLoad event:
$(function(){
....
})

How to fire "onload" event on document in IE

I am currently developing Unit Tests for a Javascript method that detects the readiness of the document. This code is already at framework level, so please avoid mentions of this being already implemented in jQuery or another library.
I have successfully simulated the 'readystatechange' change event with the following code:
var event;
event = document.createEventObject();
event.type = 'readystatechange';
document.fireEvent('onreadystatechange',event);
I failed to do the same for the 'load' event. The following code results in an invalid argument error in IE7, thrown by the call to fireEvent on the last line:
event = document.createEventObject();
event.type = 'load';
document.fireEvent('onload',event);
Has anyone done this, or failed to do this before? I am also interested in any suggestion to fire the event in a different way.
Edit: following the suggestion by Crescent Fresh, I changed my code to:
event = document.createEventObject();
event.type = 'load';
document.body.fireEvent('onload',event);
There is no more error, but the listener for 'onload' does not fire. Here is how I configured it:
document.attachEvent('onload',listener);
According to this page at MSDN, there's no onload event for document.
You want either window.onload or document.body.onload. These are identical in IE: for historical reasons, <body onload="..."> actually sets window.onload, so MS decided to make document.body.onload an alias of window.onload.
The problem with this is - as Eric mentioned in the comments - that there doesn't seem to be a way to manually fire window events, which means that there might not be a solution for Eric's problem.
For some reason, it appears that IE overrides the onload property of window with an empty object after the DOM is loaded. At least that is the case when you try to access it from within any event handler of a DOM element...
<!DOCTYPE html>
<html>
<head>
<title>Test by Josh</title>
<script type="text/javascript">
window.onload = function() {
alert("Test");
}
alert(typeof window.onload);
</script>
</head>
<body>
<h1 onclick="alert(typeof window.onload);">Test</h1>
</body>
</html>
In this situation, you'll see that window.onload is recognized as a function initially, then you see the "Test" alert. When you click on the heading, you'll see that window.onload is now an object. I tried iterating through the properties of the object, but it's empty. This is not cool.
One lame workaround is to grab the function in the accessible scope and assign it to a different property that you can fire at your convenience...
<!DOCTYPE html>
<html>
<head>
<title>Test by Josh</title>
<script type="text/javascript">
window.onload = function() {
alert("Test");
}
</script>
</head>
<body>
<h1 onclick="window.onloadfix()">Test</h1>
<!-- Could potentially be injected via server-side include if needed -->
<script type="text/javascript">
window.onloadfix = function() {
window.onload();
}
</script>
</body>
</html>
I can't think of any other way to address this issue right now.
The load event will fire when the document (including external resources such as images) has fully loaded, and not before.
What results are you getting from your attempts to fire readystatechange? Does the readyState value actually change at all? Whether or not, that's not of much use either: either you fire the event with a readyState that hasn't changed, or you do so with a readyState that isn't a valid reflection of the state of the document.

Categories