I made this simple code to understand how it works:
<div title="1">
one
<p title="2">two</p>
</div>
<br />
<div id="result"></div>
<script src="jquery-1.8.0.min.js"></script>
<script>
$(document).ready(function(){
//$("body").on("mouseover","*",function(){
//$("body").on("mouseenter","*",function(){
var html = $(this).attr("title");
console.log(html);
$("#result").text(html);
//});
});
</script>
When I use mouseover, the problem is that when I point to two, the event listener will first fire on two and then on one, so the effect will be like I pointed to one.
On the other hand, if I use mouseenter, the problem appears if I point to two without pointing to one, the effect will be one.
And if I point to one, then to two, and then to one again, there will be no effect at all because two is part of one so js sees that I'm still in one and won't work.
Is there any solution to this ?
this is due to event bubbling, you can refer for solution
http://api.jquery.com/event.stoppropagation/
Also you can use global flag variables to detect events
Basically, the difference between mouseover and mouseenter is
Similar to mouseover, mouseenter differs in that it doesn't bubble and that it
isn't sent when the pointer is moved from one of its descendants'
physical space to its own physical space.
If you use mouseover, it will bubble up, so the event listener will be triggered on pointed element and its ancestors (your 1st problem).
If you use mouseenter, it won't be triggered when the pointer is moved from one of its descendants' physical space to its own physical space (your 2nd problem).
What you need is mouseover without bubbling. There's no specific event for that, but you can manually prevent it from bubbling using stopPropagation:
$("body").on("mouseover", "*", function (e) {
e.stopPropagation();
var html = $(this).attr("title");
console.log(html);
$("#result").text(html);
});
Demo
This problem can be easily fixed by adding "[title]" to the selector.
You can find the working demo here in jsfiddle
Related
I have a clickable item, which contains child elements, too. My problem stems from wanting to animate the :active state of the clicked item by using a 1px translation.
The mousedown of the click lands on a child element
The 1px translate moves the child element from under the mouse pointer
The mouseup event now happens on the parent element
This results in the click getting canceled. I can prevent the child element from catching the click using pointer-events: none in CSS, but since it's both new and unstable, I'd love to find a more compatible fix. For now, I've settled on just sticking a transparent DIV on top of the whole item, but that's ugly.
Exaggareted demo in this pen: http://codepen.io/JonFabritius/pen/mJuzy
Try clicking the bottom half of the orange bar, the pointer remains on top of the child element. Then click on the top half, which causes the element to move from under the pointer.
It's probably staring me in the face, but I haven't been able to find a simple fix- any ideas appreciated.
Disclaimer: I don't jQuery.
This is a response better considered as a comment, though with the addition of code.
You say that "the click target is the parent" - Sorry to be a little thick here, but when you say it's the click target, is the parent the element that has the event listener attached to it, or by click target, do you mean that it is the value returned by evt.target? (Where evt is the single variable passed to the event handling function)
To better illustrate what I'm getting at, consider the following code:
JS portion:
window.addEventListener('load', mInit, false);
function mInit()
{
document.getElementById('clickTarget').addEventListener('click', handleClick, false);
}
function handleClick(evt)
{
console.log(this.id + ': is the id of the "this" element');
console.log(evt.target.id + ": was the id of the evt.target");
}
HTML portion:
<body>
<div id='clickTarget'><a id='link1'>Link1</a><a id='link2'>Link2</a></div>
</body>
Now then, when you click on link1, the output shown in the console is:
clickTarget: is the id of the "this" element
link1: was the id of the evt.target
Predictably, clicking on link2 shows the following:
clickTarget: is the id of the "this" element
link2: was the id of the evt.target
So, you can clearly see that in this example, the <div> is the parent of the two <a> elements.
Yet, in each instance the target is different - it's not the parent, it's the actual element that was clicked.
You've used jQuery, which, while simple to add functionality, hides implementation details, slows JS execution and (usually) adds unnecessarily to page-weight. Your code is very short and sweet, yet what is being returned requires some investigation - it's certainly not obvious.
As a side note, a quick look at the jQuery Docs: jQuery .delegate tells us that as of jQuery 1.7, the preferred method use to achieve this functionality is .on() - it's likely of no consequence, but one never knows..
Turns out if you use the current .on syntax, it works fine:
$(function() {
// target ON event, delegate
$('#container').on('click', '.item', function() {
$('.item').append('*');
});
});
UPDATE Could you do this with a custom class? This seems to work so long as the pointer doesn't leave the .item element. Child elements behave as expected.
$(function() {
$('#container').on('mousedown', '.item', function() {
$(this).addClass('active');
$('.item').append('*');
}).on('mouseup', '.item', function() {
$(this).removeClass('active');
});
});
DEMO: http://codepen.io/anon/pen/lponk
I would like to design something similar to what can be seen on http://www.thedana.com/ by the "Check availability" button - I've used the jquery.js file from w3school.com and got the following so far: http://quaaoutlodge.com/drupal-7.14/ (Book Now tab). Now as you realize, it is very touchy and fades out sometimes when it shouldn't (when the cursor is still in the middle of the field) how can I make this nicer, more user friendly?
Thanks!
Ron
Update:
I tried to implement that but it doesn't quite work as I would like to show my "fade" div upon hovering over "book" and keep it up as the cursor moves down, over "fade" how do I accomplish this?
Url:http://quaaoutlodge.com/drupal-7.14/
Put the div#fade inside of the div#book, that will solve half of your problems. You will have to adapt the CSS as well for this change.
Another very important point to learners is that jQuery provides unobtrusive cross-browser event listeners attaching. That means, inline JS in the html as onmouseenter="handler()" is not just unnecessary and technically ugly - mixed structure with behavior -, it also pollutes the global scope with function names.
That's one of the reasons people advertise against W3School.
But back on topic here's a solution using the DOM Ready handler and a hover one:
Fiddle
HTML
<div id="book">
Book Now
<div id="fade">TEST</div>
</div>
JS
$(function() {
var fade = $('#fade');
$('#book').hover(function() {
fade.fadeIn();
}, function() {
fade.fadeOut();
});
});
Again, you will have to rework the CSS removing the position:absolute and margins from #fade.
Can you try with jquery's .mouseleave instead of the generic onmouseout?
http://api.jquery.com/mouseleave/
"The mouseleave event differs from mouseout in the way it handles event bubbling. If mouseout were used in this example, then when the mouse pointer moved out of the Inner element, the handler would be triggered. This is usually undesirable behavior. The mouseleave event, on the other hand, only triggers its handler when the mouse leaves the element it is bound to, not a descendant. So in this example, the handler is triggered when the mouse leaves the Outer element, but not the Inner element."
i have 5 elements in a page.
i have selected them using class names $('.class')
i am trying to perform a function for those selected elements irrespective of event (click or hover or watever).
eg:
$('.class').hover(function(){definition1});
$('.class').click(function(){definition1});
i dont want to have 2 seperate event as above 2, instead i want the function to be executed irrespective of whether its hover or click event.
$('.class').bind('click mouseenter', function() {
// Go nuts.
});
(if using jQuery >= 1.7, swap bind() with on().)
Keep in mind that hover()'s second argument is for mouseleave event, which you haven't written anything for here.
If you want to cover most events, pass in 'blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error' as the first argument.
You could also try to detect them with code by iterating over properties that start with on, but it sounds too flaky to me.
To bind multiple events to one element in jQuery 1.7 and later you can do the following by separating event names by spaces:
jQuery('.class').on('click hover mousenter mouseleave', function(event){
// do what you need to do
});
which you can see in jsfiddle.
But: be careful, because you can easily fire the event too much times (more than necessary and more than enough). By binding so many events some may be called unnecessarily (as in the example above the code will be fired twice when the mouse cursor will leave the element it hovered over).
If you do not want to exec a function without any event put it in
$(function(){
function test(){definition1}
});
then in html
<body onload="test();">
Basically my client wants hidden navigation to appear when mouseover an image. I've solved the problem of the navigation not hiding when you mouseover the navigation and then hiding when you leave the navigation. There are two problems I'm running into and I've tried a variety of different combinations that I thought would work, but of course didn't. The two problems are:
When you mouseout the image without mouseover the navigation then the navigation needs to hide, as of right now it stays open until you either mouseover the image again or mouseleave the navigation.
Second problem is when you mouseleave the navigation directly to mouseover the image it loops the function and hides the nav then opens the nav again, I've tried changing slideToggle to show, but that causes a whole bunch of other issues.
Right now the code is behaving as close to how I want it and could be considered acceptable, but I'd love to know how to solve the problems above. I thought about using the hoverIntent plugin to sense the mouse movements and only trigger the functions once the mouse has slowed, but couldn't get it working properly. Clearly, I am a novice when it comes to javascript and jquery so please forgive me, but I'd really appreciate any help.
Here is my code
$(document).ready(function(){
$(".nav-body").hide();
$(".nav-head").mouseover(function(){
$(this).next(".nav-body").slideToggle(600);
$(".nav-body").mouseleave(function(){
$(this).hide(700);
});
});
});
Here is my html:
<p class="nav-head"><img src="/images/face-btn.jpg" /></p>
<div class="nav-body">
<ul><?php wp_list_pages('title_li=&child_of=12&depth=1'); ?></ul>
</div>
Markup change
<div class="nav-container">
<p class="nav-head"></p>
<div class="nav-body"></div>
</div>
Javascript
var eventHandler;
eventHandler = function(){$(".nav-head").one("mouseover",function(){
$(this).next(".nav-body").slideToggle(600);
$(".nav-container").one("mouseleave", function(){
$(this).find(".nav-body").hide(700, eventHandler);
});
});};
eventHandler();
The first change is from mouseleave to mouseout. Inside the navigation, there are likely to be descendent elements that cover the actual nav-body. With mouse leave, the handler only triggers when the mouse leaves the bound element. If it goes over descend it elements, it is considered leaving. Mouseout only triggers if it is outside the bounds of the bound object.
The second thing I did was assign a delegate to the handler binding operation so that I could use it as a callback function for hide(). This way, the event handler won't be restored to the nav-head until the hide is completely done.
The last was to assign the mouseout handler to the containing div. This way, the so long as it leaves the nav-head (or the nav-body) since its contained, the body will hide.
I'm using jQuery to toggle the visibility of a <div> using the jQuery toggle method. The toggle is fired on the mouseenter and mouseleave event, thus creating the effect of the div to fold out on mouseenter and fold in on mouseleave. Problem is, if the user drags the mouse over the <div> a few times and then leaves the <div>, the div will toggle in and out several times. This can happen if the user accidentally moves around the mouse pointer in the <div> are. Do anyone have any idea on how I can avoid this behavior?
Thanx!
Two things:
If you're going to use both mouseenter and mouseleave I'd suggest using the hover() function; and
When using triggered animations it's a good habit to get into to use the stop() method.
So:
$("div.someclass").hover(function() {
$("...").stop().fadeIn("slow");
}, function() {
$("...").stop().fadeOut("slow");
});
Note: replace "..." with the appropriate selector for what you're toggling and use the appropriate effect (I'm using fade here). Also, this in an event handler refers to the source of the event.
You can use the more common mouseover/mouseout events to get a hover event that doesn't fire on internal mouse movements.
But don't use toggle on a mouse event, it can easily go wrong if eg. the mouse is over the element at page load time, or the mouse leaves the browser (which can allow the mouse to leave the bounds of the element without firing a mouseout). Have separate function for over which shows the content, and out which hides it.
Better: just use the hover() method which is meant for exactly this purpose.
Aside from the correct answer by Cletus, i'd like to point out that using mouseenter and mouseleave events is not wrong. The trick only resides into the stop() method, in fact we could still do:
$("div.someclass").on("mouseenter", function() {
$("...").stop().fadeIn("slow");
});
$("div.someclass").on("mouseleave", function() {
$("...").stop().fadeOut("slow");
});
Here is a jsFiddle example :)