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.
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/
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();
}
});
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With