Let's say I have created something similar to this: Link
Now I want to move content with drag.
So far so good and I was able to move them using jQuery UI Draggable.
I change the slider position when the content being dragged.
But when I move the content with drag and after that when I want to use slider button to move content, the position of content is wrong and not working.
Here is my code so far :
slider.slider({
orientation : 'horizontal',
max : w_width -(one_divs_w*numberOfItemVisibleInScreen),//total width minus one content div width
min : 0,
value : 0,
slide : function(event, ui) {
fp_thumbScroller.scrollLeft(ui.value);
},
});
//initialize the draggable
fp_content_wrapper.draggable({
axis: 'x',
cursor: "move",
drag: function (event, ui) {
maxDrggable = - (w_width -(one_divs_w*numberOfItemVisibleInScreen));
if (ui.position.left < maxDrggable) {
ui.position.left = maxDrggable;
}
if (ui.position.left > 0) ui.position.left = 0;
// ****
// set position for slider
// *****
slider.slider('value', -(ui.position.left));
},
});
should I change the position of draggable when moving content with slider ?
Related
I have a draggable element, which is also resizable and rotatable. These rotations are handled by CSS transformations, however, when an element is rotated, it makes the draggable feature spin out of control.
Heres a (updated) fiddle: Click me
What I think happens is that when an element is rotated, it's height and width obviously stay the same, just at an angle, however, jQuery doesn't account for the rotation, making it think that the element is in it's normal horizontal way, which results in the "bugg" shown in the fiddle above.
In a wild goose chase for the answer, I read somewhere that this would do the trick:
refreshPositions: true,
But it didn't work. Neither did destroying the draggable function on the element and then reinitiating it. Is there a way to fix this, so the containment will function normally, thus making jQuery recognise the rotation?
Thanks.
One option is to handle the containment yourself. Here is one possible way to do that.
I am using getBoundingClientRect to get the height and width of the rotated element. Using these values I can get an idea of where the dragged element resides in relation to it's parent container and force it to stay within those bounds.
var boundingContainer, boundingDraggable, prevLeft, prevTop;
$(".draggable").draggable({
classes: {
"ui-draggable-dragging": "highlight-draggable"
},
start: function(event, ui) {
boundingDraggable = ui.helper[0].getBoundingClientRect();
boundingContainer = ui.helper.closest('#draggableContainer')[0].getBoundingClientRect();
},
drag: function(event, ui) {
if(ui.offset.left <= boundingContainer.left){
if(ui.position.left < prevLeft){
ui.position.left = prevLeft;
}
}
if(ui.offset.top <= boundingContainer.top){
if(ui.position.top < prevTop){
ui.position.top = prevTop;
}
}
if(ui.offset.left+boundingDraggable.width >= boundingContainer.right){
if(ui.position.left > prevLeft){
ui.position.left = prevLeft;
}
}
if(ui.offset.top+boundingDraggable.height >= boundingContainer.bottom){
if(ui.position.top > prevTop){
ui.position.top = prevTop;
}
}
prevLeft = ui.position.left;
prevTop = ui.position.top;
}
});
Fiddle
I am making a slider that have 3 images and they are draggable with limits , I am using UI touch punch to make the mobile drag work.
This is my js code so far :
$(".draggable").draggable({
axis: "x",
drag: function(event, ui) {
//$(window).scrollTo(0, scrollPage);
//window.scrollBy(0,scrollPage);
if (ui.position.left > 0) {
newLeft = 0;
} else if (ui.position.left < max_drag) {
newLeft = max_drag;
} else {
newLeft = ui.position.left;
}
ui.position.left = newLeft;
}
});
and this is what i want to achieve :
now everything works except on mobile when i scroll vertically over the draggable element it doesn't scroll even tho the draggable is only on x axis.
I have searched and fuond this :
jQuery UI draggable prevents scrolling on mobile
And
jQuery UI Draggable and Page Scrolling (on mobile)
but I couldnt get a clear solution or answer.
I have draggable elements with full screen width listed vertically.
I am using a plugin called (jquery.ui.touch-punch) to enable jQuery draggable on mobile. But the problem is that the draggable elements prevent the user from scrolling the page.
$('#novieList .element .content').draggable({
axis: 'x',
revert: function() {
return $(this).position().left < 30;
},
containment: [ 0, 0, 75, 0 ],
scope: 'element',
scroll: false,
delay: 300,
drag: function(event, ui) {
return true;
},
start: function(event, ui) {
// Prevent to drag the element after open it
var left = $(this).position().left;
return left == 0;
},
stop: function(event, ui) {
var left = $(this).position().left;
if (left != 0) {
$(this).offset({left: 75});
}
return true;
}
});
I don't believe commenting out event.preventDefault() in jquery.ui.touch-punch.js works any longer. I tried the same solution and found that jQuery UI draggable itself was blocking the default behavior of a vertical scroll -- even when the element is set to drag only along the x-axis.
The solution that worked for me was to measure any change in the cursor's vertical position and use window.scrollBy to manually scroll the window by the same amount:
var firstY = null;
var lastY = null;
var currentY = null;
var vertScroll = false;
var initAdjustment = 0;
// record the initial position of the cursor on start of the touch
jqDraggableItem.on("touchstart", function(event) {
lastY = currentY = firstY = event.originalEvent.touches[0].pageY;
});
// fires whenever the cursor moves
jqDraggableItem.on("touchmove", function(event) {
currentY = event.originalEvent.touches[0].pageY;
var adjustment = lastY-currentY;
// Mimic native vertical scrolling where scrolling only starts after the
// cursor has moved up or down from its original position by ~30 pixels.
if (vertScroll == false && Math.abs(currentY-firstY) > 30) {
vertScroll = true;
initAdjustment = currentY-firstY;
}
// only apply the adjustment if the user has met the threshold for vertical scrolling
if (vertScroll == true) {
window.scrollBy(0,adjustment + initAdjustment);
lastY = currentY + adjustment;
}
});
// when the user lifts their finger, they will again need to meet the
// threshold before vertical scrolling starts.
jqDraggableItem.on("touchend", function(event) {
vertScroll = false;
});
This will closely mimic native scrolling on a touch device.
I found a solution to that problem at Scrolling jQuery UI touch punch. You have to remove a event.preventDefault() in jquery.ui.touch-punch.js on line 38. So far I have only tested on Sony Xperia Z1 Compact, Android 5, Chrome, but it works very well in a project very similar to one named here.
I had the problem regarding that I could scroll on mobile when my div was dragable, as the CSS of the Jquery UI had the following code set to none, so by reverting the changes by putting them on initial everything worked again!
.ui-draggable-handle {-ms-touch-action:initial!important;touch-action:initial!important}
I am using Jquery ui and it provide a function for me to make draggable content. It has an option 'containment' that force the draggable item move within the box.
However, for my case, the content (image) must exceed the screen , how can I force it not to drag inside the screen?
Thanks
$("#popup").draggable({
addClasses:true,
scrollSpeed: "200",
containment: "parent",
//appendTo: "body",
helper: function(){
// Create an invisible div as the helper. It will move and
// follow the cursor as usual.
return $('<div></div>').css('opacity',0);
},
drag: function(event, ui){
// During dragging, animate the original object to
// follow the invisible helper with custom easing.
var p = ui.helper.position();
$(this).stop().animate({
top: p.top,
left: p.left
},1000,'easeOutCirc');
}
});
My page has several items (divs) that are draggable and resizable.
My code for doing this is given below:
part.draggable(
{
containment: 'parent',
drag: function(event, ui){
partIsDragging = true
part.prev().css('top', ui.position.top - 20 ).css('left', ui.position.left )
part.prev().show()
},
stop: function(event, ui) {
partIsDragging = false
}
}).resizable({
containment: 'parent',
handles: 'ne, se, sw, nw,n,w,e,s',
stop: function() {
}
});
The html structure for these is the following:
<body>
<div id="wrapper">
<div class="draggableItem"></div>
<div class="draggableItem"></div>
<div class="draggableItem"></div>
<div class="draggableItem"></div>
</div>
</body>
In my css files i have set body height: 100% and wrapper height: 100%. Width is always fixed for wrapper, width: 950px. I want my div to expand in height when the draggableItem reaches the bottom of the wrapper. Right now when the page is loaded, it has the height as big as the resolution allows it but in case I have more items in the wrapper then everything becomes cluttered and I would like when dragging an item to somehow expand the wrapper in height dynamically. This should happen only if I hit the bottom border.
PS: I am using jQuery and jQuery-ui.
I may have a solution. First off, I replaced part with '.draggableItem' and this where appropriate. Please tell me if that breaks the code in some critical way. In addition, I removed part.prev().css('top', ui.position.top - 20 ).css('left', ui.position.left ) in the code below.
function adjustWrapperHeight(movingObject)
{
var objectBottomPosition = $(movingObject).offset().top+$(movingObject).height()
var wrapperBottomPosition = $("#wrapper").offset().top+$("#wrapper").height()
if(wrapperBottomPosition-objectBottomPosition<distanceBuffer)
{
$("#wrapper").height($("#wrapper").height()+distanceBuffer+1)
}
}
var distanceBuffer = 20;
$('.draggableItem').draggable(
{
containment: 'parent',
drag: function(event, ui)
{
partIsDragging = true
adjustWrapperHeight(this)
},
stop: function(event, ui)
{
partIsDragging = false
}
}).resizable(
{
handles: 'ne, se, sw, nw,n,w,e,s',
resize: function(event, ui)
{
adjustWrapperHeight(this)
var objectRightPosition = $(this).offset().left+$(this).width()
var wrapperRightPosition = $("#wrapper").offset().left+$("#wrapper").width()
if(wrapperRightPosition<=objectRightPosition)
{
$(this).width(ui.originalSize.width)
var containmentLeftPosition = wrapperRightPosition-$(this).width()
$(this).offset({top:$(this).offset().top,left:containmentLeftPosition})
}
}
})
})
The function adjustWrapperHeight(movingObject) adjusts div#wrapper's height depending on a movingObject's bottom position. That is, when movingObject "pushes up" against div#wrapper's borders, it adjusts div#wrapper's height.
I had to use a hack for resizable. The containment: 'parent' for resizable (but not draggable) sets the containment to the container's ORIGINAL height or so it seems. That means as the height of div#wrapper dynamically changes, the constraint set by containment: 'parent' does not dynamically change. To fix this, I removed containment: 'parent' and indeed the entire containment and ensured that div#wrapper's right containment isn't broken within the resize event. Note that you should probably do this with div#wrapper's left containment as well.
Please tell me if this was helpful. Thank you.