Reputation: 1488
I'd like users to be able to drag a horizontal menu bar left and right. I realize there are lots of carousel and slider libraries which have this behavior– but none of them fit the situation.
When users drag an LI
, can it pass the new x-offset information to the left margin of the first LI
?
I took a stab at it here: http://jsfiddle.net/n92ng9uz/
The main problem with the above fiddle, is that the offset is still applied to the individual LI
, and if I prevent the event from bubbling up the dragging is no longer smooth.
Upvotes: 10
Views: 345
Reputation: 20359
Since you specified in the comments that it's a requirement to use margin-left
on the first li
element, and not modify the position of the ul
, I am pretty sure that it can't be easily done using jQuery UI draggable. If we were to make the li
draggable, we wouldn't catch mouse events on the other li
s, and if we were to make the ul
draggable, we couldn't easily make it affect only the margin-left
of the first li
and not the position of the ul
.
Here is a live demo of a solution that uses mouse events directly instead of using jQuery UI:
var firstLI = $('li:first-child');
var initx = 0;
var dragstartx = 0;
var dragging = false;
$("ul").mousedown(function(e) {
dragging = true;
dragstartx = e.pageX;
initx = parseInt(firstLI.css("marginLeft"), 10);
});
$("ul").mousemove(function(e) {
if (dragging) {
firstLI.css("marginLeft", (initx + e.pageX - dragstartx) + "px");
}
});
$("ul").mouseleave(function(e) {
dragging = false;
});
$("ul").mouseup(function(e) {
dragging = false;
});
ul {
list-style: none;
margin: 0;
padding: 0;
overflow: hidden;
white-space: nowrap;
-webkit-touch-callout: none;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
ul > li {
display: inline-block;
padding: 10px;
}
ul > li:nth-child(odd) {
background: orangered;
}
ul > li:nth-child(even) {
background: gold;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<ul>
<li>Link 1</li>
<li>Link 2</li>
<li>Link 3</li>
<li>Link 4</li>
<li>Link 5</li>
<li>Link 6</li>
<li>Link 7</li>
<li>Link 8</li>
<li>Link 9</li>
<li>Link 10</li>
</ul>
JSFiddle Version: https://jsfiddle.net/n92ng9uz/2/
Upvotes: 2
Reputation: 100
EDIT: Nevermind... figured it out... You need to move each item left by the position difference. I think this is what you are after: http://jsfiddle.net/xwesf1Lt/. Tell me if I'm wrong. Note that I changed the diff variable to just the left position.
Also, instead of altering the margin, we alter the left attribute.
var firstLI = $('ul:first-child')[0];
firstLI.style.marginLeft = 0;
$('li').draggable({
axis: 'x',
drag: function(e, ui) {
var diff = ui.position.left;
console.log(diff);
var currentLeft = parseInt(firstLI.style.marginLeft, 10);
var offset = currentLeft + diff + 'px';
//firstLI.style.marginLeft = diff;
// to drag all of them:
$("li").each(function(index) {
$(this).css("left", offset);
});
// with this enabled, can only be moved 1px at a time..?
// e.preventDefault();
}
});
Upvotes: 1
Reputation: 1643
If you want the users to be able to freely drag the navbar and then it should drop at the same place then you can try out the jquery dad plugin. It is by far the best drag and drop plugin I've used do to the simplicity of the code.
Click here to see its demo and documentation if you wish.
Upvotes: -1
Reputation: 841
Wouldn't this work? Adding the margin to the ul
? Seems to work in the fiddle!
var ul = $('ul');
ul.draggable({
axis: 'x',
drag: function(e, ui) {
ul.css({marginLeft: ui.position - ui.originalPosition});
}
});
Upvotes: 0