For a 'shooting gallery'-like game, there are images with an onMouseOver event that will show a crosshair (which follows the mouse) and an onMouseOut event that will hide it.
However, the instant the crosshair becomes visible, it covers the below image, activating its onMouseOut event which hides the crosshair.
This creates a 'flicker' effect which is very, very ugly.
Is there a way to prevent the crosshair image from obscuring the target below?
One easy solution is to create an onMouseOver for the crosshair that shows it (I know this is redundant, but it works for menus and the like).
Another solution would be to set a timeout in the onMouseOut to hide the crosshair. It will reduce the flickering and the crosshair will be visible out of the target for a short time.
Edit:
And another would be to perform a collision detection between the mouse and the elements, changing the mouseOver to a mouseMove in the target's parent element:
http://jsfiddle.net/sHecT/1/
The code is quite long, but its logic is what I've said above.
Just a note: The getElementsByClassName doesn't work in older browsers, but you can use an array of targets, as you create them, add them to an aray (probably you already has one) and use it in place of this call;
This one illustrates an easing function to position the crosshair smothly and the cursor is hidden when over the target
http://jsfiddle.net/sHecT/2/
Instead of using an image for your background, and an image for your cross-hairs, what if you used a div with a background image for your background instead, and then made the cross-hairs image a child of that div?
I haven't tested this, but since the cross-hair image would now be part of the content of the background div, I would imagine that it would no longer trigger a mouseout.
I believe The pointer-events property is exactly what you're looking for. It basically prevents an element from being the target of any sort of mouse-event so the elements underneath it can handle them instead. Parent elements can still react to the event.
HOWEVER it is only supported in the later versions of Firefox, Safari, and Chrome, and it probably won't be in the CSS specification until CSS4. It an awesome solution for supported browsers, but if you want to fix the issue in any version of IE or Opera you'll also need an alternate solution. I felt like it deserved a mention here though. :D
Related
Perhaps the title isn't great, but I had a little trouble with the wording...
Basically, is it possible to have jQuery's hover only fire over the actual content of a png with an alpha channel.
So in the image below;
http://i.imgur.com/3kO7v.png
Only fire on the rectangle and not the alpha channel which make up the rest of the document bounds...
I've tried the obvious $('obj').hover(function(){stuff}) but this fires on the alpha channel too...
The final implementation of this will be for more complex shapes than just a rotated square, so css3 tricks are out for the primary basis, but could be used with a back-up/shim, plus I need to support IE7 and ipad,iphone,ipod....
If there is a CSS2 solution then that would be suitable too. Also any real guidance on this issue is more than welcome.
My backup for this will be to have an empty div, display block and position it over the shape and then use that. This will obviously not be ideal for the less square objects.
Any hits or tips are more than welcome.
Thank you
Yes it is possible depending on the stacking context of your elements. Keep in mind that when you do a focus over any particular element on a page, that you are actually focusing all other elements within the same stacking context.
So what you could do is either stop the event from bubbling up the stack (if the element you want to "hover" is lower in the stack that the elements you want to prevent hover effects on), or specifically put in prevent default for onhover events for all elements in the stacking context except for the one you want to actually get a hover effect.
I have a scenario where I have some text, which should be user-selectable. The problem is, that there's an UI overlay on top of it, which prevents selecting text by default. The logical way to keep the overlay and still be able to select the text, would be to use synthetic events (use document.createEvent), but due to some reason, it doesn't work as expected.
The events seem to be delegated correctly and fire their handlers, but no text is selected. I have an example here, which is a rough simplification of the problem.
A few notes
In Firefox if you start your selection outside of the overlay, you are still able to select the text you want, even if it's under the overlay
When you have a normal selection in the uncovered area and you click on the overlay, it would be expected from the delegated mousedown event to remove the selection, but it doesn't happen
Am I missing an event that should also be delegated (I have mousedown, mousemove and mouseup)? Or is it some kind of a security measure by browsers to disable such behavior (refer to the note nr 2)? Any other suggestions on how to get the desired result? I know I should work around the current overlay solution altogether, but I'm already curious about the problem itself.
I have found two solutions for this problem:
"pointer-events" css property. Requires IE 9.0+ though.
Seems like guys from ExtJS solved it by event forwarding: demo, source, blog post
I would suggest to do the easy trick: put the transparent element with the same content as your text on-top of text itself and overlay. Here is the demonstration.
P.S.: From my experience any solution in the form you suggest will be awful. It will suffer from browser incompatibilities, side-effects of surrounding mark-up and styling etc.
If you take a quick look at the two links below, you'll see most people want to get rid of the outline around the area of a map on an image. I see this occurs on the MAC OS X platform, exclusively.
Removing outline on image map area
How do I get rid of this border outline for my image map areas when clicked (OS X Chrome Only)
However, what I want to do is show the outline in multiple browsers and change it's color and width. I tried but to avail. I created a style for an id. Didn't work. I tried using a class and that didn't work. I set an inline style and that didn't work, either. And I attempted it on both the map and area tags, by the way.
As of now, I use a gif to "border" the area when clicked. But it would make things so much easier if I could take advantage of the built-in shape attribute to highlight the area clicked.
Thank you very much for any help.
This answer looks interesting:
Changing the colour/transparency of a div on rollover or using an imagemap
Links to here: http://davidlynch.org/js/maphilight/docs/demo_simple.html
Older versions of Internet Explorer do not respect CSS for the area outlines. You can solve this by blocking the default handing of the mousedown event. If using jquery, something like
$('area').bind('mousedown',function(e) {
e.preventDefault();
});
would take care of it for all image maps on the page.
Also take a look at my plugin: http://www.outsharked.com/imagemapster which will let you easily handle outline (and other) effects on mouseover and click events.
I've run into an issue using Raphael for SVG effects on an IE browser. When I mouseover an object, the animation occurs as expected. On mouseout, however, the mouseout action is never called, so the object(s) are stuck in their mouseover state.
I've seen others complain about this issue in the past, but the only solution I saw was to force the mouseover event on every object to return everything != current object to their normal state. I'd rather not do a general "reset everything" because I have quite a few objects, so I'm wondering if anyone has an alternative they can suggest. I was thinking about storing the last object with the last triggered mouseover in a variable and only resetting that on every mouseover, which could work....
Since Raphael 2.0.2, there's been an issue in Raphael and Internet Explorer (all versions) where various manipulations of a path such as resetting a transform, .toFront(), or .toBack() called from hover() while hovering can cause hover ins to loop endlessly and/or hover outs to be missed.
While hover mostly works fine in IE for mouseout, there are a few things I've found that that can trip it up, causing it to a) ignore mouseouts as you describe and b) trigger the mouseover event recursively such that if you put a console.log in there, IE developer tools' console breaks and turns grey... which sometimes seems to also stop it recognising mouseouts.
Here are the things I've encountered which cause this:
Resetting a transform, which would cause the element to move from under the mouse, then reapplying it putting the element back under the cursor. non-IE carries on like nothing happened and works fine, IE freaks out as described above.
.toFront() and .toBack() - non-IE recognises the moved element as being the same element in the same X Y position, IE freaks out as described above.
There are some observations and demonstrations in this jsfiddle (read & uncomment the various comments).
A good workaround here, is to have some kind of flag like for example 'path.data( 'hoverIn', true );on mouse in and 'path.data( 'hoverIn', false ); on mouse out, then wrap any .toFront() or offending transforms in a check that !path.data( 'hoverIn' ) so that it can only happen once until the mouse out happens. Or, store a reference to the most recently hovered path somewhere after the toFront() or whatever, then don't toFront() or whatever if this path is also the most recently hovered one.
I had the same problem (map with regions that changed background on hover) and the deal-braker in IE9/Opera for me was the toFront() method. I removed that and it works fine.
I gone around this limitation by putting code inside anonymous function and then calling it via setTimeout inside event handler.
If you add a rect as a background underneath (and containing) the object you are trying to mouseout of, you can effectively get a mouseout effect by adding another hover event handler to the background rect.
What is the best way of turning a Canvas element into a link - by this I mean the whole canvas element, not just a part of the image.
I have tried the obvious thing - wrapping the element in an A element - but finding issues in IE9.
Take this markup for example:
<a href="#link">
<canvas width="100" height="100">
//fallback
</canvas>
</a>
Using CSS I have styled the link background colour to change on hover, and am finding in most modern canvas supporting browsers it works as expected - you hover, the background changes colour, you click the link, the link is followed.
However, in IE9 when hovering over the element it doesn't recognise that it's a link - no hover effect, no cursor changing to a pointer, clicking does nowt.
Interestingly, if I add a 1 pixel border to the A element, and hover the mouse precariously over the 1 pixel border, IE9 does recognise the link, and after that you can move the mouse over the canvas and it maintains it's hover state and works as a link.
It's almost as if the canvas is overriding the link, so the browser isn't able to recognise the link, only the canvas element - if that makes sense?
So, really I just want to ascertain:
Is is acceptable to simply wrap a Canvas element in an A element - is this just IE9 being weird or am I doing it wrong?
If I'm doing it wrong, what is the accepted technique for doing this seemingly simple task?
Thanks
UPDATE
OK, so the answer's I've had below are all correct, but unfortunately weren't working in my implementation either. My markup is quite a lot more complicated than the simplified example above, so I'm guessing that actually there is something else at play that is causing the problem - with native hover events and events attached with JavaScript - nothing was working.
However, I've come up with a hack that solved the problem. I gave my link an RGBA background colour with zero opacity. Once that was there, things work fine. Weird I know, but fixed :)
I'm not 100% on the problems with the canvas element in IE but you can update the onclick handler of the canvas element, changing the window location to where you want.
document.getElementById("mycanvas").onclick = function(e){
window.location.href = 'http://www.google.com';
};
Example: http://jsfiddle.net/jonathon/HtmVS/
You could handle other events (like the mousein/mouseout) to set the cursor, if you wanted.
You can use javascript's onclick to handle this, and combine it with CSS to put a cursor: pointer; on it. You could then implement canvas:hover in CSS for the hover effects. You can combine this with an <a> to allow the user to "tab" through the links/canvases.
Not sure if you wanted to use jQuery, but if so, try this.
$("#myCanvasId").click(function(){
window.open("https://www.google.com");
});
Cross-browser way to do this is simply by putting a div on top of the canvas that has the exact same pixel position and width and height as the canvas. Then install on click handler on that div and the use window.location.href as suggested in the earlier answer.
...
<canvas id=".. >
<div id="overlay"/>
...