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.
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.
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
When you tap and hold on a link inside a UIWebView (or mobile safari), it highlights the link in a gray text box.
You can control the styling of this with the webkit-tap-highlight css property.
What I'd like to know is if it is possible to either:
A. Listen to an event for when something is highlighted.
B. At a given time, find any elements that are currently highlighted.
Is this currently possible?
Looks like this guy figured it out using window.getSelection() and text.anchorNode.textContent.substr(text.anchorOffset, text.focusOffset - text.anchorOffset):
http://zaldzbugz.wordpress.com/2010/05/31/how-to-get-the-highlighted-text-in-uiwebview/
This article was also chosen as a working answer in another StackOverflow post.
Although the iPhone is a touch device, the mouseover event will be triggered when the element is highlighted. So, you can use javascript to listen the mouseover event.
I'm trying to implement a drag and drop script and have hit the wall with one problem. When you take an item and start dragging it - the item is directly below your cursor and onmouseover event is very rarely fired on the items below. But i want other items to highlight when i drag something over them. One of the solutions would be not to drag anything at all - that way the mouse events would work, but that would look ugly. Has anyone ever done something like this and know how to overcome this problem?
If you're thinking about suggesting some JQuery plugin or something like that - please don't. I don't need a completed solution, this is educational.
IMO, in order to have the mouseover event to be fired up frequently would be binding the mouseover event to the parent element of all the affected elements, or perhaps to the document itself, since events get bubbled up, they are probably the only elements that can fire the mouseover events.
Then further, write a hit method in your mouseover event and actively check the position of your mouse cursor, see whether it's going under the target element's boundary. Tradeoff in usability and performance. You choose.
My 2cents.
Or perhaps, you can reverse engineer jQuery UI to see how they implement the drag element. Haven't check thou, but I think there should be a wiser way.
I am simply looking for a way of using drag and drop without jquery or any other library. If a dragged object is dropped on another element the later element should start an event (in FF - better would be browser independent).
I know that drag and drop for JavaScript was discussed sometimes before but the previous postings didn't help me.
Although I found some examples it is not clear to me if there is a "drop" or "dragdrop" events exist but these things don't work:
<p ondrop='alert("It worked");'>Text</p>
<p ondragdrop='alert("It worked");'>Text</p>
How could this be done?
Many thanks in advance.
I agree with the other answers. A library will save you a lot of time and headache. This is coming from someone who just recently created a drag-and-drop control from scratch.
If you insist though this is what you'll need to do:
Bind a onmousedown event to the div you want to drag (div.onmousedown).
Change the div's position style to absolute (div.style.position = 'absolute')
Begin capturing mouse movement (document.onmousemove).
On mouse move update the div's position (div.style.top|left = '[location]px')
On the div's onmouseup event (or the document's) unbind all the handlers and do any other cleanup (null out position changes, etc).
Some problems a library will probably solve:
While dragging you will select text on the page (looks ugly).
Binding to events is different between browsers.
You have to calculate the size of the element being dragged if you want to show placeholders and to make it not "pop" when you begin dragging the control (since changing to absolute positioning will remove the element from flow).
You will probably want your dragged element to move fluidly so you will have to store some mouse offset when selecting the element or automatically center the element to the mouse.
If you want to drag an item in a list you'll have to write a ton more custom code for that list to accept the dragged item.
You'll have to take into consideration dragging when the window is scrolled and possibly dragging inside other elements that are positioned strangely.
I am simply looking for a way of using drag and drop without jquery or any other library.
I'm sorry, but there are no such thing as simply drag and drop without any library. You can write it all yourself, but that will be a lot of JS to make it work in all browsers.
Hmm. It's probably not that simple that you'd want to do it yourself, but I would look at Peter Michaux's FORK Javascript drag and drop library -- unlike JQuery or all those big libraries, FORK's modules are decoupled from each other, and are simple enough that you could probably look at Peter's source code and figure out the bits you need. (edit: I'd just use FORK.Drag as it's really small: 7.6KB total minified)
While I agree that library is the way to go, the answer you want is onmousedown, onmousemove, onmouseup. You have to handle those three events.
In onmousedown you'd find the target (event.target or similar in different browsers) and set draggedObject = event.target. You'd also start handling the onmousemove event.
Whenever the onmousemove event fired, you'd move the dragged element based on the difference in position since last time the onmousemove event fired.
In the onmouseup event, you'd clear your draggedObject variable and stop handling onmousemove.
It's not very crossbrowser, but it's the core of what you'd need to do for dragging and dropping.