SVG Blocks Touch/Mousewheel events - javascript

Is there a workaround? I am running my own custom scrollbar script as opposed to using the built in browsers functionality. I prefer to use SVG for my image elements for a number of reasons, but one, pretty major pitfall is the fact that touching or mousewheeling over an svg blocks the event and thus brings the page scrolling to a halt. This is even more noticeable on mobile browsers where the svg might take up the entire width of the document in which case as soon as you get to an SVG element, the user is unable to scroll past it.
I haven't tested in IE, but in Chrome, the touch commands dont work on top of SVG, and on Firefox, the mousewheel events are a problem. I assume it will be both on IE haha.
A decent solution would be to somehow add an event to my SVG elements the catches the events and passes them onto the scrolling events. I can't seem to find a way. An even better solution would be to somehow place the document above the SVG so the SVG doesn't interfere with the scrolling at all. Again, can't seem to find a way.
I embed my SVG elements with object tags, which is important for a variety of reasons. I'm assuming the object tag is actually the culprit.

Per Duopixel's comment. Adding:
object {
pointer-events: none;
}
To the css does solve the problem in both Firefox and Chrome. I still have to test in IE, but for now this seems the best and easiest solution.
A good article that explains the pointer events attribute can be found at http://davidwalsh.name/pointer-events
If the issues mentioned above are an issue in IE, you can use a javascript solution that requires capturing the position of the pointer and passing it to the proper element. A working version that uses jQuery but could very easily be translated into vanilla javascript can be found here: http://jsbin.com/uhuto/1/edit

Related

D3 events firing on a hidden svg element

I can't seem to find an answer for this and it took me a while to recreate it as a stand alone fiddle/pen but I finally have.
I am working on Vaadin application which uses D3 to draw and manipulate svg graphics.
At a point there are svg's on screen which have visibility:hidden.
This works perfectly find in all browsers.
These hidden element have click and mouseover events, which again work find in all browsers
However in firefox version 34 the hidden element still fire their events (click and mouseover) when they are still hidden.
To explain better: when a button is hidden, its mouseover event shouldn't fire, when its visible it should. That is how it works in ALL browsers except for firefox 34, 35 beta and 36 dev edition. It works fine in firefox 31.
I am suspecting this is a bug in D3, but wanted a second opinion or for someone to point out my error. Its worth noting that setting display:none on the element works in firefox 34 and up, however I don't feel that the problem lies there
I have created a jsbin demonstrating the code, there are two orange icons, one has visibility:hidden (you might need to disable to see it) if you mouse over the hidden element with chrome nothing happens. but with firefox 34 the events fire. Here's the jsBin
Any idea's why it would fire? I am guessing either D3 issue or firefox bug, however I'd like to nail it down to either fix my code on contribute to a fix in the other areas
Thanks
This is just a bug in Firefox. If you report it I'll fix it.
Given a specific value for pointer-events we can say exactly whether the element should receive events or not. If we don't know what value pointer-events has then the element might or might not receive pointer events. That's all the specification is trying to say. There's no ambiguity here.
Note that the firefox bug only affects <image> elements. If you replace the image with a <rect> element you should see the correct result even in Firefox.
The spec states that this is normal behavior:
Depending on the value of property ‘pointer-events’, graphics elements which have their ‘visibility’ property set to hidden still might receive events.
As a work around you could use either display: none or add pointer-events: none to your class with visibility: hidden.

Touchpad scroll detection in JS, no library

