On dragging an item to a new location I would like to output the new position of the item. for example
Col = 1
Position = 3
meaning the widget has been moved to the first col 3rds down.
I am using this script http://net.tutsplus.com/tutorials/javascript-ajax/inettuts/
I think the best place to put this is at the point below. However I tried
ui.item.index to get the new position and this just gives me the value - 1 not the position of the dragged object as excepted. Any ideas?
$(settings.columns).sortable({
items: $sortableItems,
connectWith: $(settings.columns),
handle: settings.handleSelector,
placeholder: 'widget-placeholder',
forcePlaceholderSize: true,
revert: 300,
delay: 100,
opacity: 0.8,
containment: 'document',
start: function (e,ui) {
$(ui.helper).addClass('dragging');
},
stop: function (e,ui) {
alert("New position: " + ui.item.index());
$(ui.item).css({width:''}).removeClass('dragging');
$(settings.columns).sortable('enable');
}
});
Looking at the demo on the nettuts site: Demo
ui.item is already a jQuery object so you can reference it as such.
0-based index position of the column:
ui.item.parent().parent().children().index(ui.item.parent())
0-based index position of the item:
ui.item.parent().children().index(ui.item);
so if you were to drag an item underneath the "Welcome to iNettuts" in the first column the above code would return 0 for column (so the first column) and 1 for the item position (so the second item in the column)
Just to inform you: the script is currently not working on Internet Explorer 9 - the drag functionality fails to work.
I found the following 'workaround':
add
<meta http-equiv="X-UA-Compatible" content="IE=8">
to your page.
Related
I have row with multiple columns inside it. Column width is devided by number of columns, to reach 100% of row width. User is able to update column width by dragging the edge of it. Ive been googling whole day for a script such as this one http://dobtco.github.io/jquery-resizable-columns/ but that would work on divs, not table columns, and no luck.
So i went with draggable solution, but as it does not have "containment" update during drag or after drag. I had to change draggable.js file, and it works - http://itsgoran.com/draggable/ , but i would prefer not to change draggable.js file.
I added:
o.containment = [parseInt(this.offsetParent.offset().left) + 40,0,parseInt(this.offsetParent.next().offset().left + this.offsetParent.next().width() - 40),0];
inside "_setContainment" method.
And inside _mouseStop() event, called this._setContainment();
Is there a way around this, so that i dont have to change core file ? Or some other script that would work?
Just calling _setContainment() method didnt work either.
Thanks
I managed to solve it by adding whole code to the function and running it again during "stop" callback. That way draggable is reinitiated again with updated containment. BUT i am not sure about memory usage this way ?
Here is the full code:
function init_draggable(){
$(".ui-draggable").each(function(){
var $this = $(this);
var $left = parseInt($(this).parent().offset().left) + 100,
$right = parseInt($(this).parent().next().offset().left) + 50;
console.log($left);
$(this).draggable({
axis: 'x',
refreshPositions: true,
start: function(event, ui) {
elWidth = $(this).parent().width();
nextWidth = $(this).parent().next().width();
},
drag: function(event, ui) {
$(this).parent().width( elWidth + (ui.position.left-ui.originalPosition.left) );
$(this).parent().next().width( nextWidth - (ui.position.left-ui.originalPosition.left) );
},
stop: function(event, ui) {
$(".ui-draggable").each(function(){
$(this).css({"left":'auto','right':'0'});
});
init_draggable();
},
containment: [parseInt($(this).parent().offset().left) + 40,0,parseInt($(this).parent().next().offset().left + $(this).parent().next().width() - 40),0]
});
});
}
init_draggable();
EDIT: JSFIDDLE: http://jsfiddle.net/h9yzsqfr/
--
Code:
elem.editor.find("div.ui-widget").draggable(
{
handle:"div.content",
containment:elem.editor,
snap:"*",
start: function(e,ui)
{
$(ui.helper).addClass("dragging");
},
drag: function(e,ui)
{
checkTop(ui);
if($(ui.helper).parents("div.lo-content").length > 0)
{
$(ui.helper).appendTo(elem.editor);
ui.position = { 'top': e.pageY, 'left': e.pageX };
}
},
stop: function(e,ui)
{
oldWidget.saveState($(ui.helper),1);
setTimeout(function() {
$(ui.helper).removeClass("dragging");
}, 300);
}
});
I have some draggable objects within a container defined by elem.editor; however I have some other draggable objects inside div.lo-content which is also inside elem.editor.
Whenever an object inside div.lo-content is dragged, it should reattach to the elem.editor container which is working fine; however as demonstrated in the following GIF (below), it is not setting the position of the draggable object to where the mouse cursor is.
What is a workaround for this problem?
The problem is your width: 100% and the containment option. As soon as its appended to body it stays 100%, but of the body, then it gets smaller but the containment has already been calculated.
One way to solve it is to reset containment. There are probably different ways to do it, one way could be like this:
start: function (e, ui) {
if ($(this).parents(".inner").length > 0) {
$(ui.helper).addClass("dragging");
ui.helper.css({
'width': '100px',
'left': '0px',
'top': '0px'
});
ui.helper.data()['ui-draggable'].containment = [0,0,$('body').width(), $('body').height()]
ui.helper.appendTo("body");
}
},
http://jsfiddle.net/puurqx8r/6/
connectToSortable
It's a Selector that Allows the draggable to be dropped onto the specified sortables. If this option is used, a draggable can be dropped onto a sortable list and then becomes part of it. Note: The helper option must be set to "clone" in order to work flawlessly. Requires the jQuery UI Sortable plugin to be included.
Code examples:
Initialize the draggable with the connectToSortableoption specified:
$( ".selector" ).draggable({
connectToSortable: "#my-sortable"
cursorAt:{top: 5, left: t}
});
Use cursorAt: top:, left: and appendTo: 'body'
See my answer with example here.
jQuery draggable shows helper in wrong place after page scrolled
I had the same problem. This is caused by the use of margins to center elements. Try using position absolute!
I removed position:absolute on dragable object
I am trying to copy drop element in div , but the problem is when i dropped element and change image src of already present attribute , drag element remaining same still drag-able.
Fiddle
js code snippts ::
$('.piece').draggable({
revert: 'invalid',
start: function (event, ui) {
// alert('drag start');
var td_height = $('td').height();
var draggedID = $(this).width(td_width).height(td_height);
}
});
$("td").droppable({
accept: ".piece",
drop: handleDrop
});
function handleDrop(event, ui) {
alert('hello' + $(this).attr("id"));
var drop_src = ui.draggable.attr("src");
$(this).addClass("ui-state-highlight");
//$( this ).find( "img" ).attr("src",drop_src);
$(this).append(ui.draggable.clone().removeClass().addClass('new_piece'));
ui.draggable.draggable('option', 'revert', false);
}
});
Scenario 1:
If we continue from where you left your JSFiddle, there are a number of problems, each of which may have better solutions than shown, but here goes:
http://fiddle.jshell.net/Z9HDP/1
You are dropping onto a TD that already contains an image, but you are not removing the existing image before appending a new one. I assumed you did not want them lining up side-by-side, so have made it remove the existing content of the TD first.
You are cloning the dragged object, which includes its relative offset of the dragging, but are not removing the top and left style values. This means your clone is above and to the right of the table (usually off-the-grid in the Fiddle, so not visible). I am removing the top and left offsets.
You are not resetting the position of the original dragged item, which leaves it where you dropped it. I assumed you wanted it back in the palette and there may be a better way, but I just reset the top & left to 0.
function handleDrop(event, ui) {
//alert('drop ' + $(this).attr("id"));
var drop_src = ui.draggable.attr("src");
//alert(drop_src);
$(this).addClass("ui-state-highlight");
//$( this ).find( "img" ).attr("src",drop_src);
$(this).empty().append(ui.draggable.clone().removeClass().addClass('new_piece').css("left", "").css("top", ""));
// Reset position of dragged item
ui.draggable.css({
top: "",
left: ""
});
ui.draggable.draggable('option', 'revert', false);
}
Scenario 2:
If you want to go with your original comment, of changing the target source, this appears to work. I am guessing you were just missing the position reset of the dragged item:
http://fiddle.jshell.net/Z9HDP/3/
function handleDrop(event, ui) {
//alert('drop ' + $(this).attr("id"));
var drop_src = ui.draggable.attr("src");
$(this).addClass("ui-state-highlight");
$(this).find("img").attr("src", drop_src);
// Reset position of dragged item
ui.draggable.css({
top: "",
left: ""
});
ui.draggable.draggable('option', 'revert', false);
}
For my application, after an element is dragged and snapped to the droppable zone I need to continue to allows for that dragged item to be moved vertically only. I have already gone ahead and done this, but I also need for that item to only be dragged and snapped to pixel increments. How can this be done?
For example, I have a timeline and I need the elements to snap to 15 minute increments. I need to know if this is possible with the draggable function or do I need to come up with some slider hybrid? I'd rather not use some hybrid approach if possible.
Code Snippet:
$(".activity_link").draggable({
"snap": ".trek_slider",
"snapMode": "inner",
// "snapTolerance" : 30,
"revert": function (event, ui) {
// on older version of jQuery use "draggable"
// $(this).data("draggable")
// on 2.x versions of jQuery use "ui-draggable"
// $(this).data("ui-draggable")
$(this).data("uiDraggable").originalPosition = {
top: 0,
left: 0
};
$(this).draggable("option", "axis", false);
// return boolean
return !event;
// that evaluate like this:
// return event !== false ? false : true;
}
});
$(".trek_slider").droppable({
"tolerance": "touch",
"over": function (event,
ui) {
var left_position = parseInt($(ui.draggable).css("left"));
$(ui.draggable).find(".activity_caret").show();
$(ui.draggable).draggable("option", "axis", "y");
}
});
Try this
$( ".your_div" ).draggable({ grid: [ 1,1 ] });
In above example it will be draggedx by only one pixel in each direction
Please Note: Do not forget to add your other options.
Edit#1:
Since I asked this problem, I made a script which allows the elements to move together, but with problems. :(
$(this).append(
$('<div class="elem '+classes+'" style="width: 210px; height: 30px" data-modby="'+ui.draggable.attr("data-for")+'"><p>'+text+'</p></div>')
.resizable({
grid: 10,
maxHeight: 120,
maxWidth: 600,
minHeight: 30,
minWidth: 210,
containment: ".box-section"
})
.draggable({
grid: [10,10],
containment: ".box-section",
scroll: false,
helper: "original",
start: function(event, ui) {
posTopArray = [];
posLeftArray = [];
if ($(this).hasClass("r-active")) {
$(".elem.r-active").each(function(i) {
thiscsstop = $(this).css('top');
if (thiscsstop == 'auto') thiscsstop = 0;
thiscssleft = $(this).css('left');
if (thiscssleft == 'auto') thiscssleft = 0;
posTopArray[i] = parseInt(thiscsstop);
posLeftArray[i] = parseInt(thiscssleft);
});
}
begintop = $(this).offset().top;
beginleft = $(this).offset().left;
},
drag: function(event, ui) {
var topdiff = $(this).offset().top - begintop;
var leftdiff = $(this).offset().left - beginleft;
if ($(this).hasClass("r-active")) {
$(".elem.r-active").each(function(i) {
$(this).css('top', posTopArray[i] + topdiff);
$(this).css('left', posLeftArray[i] + leftdiff);
});
}
}
})
);
The actual problem is the moved elements have to stay in the containment box (called .box-section and if I have a single element it works fine. Also if i have two elements has not the same width, if i pick the sorter one and drag, I can pull out the longer of the container.
Also, if I move them fast (like a ninja) they will slip, and they won't be in the same grid they used to be.
30 percent solved since:
I'm going to make a new thingy which can drag and drop items to a box, and resize them.
My problem is that, I can't make them move together. But with some rules.
Rule one: They must move based on a 10x10px grid.
Rule two: They can't move outside their frame.
(Resize is an issue which i simply can't imagine, so I don't care about it, resize will be later)
I made a fiddle for it here: http://jsfiddle.net/9fueY/ you can see this.
In the right side, you can see inputs and a and a checkbox (and on hover a button).
The checkbox is the draggable object, drag it to the image. Now you have some text or a star appeared on the left.
If you type anything to the inputs, it refreshes the text.
OnHover the right boxes you can see a button. By clicking on it, will make a clone of the first element. Drag it inside.
If you click to a right-side box, it will glow blue. Click to two boxes on the right, makes all the two textfields glow blue in the image.
Now this is the case when i want them to move together. :D
What's your opinion, what should I do with this?
Thank you very much. - Répás
There is a plugin i developed for dragging elements together. Please do use it if it makes sense.
https://github.com/someshwara/MultiDraggable