I have a div with an attached movable element. Inside the div there is a list of buttons that is accompanied by a scroll bar. When I try to drag the scroll bar it simply drag the whole div around my screen. In this code fragment I am trying to get the moveable to turn off when I click on the scroll bar (which is part of metL).
I have the "metId" which is everywhere else in the div set to resume dragging the div around.
The pause and resume do not work.
Any help resolving the issue would be helpful, thank you.
It is quite difficult to answer the question, without seeing the html markup comprising the structure of all relevant elements. There may even be a better approach to do what you are trying to accomplish. Nevertheless, I'm pointing out one possible issue:
The drag and drop action starts, when dojo registers the dragstart, mousedown, or selectstart events on the drag handle. In your case the drag handle is the div with id "divMenu"+threadId. All of these events are triggered before the click event occurs, so pausing the moveBlocker has no effect.
In addition I think, your moveBlocker event should not be an empty function. Instead it should actively 'block' the relevant events from being propagated to the drag handle:
var moveBlocker = on.pausable(dnd.handle, "mousedown,dragstart,selectstart", function(e) {
e.stopPropagation();
e.preventDefault();
});
Depending on the behavior you are trying to accomplish, the other event handlers should also be registered on the "mousedown" event.
Related
I'm trying for numerous days to solve the following issue.
I have a menu located on the top of the page which needed to be open using swipedown event (I'm using Hammer.js jQuery version).
Problem is, every time I try to interact using swipes I either scroll the page (swipeup) or pulling the page down same as described in the following question.
Here is what I've tried so far:
overflow: hidden; on the body element with an inner container with overflow: auto, swipe on top element still triggered document scroll.
Setting preventDefault on the document also disabled lower elements events in the DOM hierarchy and by that I had no swipe events working in the page.
Also tried using stopPropagation on the actual element when the event occurs, to prevent the bubbling up the chain for the event, the result cause the object to not respond to the events (swipes) and document scroll worked with no problems.
Any ideas how can I still keep page scroll but also when using common gestures, such as swipedown/swipeup, on specific elements that the element only will be affected?
Here is an example using JSFiddle, to better demonstrate the issue.
Would appreciate ideas/thoughts
I don't know if this will help, but I've always liked to use drag more than swipe. Using Hammer on my projects, swipes were a bit finicky. And from a UX standpoint, drag feels instantaneous vs a swipe. Much like, mousedown vs mouseup/click. So in instances where it's appropriate, and I believe in the case of showing swipey menu it is, I'd opt for drag.
Replacing your example with drag rather than swipe, and also using CSS transition, -webkit-transition, rather than jQuery's animate (drag will trigger like a mousemove, vs a click or a mouseup) seemed to make it work.
Hammer('.nav').on('dragdown', function(e){
e.gesture.preventDefault()
$(".blue").html("down")
$('.nav').css({"top":"0px"});
})
.on('dragup', function(e){
e.gesture.preventDefault()
$(".blue").html("dragup")
$('.nav').css({"top":"-150px"});
});
//Added in CSS, for .nav
.nav {-webkit-transition:0.5s top;}
Example
This does still have the page overscroll. A preventDefault() on document.ontouchstart would could fix that but that breaks scrolling. You might be able to do a selective preventDefault() by checking the scrollOffset perhaps. But I guess in the long run, I'd recommend something like iScroll.
Example
Also maybe tweak the hitbox for the drag to be a bit larger. Which I did in the last example. I attached the dragdown event on the document instead of the "menu" so the menu doesn't have to be visibly bigger.
Hammer(document).on("dragdown",function(e){
//calculate ratio of first touch from top
var pos=e.gesture.startEvent.center.pageY/window.innerHeight
if(pos<0.2){ //drag occurs in the first 20% of the screen
menu.style.marginTop="0px" //or animate here
e.gesture.preventDefault()
e.gesture.stopPropagation();
}
})
You should use the preventDefault function of the orginal gesture, to stop the browsers default behaviour, see here: https://github.com/EightMedia/hammer.js/wiki/Event-delegation-and-how-to-stopPropagation---preventDefaults
When you have a div element, on which you want to register swipe events, you would do the following:
$('#swipeDiv').hammer().on("swipe", function(ev) { ev.gesture.preventDefault(); });
That should prevent the scrolling of the page, but only if the swipe happens on the div element.
I have sliders on my site that allow the user to select via dragging, or clicking on an item. When they drag, the item closest to the vertical center of the parent is chosen.
CodePen Demo
The problem is that the Knockout click binding is being bound before the jQuery UI draggable option (implemented in a custom binding).
To reproduce, try clicking and dragging on the bottom number, and move it up a little (but not in the center). Try doing that a few times, as it seems to work correctly on the first drag... sometimes.
The binding basically calls .draggable, and updates an observable when dragging stops.
The HTML is set up like this.
<ul data-bind="slideSelect: thing, foreach: nums">
<li data-bind="click: $root.thing.set($data), text: $data">1</li>
</ul>
Is there any way to make the draggable element stop the lis click events from firing? I'd like to do it in the cleanest fashion possible.
did you try event.preventDefault(); in on drag event handler? the idea is if you detect drag event then stop the event bubbling. if click happens before drag then i think you might have to wait to see if drag happens then complete the action.
I noticed mouseenter event triggered when mouse is untouched but the page below the cursor is scrolled.
Check out this fiddle: http://jsfiddle.net/F3EwW/
Steps to reproduce:
Click on a li
Use up/down arrow keys to scroll the items
You would notice the mouseenter event getting triggered when the li below is scrolled to the view.
Note: To notice this behavior, make sure the mouse cursor is above li and leave it untouched.
Initially, I accepted this as a default behavior and went on with a work around to handle this in my code.. but then I got curious and wanted to verify this behavior in any documentation which I couldn't find it anywhere.
Does anyone know if this behavior is documented anywhere in spec or any authentic webpage?
I looked up w3spec event scroll and mouse event order, but couldn't locate anything about this.
Also the spec description for mouseenter is as follows,
A user agent must dispatch this event when a pointing device is moved onto the boundaries of an element or one of its descendent elements. This event type is similar to mouseover, but differs in that it does not bubble, and must not be dispatched when the pointer device moves from an element onto the boundaries of one of its descendent elements.
In Chrome, you would notice mouseover to be triggered as well. I have posted a question and a bug report already on this.
You realize that you have $('li').mouseenter(function () { ?
this caused the mouseenter event to be binded to each and every one of this li elements so when you are using the up and down key to scroll and your mouse is still inside the ul it keeps entering a new li. This was not an unintended feature the mouse in entering the new element.
The behaviour you are looking for is more something like this:
$("element").bind("mousemove mouseenter", function(event) {
//...
});
Also you need to realize the DOM understands the movement of the mouse relative to the document not where your mouse is on your screen as your OS does.
I'm trying to build a little calendar app sort of like Google Calendar. I'm trying to create events with a click and drag functionality so that the events align to a grid. I'm trying to
tie the dragging to TD elements below the event DIV element, which works when moving downwards (lengthening the event), but it doesn't work moving upwards (shrinking the event).
What occurs is that the mouseenter event is fired for the event DIV element, but it is never fired for the underlying TD. If you try to resize the DIV by moving upwards on the side, it works because the TDs actually receive the mouseenter event.
Google Calendar and jQuery Week Calendar use the mousemove event, but the mousemove event is fired for every pixel, which seems a waste. Is there a way to write this without using the mousemove event?
Is it possible to put the DIV element behind the table and the TDs? If the table is somewhat transparent, the user would still be able to see the DIV, but would actually be firing events on the TDs. I tried to do this with z-index, but it didn't seem to actually work.
jsFiddle example code: http://jsfiddle.net/rockymeza/8SHpA/
It sounds like you're having a similar kind of issue that I had:
you want to fire event behind an element? The answer is CSS. Set pointer-events:none; to the parent.
I had made a test where I tried to (unsuccessfully) implement the same behavior on touch devices. You can check that at: http://www.hakoniemi.net/misc/pointer-events.html if it'd help you with your issue.
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.