Selected HTML DIV element draggable using JQueryUi draggable - javascript

I've an array of jQuery objects which are draggable.
What I want is when any element present in the array is dragged, All other elements should also be dragged.
Following is sample code that I have tried but I haven't got any success
$(event.target).parents('.ui-class-name').draggable({
disabled : false,
helper: function() {
var allSelectedEle = $($selected).map( function() {
return this.toArray()
});
return allSelectedEle;
}
});
Here $selected is the array of jQuery object
Update: Here is the sample markup

You need to save initial coordinates of elements, and update them while you dragging them (demo):
var els = $('.eq-ui-widget')
var coords = { x: 0, y: 0 }
function getSelected() {
return els.filter('.selected')
}
els
.draggable({
disbled: true,
drag: function(e, ui) {
getSelected().each(function() {
var orig = $(this).data().orig
$(this).css({
top: orig.top + (ui.position.top - coords.y) ,
left: orig.left + (ui.position.left - coords.x)
})
});
},
start: function(e, ui) {
coords.x = ui.position.left;
coords.y = ui.position.top;
getSelected().each(function() {
$(this).data().orig = $(this).position();
});
}
})
.on('click', function(event) {
if(!event.ctrlKey) return;
$(event.target).toggleClass('selected');
/*logic for dragging all selected elements simultaneously*/
var selected = getSelected()
els.draggable('option', 'disabled', true )
selected.draggable('option', 'disabled', false )
});

Related

jQuery draggable change image size on drag start, restore original size on revert

I have a set of divs all different sizes with the same class .gjg-item. I have it so you can drag and drop these divs into each others positions.
How can I tell jquery to not only shrink the image on dragstart but to resotre it to it's original size on revert?
Here is the code I am using:
$('.gjg-item').draggable({snap: true, snapMode: 'inner', revert: 'invalid'});
$('.gjg-item').droppable({accept: '.gjg-item', hoverClass: "ui-state-hover"});
$('.gjg-item').on('dragstart', function(event, ui) {
$(this).css('z-index', '9999999').width(50).height(50);
$(this).find('img').width(50).height(50);
});
$('.gjg-item').on("dropover", function(event, ui){
var draggingImgID = ui.draggable[0].id;
var hoverPositionSize = $(this).width();
if($(this).attr('data-pid') != draggingImgID) {
$(this).css('opacity', '.2');
}
});
$('.gjg-item').on("dropout", function(event, ui){
$(this).css('opacity', '1');
});
$('.gjg-item').on("drop", function(event, ui){
$('.gjg-item').draggable('destroy');
$('.gjg-item').droppable('destroy');
var idOfItemDropped = ui.draggable[0].id; // css id of item being dropped
idOfItemDropped = idOfItemDropped.replace('gjg-i-', ''); // parse the id
var droppedImgOldPosition = $('#gjg-i-'+idOfItemDropped).attr('data-position'); // get the image being dropped old position
var droppedImgNewPosition = $(this).attr('data-position'); // get the new position where the image was dropped
//console.log('hello');
$.post( DOMAIN+LIBRARY+"grid/ajax/ajax_dragndrop.php", { gridID: gridID, imageID: idOfItemDropped, oldPosition: droppedImgOldPosition, newPosition: droppedImgNewPosition}, function(data) {
if(data.code == 200) {
$('.gjg-item').remove();
ajaxArea('ni');
}
});
});
You can add code to resize the image of dragstop event like this:
var original_height = 100;
var original_width = 100;
$('.gjg-item').on('dragstop', function(event, ui) {
$(this).css('z-index', '9999999').width(original_width).height(original_height);
$(this).find('img').width(original_width).height(original_height);
});

How can I "destroy" a draggable object, then re-enable it again?

I have a div that is draggable along the Y axis. When the div hits 50px, I destroy the draggable element, then preform a animation to move it back to the start, how can I enable the element to become draggable again once the animation completes?
here is a Fiddle
$( ".box" ).draggable({
axis: "y",
drag: function( event, ui ) {
y2 = ui.position.top;
x2 = ui.position.left;
$('.result').text(y2);
if (y2 > 100) {
$( ".box" ).draggable('destroy')
$('.box').animate({
top:0
}, {
duration:500,
complete: function() {
//$( ".box" ).draggable('enable');//doesn't work
$( ".box" ).draggable({axis: "y"});
}
})
}
}
});
You should rather do this:
object.draggable( 'disable' )
This will disable the object and it wont be draggable.
object.draggable( 'enable' )
After that you can re-enable the drag on the object.
With a bit of tweaking user2436738's answer will work.
You just need to prevent the drag events from updating the position whilst you're animating the box back to its original position:
var reverting = false;
$(".box").draggable({
axis: "y",
drag: function(event, ui) {
var y2 = ui.position.top;
var x2 = ui.position.left;
$('.result').text(y2);
if (reverting){
event.preventDefault();
event.stopImmediatePropagation();
} else if (y2 > 100) {
reverting = true;
revertDrag($('.box'));
}
}
});
function revertDrag(element){
element.draggable('disable');
element.animate({
top: 0
}, {
duration: 500,
complete: function() {
reverting = false;
element.draggable('enable');
}
})
}
Here is a working example: http://jsfiddle.net/Sly_cardinal/F3h2Q/12/