I'm making my own little Javascript library that makes it easy to replace the default scrollbars for your Website (and mine) with custom ones. Part of that means giving the BODY element an "overflow:hidden" style to hide the normal scrollbars. However, this prevents all scrolling except for that which is done in code.
I have everything working in terms of showing the bar and having it scroll when you click/drag it. However, many touchpads (like on the computer I'm testing this with) have a feature where you can scroll by sliding a finger along the right side of the pad. I need the library not to break that, so I need some way of detecting when the user tries to scroll this way.
I thought it would be interpreted by the browser as a mouse wheel, so I set up an onmousewheel event, but that doesn't seem to capture it at all. For the record, I'm testing with Firefox 25.0.1.
Is there any way to capture the trackpack scrolling, preferably without an external library? I'm trying to keep this as self-contained and lightweight as possible, but if I absolutely need to, I guess I can use jQuery and its mousewheel extension...
Some browsers use the onwheel event instead of onmousewheel. So, it's usually a good idea to listen for both events.
See this MDN article for more about onwheel.

Issue with mousemove in Internet Explorer

Internet explorer does not fire onmousemove events when the event target is positioned over an <img> element and lacks a background.
But it does register the event when the target has a background. Does anyone have an explanation for this? I had the same behavior in IE10, IE9, and IE8.
Fiddle here:
http://jsfiddle.net/xSpqE/2/
As OP asked for a reason, here's my breakthrough:
It's easier to explain visually, so first off let's add a click handler to the imgs:
$('img').click(function() {
$('.pageX').text('img clicked!');
});
Fiddle
Fair enough. You click the image in Chrome/Firefox/not-IE browsers and nothing will happen as the absolutely positioned div covers it.
Now try it on IE. The img's click handler is fired! Therefore it shows that IE pushes elements through absolutely positioned "transparent" (no content or background) elements. More interestingly, relatively positioned elements suffer the same issue and setting z-index on either/both elements won't solve it either. Of course, as the image is above the overlay, it won't trigger the overlay's mousemove event.
An workaround is to provide some "filling" to the overlay, say background:rgba(0,0,0,0) will force IE to keep the absolutely positioned element at the top. Fiddle. If you need to support browsers without rgba support, use a 1x1px transparent gif as background.
I've never seen this defined in any spec nor officially reported as a bug. There's no logic or reason for absolutely positioned elements without content nor background to suffer this z-index issue, hence I'll call it yet another IE bug. Maybe reporting it on the Microsoft forums would be of use.
Also, related question: IE bug: absolutely-positioned element with a non-transparent background colour
Yet another IE fail! This is more of a workaround than an answer, but it seems to work alright:
var is_ie = $.browser.msie;
if(is_ie){
$('.main img').mousemove(function(e){
$('.pageX').text('pageX: '+e.pageX);
}
}
That is in addition to the $('.overlay').mousemove function, so keep that too, and of course the is_ie check is optional.

Safari jittering/jumping (bug?) on first "focus" event of page load

I'm currently fighting a very frustrating bug on Safari, and I'm not sure where else to turn.
It seems most elements (but not all, and I can't discern the differentiating factor) that will trigger a focus event will cause all elements on the page that are transitioned or animated to jump ~2px to the top and left. And this only occurs on the first focus event after the page loads.
It's a little annoying to see the bug, as it's in the logged-in portion of droplr.com, and I have been completely unable to distill down a simpler case on JSFiddle.
If you have/create an account and log-in, click on this edit icon for a drop:
You'll see that on the first focus of the page, things jitter. Here's the timeline when there's a single drop on the page and I trigger focus on an offending element:
With more drops, it's just more of the same, but it seems to max out around 40 paints. And the profiler doesn't suggest anything nefarious. Just a trip through jQuery internals.
If instead of laying elements out via a translate3d or matix3d, I simply use top and left, this bug goes away. After hours and hours of debugging this, I'm at a complete loss.
Hoping someone has seen something similar, could take a look, or could give me advice on debugging next steps.
Thanks so much!
Update: Dave Desandro suggested it was the 3d acceleration kicking in, so I tried it out with a translate instead, and sure enough, that did not cause the jitter. I have no idea why the hardware acceleration would be firing up with a focus event though, and only once.
I've tried setting a transformZ of 0 on page load to go ahead and ramp-up the hardware, but no luck there, either. Any more ideas are welcomed.
I've had this issue a while back and honestly I don't remember what exactly was the cause but here are some of the steps I followed:
Check that you don't have hide() and show() for the same element in the next line or vice versa.
Example:
el.show()
el.hide()
Change Custom fonts to "Arial"
For the elements you don't want focus events add this code at the bottom of your scripts:
noFocusElem.off('focus');
This will make sure to remove any focus handlers you might have added by mistake
Finally place your css before any scripts. It's a know fact that adding css rules after an inline style has been applied may cause jitter especially if you're using line-hieght property
Hope this helps :)
I've had this happen when using custom font kits. Could this be the issue? Some events cause custom fonts to re-draw, which can cause a ever so slight "jitter" in page display.
Sometimes, manually setting heights and widths on all the parent HTML elements can reduce the flicker.
I know this question was posted a while ago and this is a bit of a long shot but here goes:
Maybe as a starting point go back to chrome and look at the composite layering:
Hit this into the address bar:
about:flags
You will be able to enable composite borders from within there. The red borders generally indicate a rendering issue:
http://www.chromium.org/developers/design-documents/gpu-accelerated-compositing-in-chrome
What I have found from time to time is that although there are rendering issues in Chrome the browser copes pretty well with hiding them from me. In other webkit based browsers however the result can be more noticable (i.e. android).
I've also seen flickering occur when z-indexes are being used in conjunction with content that is being transformed.
Either way it would be great to know how you resolved this issue (if you did). Post an answer to your own question perhaps?
A way to avoid spending time fixing load time twitches; you could set the page to hidden then make elements visible with the load. If your page is slow to load, you may want to have a spinner default to visible, then have load hide it. Then you could come back to the issue when you have nothing better to do.
Just my 2c worth.
The first thing I would try:
First in chrome, whack in 'about:flags' (yes I know you're not using Chrome). Find the 'Composited render layer borders' and turn it on. Once this feature is switched on you'll get a rough idea of what is being rendered/hardware accelerated.
See: http://www.chromium.org/developers/design-documents/gpu-accelerated-compositing-in-chrome
and look for any rendering problems. These are normally caused by z-indexes. Play around with any z-indexes and hide/show certain elements until the rendering issues are resolved. Then work from there. translate-z hacks and opacity can also cause problems.
From experience I've found rendering problems in other webkit browsers can be diagnosed using chrome. Flickering is a common occurrence on the stock android browser.
Secondly: take a look at the focus event itself and try things like preventing the default behaviour. Seems like a long shot to me but give it a go.
I haven't tested this, so I will be very surprised if it works... but here's an idea:
$(document).ready(function() {
$(document).focus(function(e) {
e.preventDefault();
});
$(document).click(function() {
$(document).unbind();
});
});
I've been running into the same issue recently and found something that fixed it in my case.
Check for anything that's hidden offscreen like:
text-indent: -9999px;
left: -9999px;
Removing any instance of these from the 3d accelerated elements (including children) stopped the content jump on focus for me.

How do I make it so that there is no "Ghost" when I drag an image in Firefox?

When you drag an image , there is a semi-transparent ghost image that follow your mouse when you hold it down.
Is there some way to apply CSS/JS to remoe this effect on a certain portion?
The easiest way is to set very large x and y coordinates to setDragImage to its away from the screen. For example:
element.addEventListener('dragstart', function(event) {
event.dataTransfer.setDragImage(element, -99999, -99999);
}, false);
The actual element you pass to setDragImage doesn't really matter. We use the same element here for convenience.
The only way to disable that in the browser (It does the same thing in Safari) is by returning false from the onmousedown event on the img element (or event.preventDefault()) and by handling the rest of the drag operation with javascript.
Pretty much every major JavaScript library has support for 'dragging' and 'dropping'. You could use their code as a starting place or just use it outright if you already are using a library on your page.
Just add attribute draggable="false" to the image. Also, add a container div.
E.g.
<div draggable="true">
<img draggable="false" src="your/path/to/image.png"/>
Optional Text
<div>
Also, add
function handleDragStart(e) {
// other code
var dragIcon = document.createElement('img');
dragIcon.src = 'another/image/path.png';
e.dataTransfer.setDragImage(dragIcon, -10, -10);
// other code
}
You could try using css background images instead of actual images with the img tag.
You need to return false from the ondragstart event. I had this issue myself, and that's how I've solved it. It's an issue in IE7 as well. The problem is IE's drag and drop api, its standardisation into html5, and firefox's subsequent implementation of it.
Others suggestions of using a javascript library for drag and drop won't work. (I was already using jquery UI), as this is a recent thing in firefox, and jQuery UI doesn't seem to account for it.
I'm afraid it's the browser behaviour/feature. I'm not sure of any specific FF CSS style which can handle that.
You might want to modify the Firefox's code to have your own firefox. If you are looking for some means to do it non-programmatically, I guess you have to post in superuser.com :P
There is be a Firefox option in about:config to turn this off - nglayout.enable_drag_images - but obviously that will only work for you. I'm guessing you want to remove it for all visitors?
If you want to do drag & drop, maybe try jQuery UI or another JS library? You should be able to move other elements quite easily, and you could use a background image like Tim said on one of those.
Another advantage to that is you can use CSS sprite effects to reduce HTTP requests. I made a jigsaw puzzle with jQuery UI, which is actually only one image, but it looks like several.

Categories