i want to detect to see if an element was dragged out of container.
for example:
<div id="container">
<img src="xxx.png" />
</div>
if i am drag that img element out of the div. i will remove
the img element, but i do not know how to detect when the img is out of div.
i am use jquery drag and drop library.
There is an easy way to do this.
Set child to draggable
Set parent to droppable
Set a flag which if true on drag stop removes the element
Unset this flag in the parents on drop function
child dragged out of parent == child not dropped into parent
So when you move the child around in the parent nothing happens (removeMe flag is unset) and it moves back to original position.
If you drag the child outside of the parent the removeMe flag isn't unset and the drag stop method removes the child.
javascript
$("#draggable").draggable({
start: function(event, ui) {
// flag to indicate that we want to remove element on drag stop
ui.helper.removeMe = true;
},
stop: function(event, ui) {
// remove draggable if flag is still true
// which means it wasn't unset on drop into parent
// so dragging stopped outside of parent
if (ui.helper.removeMe) {
ui.helper.remove();
}
},
// move back if dropped into a droppable
revert: 'valid'
});
$("#droppable").droppable({
drop: function(event, ui) {
// unset removeMe flag as child is still inside parent
ui.helper.removeMe = false;
}
});
html
<div id="droppable">
<p id="draggable">Drag me!</p>
</div>
thank your provides a solution.
I have found an other solution without need an outer div for this problem.
I am use "distance" option to detect how long mouse has moved, then use
"stop" option to remove element.
$(".droppable").droppable({
drop: function(event, ui) {
var obj = $(ui.draggable).clone();
obj.draggable({
distance: 100,//used to measure how far my mouse moved.
helper: 'clone',
opacity : 0.35,
stop: function(event, ui) {
$(this).remove();//remove this element.
}
}
);//obj.draggable
}//drop
})
you need to add a div outside of your container
<div id="droppableDiv">
<div id="container">
<img src="xxx.png" />
</div>
</div>
and then make it droppable by adding a function similar to:
$("#droppableDiv").droppable ({
drop: function() { alert('dropped'); }
});
instead of the alert('dropped'); part you could add a little bit of code that removes the img element from the container div.
here is a example that does some other thing but makes use of droppable and draggable objects, maybe it can help you understand how it works!
hope this helps
-Fortes
Related
I am using leaflet markers in my ASP.NET MVC 5 application.
I need to drag marker outside application to a div element, where I want to get its id to perform further operations.
marker=new L.marker([latNumber,longNumber], {draggable:'true'});
marker.id = "ABC";
$('#'+ marker.id).draggable(); // draggable jquery UI
marker.on('dragend', function(event){
var marker = event.target;
var position = marker.getLatLng();
console.log(position);
marker.setLatLng(position,{draggable:'true'}).bindPopup(position).update();
});
On the other hand I am using droppable element of jquery UI
$("#navs").droppable({
drop: function (event, ui) {
alert('dropped')
}
});
I do not get dropped event on navs element when I drop it over it. What changes I need to do to make it work.
If someone can further explain this, it would be of great help too.
Actually, there seems to be a workaround. Leaflet markers calls an event "add" after the marker is added to the map, and becomes visible. In that event you can initialize a draggable on the icon corresponding to that marker.
m=L.marker([lat,lng],{
title:title,
draggable:true
});
m.on("add",function(){
$(this._icon).data("marker",this);
$(this._icon).draggable({
appendTo:"body",
helper:"clone",
zIndex:1000
});
});
"appendTo" is required for dragging outside of leaflet panel. zIndex should be higher than leaflet map zIndex (not sure if it's fixed, it's 600 on my page). Probably, you will need a helper function for copying an icon, I've customized my helper (marker is accessible via data "marker").
I've used that with leaflet 1.0.3.
You can't drag a Leaflet marker outside the map.
The draggable option of a marker and the draggable concept of jQuery are completely different.
That beeing said, you can pretend a marker is dragged by using the image of the marker an place it above the map: it is not part of the map, but it looks like (that is what the link you mention is referring to)
<div>
<div id='map'></div>
<img style="position: absolute; left: 300px; top: 200px; z-index: 1000" id="fakeMarker" src="https://unpkg.com/leaflet#1.0.1/dist/images/marker-icon.png"></img>
</div>
<ul id="liste">
<li>A</li>
<li>B</li>
<li>C</li>
<li>D</li>
</ul>
<div id="log"></div>
<script>
$( function() {
$("#fakeMarker").draggable();
$( "#liste li" ).droppable({
accept: "#fakeMarker",
drop: function( event, ui ) {
$( "#log" ).html("dropped on " + $(this).html());
}
});
} );
</script>
Here is an example: https://yafred.github.io/leaflet-tests/20161120-drag-and-drop-outside-map/
here's the function:
$('.popoutlink').on('click', function() {
var box = $('#' + $(this).data('box'));
box.siblings().hide();
box.toggle("slide", { direction: "left" }, 500);
box.siblings().hide();
});
the two siblings.hide statements are because I'm in the middle of trying to figure out why I'm left with two slideouts on screen if I click on two buttons in rapid succession.
The html is:
<div class="col-md-2">
<div class="popoutlink" data-box="p1">1</div>
<div class="popoutlink" data-box="p2">2</div>
<div class="popoutlink" data-box="p3">3</div>
<div class="popoutlink" data-box="p4">4</div>
<div class="popoutlink" data-box="p5">5</div>
</div>
<div class="col-md-10 bb" style="height: 400px;">
<div class="popout" id="p1"><h1>panel 1</h1></div>
<div class="popout" id="p2">
<h1>panel 2</h1>
</div>
If I click on two buttons quickly then two windows are left on screen. I would like the siblings to hide before the selected div appears.
I have tried using promise.done():
box.siblings().hide(200).promise().done(function(){
box.toggle("slide", { direction: "left" }, 500);
});
to no effect. Adding box.toggle to hide as a callback:
box.siblings().hide(200, function(){
box.toggle("slide", { direction: "left" }, 500);
});
was very funny but not useful.
How do I get the siblings to go away reliably before I show the selected div no matter how quickly I click the buttons?
You see it here just click on the numbered boxes quickly
Thanks
If I understand your question, this should help:
https://jsfiddle.net/Twisty/3mbh5p0r/
jQuery UI
$(function() {
$('.popoutlink').on('click', function() {
var box = $('#' + $(this).data('box'));
$(".popout").hide();
//box.siblings().hide();
box.toggle("slide", {
direction: "left"
}, 500);
//box.siblings().hide();
});
});
When any of the "links" are clicked, they are all hidden and then only the one whom was clicked is toggled.
Update
A little more testing of .hide() versus .css("display", "none") revealed that changing the CSS was a faster method. This page talks about how it's immediate but I found that it wasn't as fast.
The matched elements will be hidden immediately, with no animation.
This is roughly equivalent to calling .css( "display", "none" ),
except that the value of the display property is saved in jQuery's
data cache so that display can later be restored to its initial value.
If an element has a display value of inline and is hidden then shown,
it will once again be displayed inline.
And:
Note that .hide() is fired immediately and will override the animation
queue if no duration or a duration of 0 is specified.
I did try using the callback, which made it worse. The callback should be triggered when the hide animation is complete, yet it added the element of animating the hide operation. Even when the speed was 0, it was slower.
So I advise this:
$(function() {
$('.popoutlink').on('click', function() {
$(".popout").css("display", "none");
$('#' + $(this).data('box')).show("fast");
});
});
I have an image that I drag from one part of the page and drop into a DIV. No problem. But when I just drag the image around inside its new DIV home, I still trigger the DIV's drop handler. Is there an easy way to disable the drop handler for elements that are already in the droppable?
Thanks
You can add a class to the dropped element, then in the drop function check if the element have that and if so exit the drop function.
In my example I clone the element in a new one on drop, if you use the dragged you must change the selected element.
Code:
$(document).ready(function () {
$(".doodad").draggable({
helper: 'clone',
scroll: true
});
$(".dropped").draggable({
containment: ".box"
});
$(".box").droppable({
accept: ".doodad",
activeClass: "ui-state-default",
hoverClass: "ui-state-hover",
drop: function (e, ui) {
if ($(ui.draggable).hasClass('copied')) return
alert('dropped');
var droppedItem = $(ui.draggable).clone().addClass('copied').css({
position: "relative",
top: $(ui.helper).position().top - $(this).position().top,
left: $(ui.helper).position().left - $(this).position().left
}).draggable({
containment: ".box"
});
$(this).append(droppedItem);
}
});
});
Demo: http://jsfiddle.net/IrvinDominin/hLxAd/
I'm trying to allow dropped elements to be both draggable and resizeable within the parent container.
Here is my CSS:
.toolitem {padding:5px 10px;background:#ececec;border:1px solid silver}.labelitem {width:114px;padding:10px 5px;color:#222;background:#fff;border:1px solid silver}
Here is my html:
<header>
<ul>
<li><div id="atool" class="toolitem droppable">A</div></li>
<li><div id="btool" class="toolitem droppable">B</div></li>
</ul>
<div class="clear"></div></header><section id="container"/>
Here is my JS:
$(".toolitem").draggable({
opacity:1,
tolerance:'fit',
helper:'clone'
});
$("#container").droppable({
accept:'.droppable',
drop: function (event, ui) {
// Check for new or already dropped element
var dropped = ui.draggable.data("dropped");
if (dropped == null && dropped != "1") {
// Create new element only once
var label = $('<div class="labelitem droppable">[Label]</div>');
// Set flag as dropped
label.data("dropped", "1");
// Make new element draggable within parent
label.draggable({ containment: 'parent', grid: [2, 2], helper: 'original' });
// Make new element resizable within parent
label.resizable({ containment: 'parent' });
// Append new element to parent
label.appendTo(this);
}
}
});
The above code executes well, except the dropped div is not resizeable. Please help.
I solved it myself. After googling for an hour, I found I was missing the following include
<link type="text/css" rel="stylesheet" href="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.18/themes/base/jquery-ui.css" />
It was needed for resizing div's styles. Everything is now working as expected. But, strange it is never mentioned in jQueryUI documentation or did I miss it.
I am using Jquery UI tabs, and have it set to toggle the opacity with each slide change. I'm wondering if there's a way to apply the opacity toggle to only a single element within each tab, instead of the entire tab. My understanding of jQuery is pretty basic, so bear with me.
So, If I have something like this:
<div id="tabs">
<ul id="tabs-nav><li></li></ul>
<div id="tab-1">
<img />
<p />
</div>
<div id="tab-2">
<img />
<p />
</div>
...etc
</div>
How could I set it so that only the <img> has an effect applied, and the rest just switches normally?
Here are the basics of the call I have for UI tabs:
var $tabs = $('#slides').tabs({fx: { opacity: 'toggle' } });
$(".ui-tabs-panel").each(function(i){
//stuff to create previous/next links
});
$('.next-tab, .prev-tab').click(function() {
$tabs.tabs('select', $(this).attr("rel"));
return false;
});
UPDATE: So this is what I ended up with based on karim79's suggestions, and it seems to work. I added this after the original code I showed above (and removed {fx: { opacity: 'toggle' } } from my original code):
$( "#slides" ).bind( "tabsselect", function(event, ui) {
$(ui.panel).find("img").fadeOut().fadeIn();
});
I'm going to explain my logic, because like I said, my understanding is basic, so I'd love to know if my rationale is off!
I removed karim79's coniditional statement, because I want this to apply to ALL of the tabs. Am I correct in understanding that an if(ui.index == 2) would only apply to the third tab?
Then, I changed the .css("opacity", 0.6) to .fadeOut().fadeIn() because the .css opacity was only succeeding in making all of the slides semi-transparent, but not fading anything in or out.
Would this be an acceptable way of doing this or is it somehow hackish?
This should do it:
$( ".selector" ).bind( "tabsselect", function(event, ui) {
if(ui.index == 2) { // or whatever index you're interested in
$(ui.panel).find("img").css("opacity", 0.6);
}
});