Unable to drop an element on mouseup event

Here is the jQuery code that I have written to drag multiple items at a time. It is draggable now but not droppable.
here is the code
$(document).on('click', function (e) {
var target = e.target;
if (!$(target).hasClass('a')) $('.selected').removeClass('selected');
});
$(document).delegate('.a', 'dblclick', function (e) {
$(this).addClass('selected');
});
$(document).delegate('.selected', 'mousedown', function (e) {
var div = $('<div></div>');
$('.selected').each(function () {
div.append($(this).clone());
});
div.prop('id', 'currentDrag');
$('#currentDrag').css({
left: e.pageX + "px",
top: e.pageY + "px"
});
$('body').append(div);
});
$(document).on('mouseup', function (e) {
var tgt = e.target;
var mPos = {
x: e.pageX,
y: e.pageY
};
$('.drop').each(function () {
var pos = $(this).offset(),
twt = $(this).width(),
tht = $(this).height();
});
if((mPos.x > pos.left) && (mPos.x < (pos.left + twt)) && (mPos.y > targPos.top) && (mPos.y < (pos.top + tht))) {
$(this).append($('#currentDrag').html());
}
$('.drop .selected').removeClass('selected');
$('#currentDrag').remove();
});
$('.drop').on('mouseup', function (e) {
$(tgt).append($('#currentDrag').html());
$('.drop .selected').removeClass('selected');
$('#currentDrag').remove();
});
$(document).on('mousemove', function (e) {
$('#currentDrag').css({
left: e.pageX + "px",
top: e.pageY + "px"
});
});
What is the pronblem with my code and how can I achieve this. here is the fiddle http://jsfiddle.net/mDewr/27/
I would really recommend trying to find a way to make the jQuery UI draggable and droppable libraries work for you. Then the question becomes,
similar to this one: How do I drag multiple elements with JavaScript or jQuery?.
Here's how we can apply one of the answers from that question to your problem. I'm using the jQuery UI multiple draggable plugin, the entire script of which can be found here: jquery.ui.multidraggable-1.8.8.js.
First let's simplify your HTML. By putting our draggable and dropable divs inside of elements, we don't have to apply redundant stylings to each one. Instead we can use the containing element to style
HTML
<div id="parent">
<div id="dragTargets">
<div>123</div>
<div>456</div>
<div>789</div>
</div>
<div id='dropTargets'>
<div></div>
<div></div>
</div>
</div>
Using the plugin we can call multidraggable on each of the drag divs. And droppable anywhere they can be dropped
JavaScript
$("#dragTargets div").multidraggable();
$("#dropTargets div").droppable();
Customize
We can control the appearance with styling. As an example, we'll make anything that can receive drops yellow, anything you're about to drop as red, and anything that has received an element green.
Here's some styling as an example in CSS
.ui-state-highlight { background: green; }
.ui-state-active { background: yellow; }
.ui-state-hover { background: red; }
And we'll control when these classes are applied with JavaScript:
$("#dropTargets div").droppable({
activeClass: "ui-state-active",
hoverClass: "ui-state-hover",
drop: function () {
$(this).addClass("ui-state-highlight")
}
});
Multi-Draggable
You should style the elements that are currently selected. The script will apply the class ui-multidraggable to all the currently selected elements. The following CSS will make it apparent to the user that their choice is selected.
.ui-multidraggable {
background: tan;
}
Check out this demo. Just hold down ctrl to select more than one of the divs and then drag all of them at once.
jsFiddle
There are few errors in you code. You can check errors on browser console.
To check elements over droppable area, you should check the drop area in the each loop, rather than after each loop. When moving mouse, you should better turn off selection to avoid selected text flashing
$(document).on('click', '.a', function (e) {
$(this).removeClass('selected');
});
$(document).on('dblclick', '.a', function (e) {
$(this).toggleClass('selected');
});
$(document).on('mousedown', '.selected', function (e) {
var dragMode = true;
var div = $('<div></div>');
$('.selected').each(function () {
div.append($(this).clone());
});
div.prop('id', 'currentDrag');
$('#currentDrag').css({
left: e.pageX + "px",
top: e.pageY + "px"
});
$('body').append(div);
//disable selection on dropping start
disableSelection();
$(document).on('mousemove.drop', function(e){
onDragging(e, dragMode);
});
$(document).on('mouseup.drop', function(e){
onDragEnd(e, dragMode);
});
});
function onDragEnd(e, dragMode){
if(!dragMode)
return;
var tgt = e.target;
var mPos = {
x: e.pageX,
y: e.pageY
};
$('.drop').each(function () {
var pos = $(this).position(),
twt = $(this).width(),
tht = $(this).height();
if((mPos.x > pos.left) &&
(mPos.x < (pos.left + twt)) &&
(mPos.y > pos.top) &&
(mPos.y < (pos.top + tht))) {
$(this).append($('#currentDrag').html());
}
});
$('.drop .selected').removeClass('selected');
$('#currentDrag').remove();
$('.onDrop').removeClass('onDrop');
//remove listener on docuemnt when drop end
$(document).off('mousemove.drop');
$(document).off('mouseup.drop');
//enable selection
enableSelection();
}
function onDragging(e, dragMode){
if(!dragMode)
return;
var p = $('body').offset();
var mPos = {
x: e.pageX,
y: e.pageY
};
$('#currentDrag').css({
left: mPos.x,
top: mPos.y
});
$('.drop').each(function () {
var pos = $(this).position(),
twt = $(this).width(),
tht = $(this).height();
$(this).toggleClass("onDrop",
(mPos.x > pos.left)
&& (mPos.x < (pos.left + twt))
&& (mPos.y > pos.top)
&& (mPos.y < (pos.top + tht))
);
});
}
function disableSelection(){
$(document).on("selectstart", function(){ return false; });
//firefox
$("body").css("-moz-user-select", "none");
}
function enableSelection(){
$(document).off("selectstart");
//firefox
$("body").css("-moz-user-select", "");
}
I updated your code: http://jsfiddle.net/mDewr/46/, may can help you.
There were several errors, which I'll not list now, but you can compare the old version with the new one.
$(document).on('dblclick', '.a', function (e) {
$(this).toggleClass('selected');
});
$(document).on('mousedown', '.selected', function (e) {
var div = $('<div id="currentDrag"></div>');
$('.selected').each(function () {
div.append($(this).clone(true));
});
var p = $('body').offset();
var l = e.pageX - p.left;
var t = e.pageY - p.top;
console.log(l, ', ', t);
$('body').append(div);
$('#currentDrag').css({
left: l,
top: t
});
});
$(document).on('mouseup', '.selected', function (e) {
$('.d').each(function(index, item){
var $i = $(item);
if (e.pageX >= $i.offset().left &&
e.pageX <= $i.offset().left + $i.width() &&
e.pageY >= $i.offset().top &&
e.pageY <= $i.offset().top + $i.height()) {
console.log('Dropped');
var $cl = $('#currentDrag').find('>*').clone(true);
$i.append($cl);
}
});
$('.selected').removeClass('selected');
$('#currentDrag').remove();
});
$(document).on('mousemove', function (e) {
var p = $('body').offset();
$('#currentDrag').css({
left: e.pageX - p.left,
top: e.pageY - p.top
});
});
http://jsfiddle.net/mDewr/43/
Everything should work perfectly in this version (this is an update).
PS: I've changed to 1.7+ jQuery, but you can easily change it back to <1.7. Also you don't need custom attributes, use css classes instead.

