I'm working on a drag and drop solution, but I don't want specific items to be dropped on. For that, I use the dragnot = "true" attribute in a div.
It works, however when an user drags a div on this dragnot div, I would like to change the cursor to not-allowed. But the cursor only updates after I dropped the div, not when I dragenter.
I have put up a JSfiddle where it's demonstrated. Try to move div A or div C into div B. You'll see the cursor changed after you dropped the div (mouse over div B again if you don't see the cursor change).
How can the cursor be changed realtime?
Related
I have a Vue3 app with vue-draggable and I have a list of sortable cards which possibly contain long text inside. To make dragging easier, I want to hide the text contained in the cards and only show their title when one is being dragged. This makes it easier to drop the card into the right position.
In order to achieve this, the elements which I want to hide inside of the cards while one is being dragged are given a CSS class hidden-while-dragging and the whole collection receives a class dragging while an item is being dragged. This is achieved by setting a boolean variable to the correct value upon receiving the events start and end and conditionally setting the class on the whole <draggable> element. Then I have this CSS rule:
.dragging .hidden-while-dragging {
display: none;
}
This works fine except for one case: if I drag an element and, upon dragging, the height of the parent container changes (due to the disappearing of the content inside of the cards), I am not able to drag the item: it instantly gets dropped in place, and no end event is emitted, so for example the collection keeps the class dragging.
Afterwards, I am able to drop the element once again: the issue doesn't occur this time, because no change in height occurs, and after I drop the element, everything goes back to "normal".
I made this repo in order to have a reproducible example: https://github.com/samul-1/vue-draggable-bug-demo
Here's a codepen as well: https://codepen.io/samul-11/pen/mdjKvZa try and drag the first or last element and you'll see the issue.
You can observe the height of the #app element changing when dragging an element. An interesting thing is that this only happens if dragging the first or third item in my example, not the second. So apparenly the issue is with elements at the edge of the parent.
Is this a bug with the library or is there a way around it?
I want to make something like Grammarly, exactly like this:
The text is in a textarea, and a div for highlighting is under it, when I click on the red line, the correction card appears, but with z-index of the div less than the textarea's one, I am losing the events on it !
How can I implement such thing ?
If Element A has a lower z-index than (ie. is underneath) Element B but Element B has the following applied (either in the initial stylesheet or later, dynamically):
element-b {
pointer-events: none;
}
then any user clicking on Element B will actually be clicking on Element A.
Essentially the click goes straight through the element which cannot take pointer-events and instead hits the element beneath.
Further Reading:
https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events
I would like to drag and drop divs within a container-div. Only up and down the list, using the mouse. How can I create this?
Searching the internet and stackoverflow didn't give me a good answer, since I would like to have it in vanilla Javascript and everything is nowadays in jQuery. :S
This is wat I have:
<div class="chapcontainer" data-chaporder="1000">
<div class="chapter">Big fire</div>
<div class="subchapter" data-chapid="1">Forest burning</div>
<div class="subchapter" data-chapid="2">Balu hoses</div>
<div class="subchapter" data-chapid="3">Forest animals die</div>
<div class="subchapter" data-chapid="4">Lovely fire</div>
</div>
</div>
The chapter-div is the container. Within this div I want to be able to move the subchapter-div with a click of the mousebutton up and down the list of subchapter-divs.
For example I move the subchapter-div with data-chapid 4 to the top, then it should be moved to the top and the data-chapid changed to 1. Is something like this possible in vanilla javascript?
I've read about AppendChild, but I don't know how I can trigger this with the mouse.
You could do it with jQuery:
$(".subchapter[data-chapid='1']").on("click", function() {
$(this).css('margin-left', '20px') // add margin/padding/etc here
})
Fiddle
Doing drag and drop yourself is complicated, but here are some of the basic steps. One advantage of rolling your own is you can do more advanced things than your standard jquery ui drag and drop can, like smooth scrolling the container, auto-opening nested tree items if the user hovers over them, or doing animations while moving items.
Steps:
Listen for mousedown events on your items in your container. When the user presses down on an item, store the mouse's offset relative to the top of container (this includes the scroll of the container). Also store the mouse's offset relative to the item being dragged.
Clone the element that's being dragged and absolute position it under the mouse, using the relative offset you stored in step 1.
Make the original element invisible.
Listen for mousemove events on your container. Reposition the dragged item appropriately.
As the mouse moves, you'll need to update the mouse's new offset from the top (including scroll) and figure out which item you're over. You can do this by getting the height of each item in your list. So if your mouse is 710 pixels from the top, and each item is 100 pixels high, you're over index 8. You can use this info to change the style of the item you're over to show that it's a drop target. One thing to watch out for is if you do any styling changes that change the heights of items, you'll need to recalculate your heights.
On mouseup, you already know which item you're over, so now you need to update your data array to move the dragged item, probably using array.splice. Delete the absolutely positioned dragged element, and rerender your list to reflect your changes. I'm assuming you're using some sort of templating library to render your stuff, or at least a render function that clears what's there and replaces it with the current state.
I've accomplish successfully when the mouse overs a div to cycle and change the background-image and stop the other divs from cycle.
What happens is that, this div have a title which appears when the mouse is hovering the div, and if I grab the cursor and put it over the title and then move the cursor again to the other div title, the cycle continues in both divs, and I would like not to.
I'm clearing the interval cycle this way: clearInterval(theInterval);
But, somehow, when the title is being hovered it doesn't stop the others cycle.
The problem can be seen in JSFiddle.
Simulate the problem:
Put your cursor over the title
Move your cursor quickly to the other div title
You'll see that both divs continue the cycle independently (and I want only one to cycle)
Simulate how it works:
Put your cursor over the div (without being in the title)
Move your cursor to the other div
You'll see that only one div cycles
I believe it's a problem with the nature of the mouseover event, and the divs being in such close proximity. Try using the hover event instead. See this fiddle
In essence:
$('.collection-photo').hover(function(){
// mouse over stuff here
}, function() {
// mouse out stuff here
});
I'm trying to attach click events to a couple of divs. One of which has no height or width, just borders. Maybe it's just the browser, but the clicks are being triggered very unreliably. Even the css parameters .class:hover{} isn't really working.
$("body").on("click", "._tlh_dropdown, ._tlh_dropdown *", function (event) {
isn't working when the a div contained by ._tlh_dropdown is clicked. And the div ._tlh_dropdown_close_button is not removing it's parent div when clicked, nor turning a darker shade of gray when it is hovered over. What am I doing wrong here? I assume it has to do with the click event not being applied to the areas of the divs that are "just padding". Is this the case? How can I overcome this?
http://jsfiddle.net/UrNUM/7/
This is happening because the underline element that is a div element overlaps the elements in question . As you know div is a block level element.
One work around is to to set the 2 divs to inline-block
._tlh_dropdown_input_container, ._tlh_dropdown{
display: inline-block;
}
Check Fiddle for hover
If you want the div to be block level as it is then you can also play around with the z-index
._tlh_dropdown_close_button{
z-index: 1;
}
This will make sure the close div is always on top of the underlying container
UPDATE
2 events fire for every click event on the page..
So the content is not shown when u click on the image because of this condition
if ($targ.hasClass('_tlh_dropdown')
|| $targ.closest('._tlh_dropdown_content').length)
return;
This happens because the e.target when you click on the arrow image will be the arrow and not the tlh_dropdown .. So it fails on this condition and moves to the next statement where the content is removed.
Change it
if ($targ.hasClass('_tlh_dropdown')
|| $targ.closest('._tlh_dropdown').length
|| $targ.closest('._tlh_dropdown_content').length)
return;
It should work..
Check Fiddle
Also I feel the same can be accomplished with a lot less code. You can always have the HTML already built and then hide or show based on the condition.
Regarding the close button, if you hover "_tlh_dropdown_input_container" in the inspector, you can see that it overlaps the bottom part of the X button. That's why the hover/click event on the X is not caught below the middle of it.
Regarding the down arrow, just wrap it with another DIV on which you'll add the events. You can achieve minimal HTML by using a single DIV and adding the arrow to it using CSS :before or :after.