jQuery addClass only affecting current item

I use this code to make a slider function.
$(function() {
$(".slider").draggable({
axis: 'x',
containment: 'parent',
drag: function(event, ui) {
if (ui.position.left > 200) {
$(".well").fadeOut(500, function(){
$( ".well" ).delay(1000).addClass( "disappear" );
$( ".showup" ).delay(500).removeClass( "disappear" );
});
} else {
// $("h2 span").css("opacity", 100 - (ui.position.left / 5))
}
},
stop: function(event, ui) {
if (ui.position.left < 201) {
$(this).animate({
left: 0
})
}
}
});
$('.slider')[0].addEventListener('touchmove', function(event) {
event.preventDefault();
var el = event.target;
var touch = event.touches[0];
curX = touch.pageX - this.offsetLeft - 40;
if(curX <= 0) return;
if(curX > 200){
$('.well').fadeOut();
$(".well").addClass( "disappear" );
$('.well').add('<h2>Erbjudandet använt</h2>');
}
el.style.webkitTransform = 'translateX(' + curX + 'px)';
}, false);
$('.slider')[0].addEventListener('touchend', function(event) {
this.style.webkitTransition = '-webkit-transform 0.3s ease-in';
this.addEventListener( 'webkitTransitionEnd', function( event ) { this.style.webkitTransition = 'none'; }, false );
this.style.webkitTransform = 'translateX(0px)';
}, false);
});
Here is my HTML for displaying the slider:
return "<link rel='stylesheet' href='http://www.infid.se/wp-content/themes/simplemarket/anvandstyle.css'>
<script src='http://ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.min.js'></script>
<script src='http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.2/jquery-ui.min.js'></script>
<script src='http://www.infid.se/wp-content/themes/simplemarket/slidetounlock.js'></script>
<div id='page-wrap'>
<div class='showup disappear'><h2>Erbjudande använt</h2></div>
<div class='well'>
<h2><strong class='slider'></strong> <span>Använd erbjudande</span></h2>
</div>
</div>";
The problem here is that I have about 100 of these sliders, and when slider is activated(The "disappear" class makes it disappear, and the h2 is added on), all of them disappears. Is there a way to make the "disappear" class only affect the current item?
You need to select the element relative to the current slider so change.
$('.well').fadeOut();
$(".well").addClass( "disappear" );
$('.well').add('<h2>Erbjudandet använt</h2>');
to
$well = $(this).closest('.well'); //Select only the respective well element.
$well.fadeOut();
$well.addClass( "disappear" );
$well.add('<h2>Erbjudandet använt</h2>');
.....
$well.prev(".showup").delay(500).removeClass( "disappear" );
Similarly you can change this in other events as applicable.
$(".slider").draggable({
axis: 'x',
containment: 'parent',
drag: function(event, ui) {
if (ui.position.left > 200) {
var $well = $(this).closest('.well');
$well.fadeOut(500, function(){
$well.delay(1000).addClass( "disappear" );
$well.prev(".showup").delay(500).removeClass( "disappear" );
});
} else {
// $("h2 span").css("opacity", 100 - (ui.position.left / 5))
}
},
stop: function(event, ui) {
if (ui.position.left < 201) {
$(this).animate({
left: 0
})
}
}
});
$('.slider')[0].addEventListener('touchmove', function(event) {
event.preventDefault();
var el = event.target;
var touch = event.touches[0];
curX = touch.pageX - this.offsetLeft - 40;
if(curX <= 0) return;
if(curX > 200){
var $well = $(this).closest('.well');
$well.fadeOut();
$well.addClass( "disappear" );
$well.add('<h2>Erbjudandet använt</h2>');
}
el.style.webkitTransform = 'translateX(' + curX + 'px)';
}, false);
Fiddle

Jquery Draggable Element Intersect

I wanna make if Dragged element intersect any draggable elements dragged items revert old position. Any Idea About it?
$( "#MainContents div[name=draggable]" ).each(function() {
$( this ).draggable({containment: 'parent',
scrollSpeed: 1000,
cursor: "crosshair",
scroll:true,
disabled: DragDropState,
stop: function(event, ui) {
var Stoppos = $(this).position();
var parentPosition=$(this).parent().position();
var CalculatedTop=Stoppos.top-parentPosition.top;
var CalculatedLeft=Stoppos.left-parentPosition.left;
}
});
});
you'll need to record where it came from on dragging start and then check for an overlay on dragging stop. check out this jsfiddle example
in a nutshell, extend your draggable options array to include start, record the top/left position in a data object, then on stop, check other draggable items in the DOM and call a revert function if anything matches.
ex:
$( this ).draggable({
start: function() {
var div = $(this);
div.data('top', div.css('top'));
div.data('left', div.css('left'));
},
containment: 'parent',
scrollSpeed: 1000,
cursor: "crosshair",
scroll:true,
disabled: DragDropState,
stop: function(event, ui) {
var draggables = $('.ui-draggable');
var div = $(this);
var goHome = function () {
div.css('left', div.data('left'));
div.css('top', div.data('top'));
};
draggables.not(div).each(function () {
var curr = $(this);
var currPos = curr.position();
var divPos = div.position();
if (divPos.left >= currPos.left && divPos.left <= (currPos.left + curr.width())) {
if (divPos.top >= currPos.top && divPos.top <= (currPos.top + curr.height())) {
goHome();
}
}
});
};
});
i'm pretty sure something like this is what you're looking to do. btw, from here you can animate the revert function so it gracefully goes back where it was last at.

Categories