I have a list of tasks, i want to be able to drag them around and get the sortOrder array to change to the new order, this is what I've come up with but it's not working right, sometimes i get the order, sometimes i don't.. for example if i drag the first element to second position it works, but if i drag to last position it's not... also if i drag up it usually wrong.. What am i doing wrong? or can this be done some other way? I need to keep track of previous/next id's because there can be other elements in the sortOrder that are not visible, so i need to add the dragged element before or after a visible element.
Thanks
const sortOrder = ["7","x", "5","y", "55", "1"],
tasks = document.getElementById("tasks");
Sortable.create(tasks, {
scroll: true,
scrollSensitivity: 30, // px, how near the mouse must be to an edge to start scrolling.
scrollSpeed: 10, // px, speed of the scrolling
bubbleScroll: true, // apply autoscroll to all parent elements, allowing for easier movement
revertOnSpill: true,
group: 'shared',
animation: 0,
dataIdAttr: 'id',
ghostClass: 'task-ghost',
dragClass: 'task-drag',
onEnd: (evt) => {
// let newIndex;
console.log('previousElementSibling', evt.item.previousElementSibling);
console.log('nextElementSiblingElementSibling', evt.item.nextElementSiblingElementSibling);
console.log('oldIndex', evt.oldIndex);
console.log('newIndex', evt.newIndex);
let neighborIndex;
// drag up or down
if (evt.oldIndex < evt.newIndex) neighborIndex = sortOrder.indexOf(evt.item.previousElementSibling?.id || sortOrder[0]);
else neighborIndex = sortOrder.indexOf(evt.item.nextElementSibling?.id);
console.log("neighborIndex",neighborIndex);
// remove element from array
sortOrder.splice(sortOrder.indexOf(evt.item.id), 1);
// add element to specific position
sortOrder.splice(neighborIndex, 0, evt.item.id);
console.log(sortOrder);
}
})
.tasks {
list-style-type: none;
}
li {
border: solid 1px red;
margin: 4px;
width: 200px;
}
.task-ghost{ opacity: 0; }
.task-drag{ opacity: 1;}
<script src="https://cdnjs.cloudflare.com/ajax/libs/Sortable/1.14.0/Sortable.min.js"></script>
<ul class="tasks" id="tasks">
<li id="7" class="task">element 7</li>
<li id="5" class="task">element 5</li>
<li id="55" class="task">element 55</li>
<li id="1" class="task">element 1</li>
</ul>
I've managed to get good results, if someone has a better way please tell me.
const sortOrder = ["7", "x", "5", "y", "55", "1"],
tasks = document.getElementById("tasks");
Sortable.create(tasks, {
scroll: true,
scrollSensitivity: 30, // px, how near the mouse must be to an edge to start scrolling.
scrollSpeed: 10, // px, speed of the scrolling
bubbleScroll: true, // apply autoscroll to all parent elements, allowing for easier movement
revertOnSpill: true,
group: 'shared',
animation: 0,
dataIdAttr: 'id',
ghostClass: 'task-ghost',
dragClass: 'task-drag',
onEnd: (evt) => {
// let newIndex;
console.log('previousElementSibling', evt.item.previousElementSibling);
console.log('nextElementSiblingElementSibling', evt.item.nextElementSiblingElementSibling);
console.log('oldIndex', evt.oldIndex);
console.log('newIndex', evt.newIndex);
let neighborIndex;
sortOrder.splice(sortOrder.indexOf(evt.item.id), 1); // stergem pe ala pe care l-am tras de sus
if (evt.oldIndex < evt.newIndex) neighborIndex = sortOrder.indexOf(evt.item.previousElementSibling.id) + 1;
else neighborIndex = sortOrder.indexOf(evt.item.nextElementSibling.id);
sortOrder.splice(neighborIndex, 0, evt.item.id); // il adaugam dupa vecin
console.log(sortOrder);
}
})
.tasks {
list-style-type: none;
}
li {
border: solid 1px red;
margin: 4px;
width: 200px;
}
.task-ghost {
opacity: 0;
}
.task-drag {
opacity: 1;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/Sortable/1.14.0/Sortable.min.js"></script>
<ul class="tasks" id="tasks">
<li id="7" class="task">element 7</li>
<li id="5" class="task">element 5</li>
<li id="55" class="task">element 55</li>
<li id="1" class="task">element 1</li>
</ul>
Related
I would like to know how I can click on an image like this
If I click on the BMW or Toyota logo then it shades the icon I have selected with CSS then keep that 'value' and save it in javascript variable so I can use later.
Let's say I have this
<ul class="car_types">
<li class="bmw"><img src="test/bmw.png"></li>
<li class="audi"><img src="test/audi.png"></li>
<li class="toyota"><img src="test/toyota.jpg"></li>
<li class="benz"><img src="test/benz.jpg">Discover</li>
</ul>
or i have
<table>
<tr>
<div class="car_types">
<img id="bmw" src="test/bmw.png">
<img id="audi" src="test/audi.png">
<img id="toyota" src="test/toyota.jpg">
<img id="benz" src="test/benz.jpg">
</div>
</tr>
</table>
or any other way of doing it.
Many thanks.
You need to add an event listener to each of your images, so that you can select which image should be highlighted.
Then, create a special css class which gives a special style to the selected image.
I've created a simple demo below:
Here, we have a listener that listens on the "click" event on the <li> elements inside of your .car_types list. When we do click on an image, we remove any elements that might have the shaded class (from a previous click), and then add the shaded class to the one we just clicked on.
The shaded class just gives a 50% brightness, instead of 100%.
$(".car_types li").on("click", function(){
$(".car_types li").each(function() {
$(this).removeClass("shaded");
});
$(this).addClass("shaded");
});
.car_types li {
display: inline-block;
}
.shaded {
filter: brightness(50%);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul class="car_types">
<li class="bmw"><img src="http://via.placeholder.com/135x135"></li>
<li class="audi shaded"><img src="http://via.placeholder.com/135x135"></li>
<li class="toyota"><img src="http://via.placeholder.com/135x135"></li>
<li class="benz"><img src="http://via.placeholder.com/135x135"></li>
</ul>
If you want to be able to shade several logos at once, try this instead:
$(".car_types li").on("click", function(){
if($(this).hasClass("shaded")) {
$(this).removeClass("shaded");
} else {
$(this).addClass("shaded");
}
});
.car_types li {
display: inline-block;
}
.shaded {
filter: brightness(50%);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul class="car_types">
<li class="bmw"><img src="http://via.placeholder.com/135x135"></li>
<li class="audi shaded"><img src="http://via.placeholder.com/135x135"></li>
<li class="toyota"><img src="http://via.placeholder.com/135x135"></li>
<li class="benz"><img src="http://via.placeholder.com/135x135"></li>
</ul>
Here it is with pure JS
HTMLCollection.prototype.each = function(cb) { for(var i = 0; i < this.length; i++) {
cb(this[i], i);
}
}
var imgs = document.getElementsByTagName('img');
imgs.each(function(img) {
img.addEventListener('click', function(ev) {
imgs.each(function(img) {
img.classList.remove('selected');
});
ev.target.classList.add('selected');
});
});
img {
opacity: .8;
}
.selected {
opacity: 1;
}
<ul class="car_types">
<li class="bmw"><img src="test/bmw.png"></li>
<li class="audi"><img src="test/audi.png"></li>
<li class="toyota"><img src="test/toyota.jpg"></li>
<li class="benz"><img src="test/benz.jpg">Discover</li>
</ul>
Considering you have added event listener like this,
Have a global variable in your js file and modify it on click event..
var selectedVal; //global variable for value
$(".car_types li").on("click", function(){
$(".car_types li").each(function() {
$(this).removeClass("shaded");
});
$(this).addClass("shaded");
selectedVal=$(this).data("val"); //modifying global variable
});
//access selectedVal anywhere
HTML:
<ul class="car_types">
<li class="bmw" data-val="bmw"><img src="test/bmw.png"></li>
<li class="audi" data-val="audi"><img src="test/audi.png"></li>
<li class="toyota" data-val="toyota"><img src="test/toyota.jpg"></li>
<li class="benz" data-val="benz"><img src="test/benz.jpg">Discover</li>
</ul>
CSS:
.shaded{
box-shadow:0px 0px 20px black;
}
Usually, you add a click listener to the image. This click listener then adds a selected class to the image. The image has styles which it applies when there is a .selected class on the image. These styles should then shade the image. The click listener also sets the JavaScript variable which you can then use.
Here is an example with plain JavaScript (no jQuery):
var selectedCar = 'no car selected';
var allCarTypes = document.querySelectorAll('.car_type');
allCarTypes.forEach(function (item) {
item.addEventListener('click', function (event) {
var selectedElement = event.target;
removeSelectedClassForAllElements();
selectedElement.classList.add('selected');
selectedCar = selectedElement.id;
});
});
function removeSelectedClassForAllElements () {
allCarTypes.forEach(function (item) {
item.classList.remove('selected');
});
}
.car_type {
width: 130px;
height: 130px;
position: relative;
cursor: pointer;
}
.car_type:after {
content: "";
position: absolute;
top: 0;
left: 0;
display: block;
height: 100%;
width: 100%;
background: rgba(0, 0, 0, 0.5);
transition: 0.3s ease all;
opacity: 0;
visibility: hidden;
}
.car_type.selected:after {
opacity: 1;
visibility: visible
}
<div class="car_types">
<img id="bmw" class="car_type" src="test/bmw.png">
<img id="audi" class="car_type" src="test/audi.png">
<img id="toyota" class="car_type" src="test/toyota.jpg">
<img id="benz" class="car_type" src="test/benz.jpg">
</div>
<!-- do not use 'onclick' -->
<button onclick="alert(selectedCar);">Which car is selected?</button>
I'm implementing infinity scrolling with jquery and here all list item is rendering data from database. everything is working well but my scroller not scrolling with animation its looks like its just jumping how could i make it animate not jumping!... please
[Jquery]
var item_width = $('.scroller li').outerWidth();
var left_value = item_width * (-1);
$('.scroller li:first').before($('.scroller li:last'));
$('.scroller').css({'left' : left_value});
$('#prev').click(function() {
var left_indent = parseInt($('.scroller').css('left')) - item_width;
$('.scroller').animate({'left' : '-='+left_indent}, 400, function(){
$('.scroller li:first').before($('.scroller li:last'));
$('.scroller').css({'left' : left_value});
});
return false;
});
$('#next').click(function() {
var left_indent = parseInt($('.scroller').css('left')) - item_width;
$('.scroller').animate({'left' : '+='+left_indent}, 400, function () {
$('.scroller li:last').after($('.scroller li:first'));
$('.scroller').css({'left' : left_value});
});
return false;
});
[Style]
*{margin: 0;padding: 0;list-style: none;}
.scroller{height:70px;overflow:hidden;}
.scroller li{float:left;display:inline-block;position:relative;border-bottom:1px solid #e8eef4;border-top:1px solid #e8eef4;border-right:1px solid #ddd;height:70px;width:25%;cursor:pointer;
background-image: -moz-radial-gradient(top, #fff, #ddd);}
.scroller li:nth-child(4),.scroller li:nth-of-type(4){border-right:0}
.scroller li a{display:block;margin-top:8%;height:90%;font-size:x-small;text-align:center;}
.scroller .active,.scroller li:hover{background-image:-moz-radial-gradient(top, #ddd, #fff)}
.scroller .active:before{content:'';height:0;position:absolute;top:-1px;width:0;left:42%;border: 10px solid transparent;border-top-color:#fff;z-index:100}
.scroller li a img{border:1px solid #ccc;width:80%;height:40%}
[Html]
<div>
<ul class="scroller">
<li class="item">01</li>
<li class="item">02</li>
<li class="item">03</li>
<li class="item">04</li>
<li class="item">05</li>
<li class="item">06</li>
<li class="item">07</li>
<li class="item">08</li>
<li class="item">09</li>
<li class="item">10</li>
</ul>
<p class="tar">‹›</p>
</div>
You can use lucid.js, they did a great job and i think it can save your time.
They have a nice API which let you choose what elements you want to scroll or even the whole page.
Please let me know if it helps you.
here is the link for documentations and demos : http://ataredo.com/morphology/lucidscroll/
I am new to YUI. I am wanting to achieve a drag and drop operation with contstraints. I am following the simple YUI 3 guide and was able to achieve the drag and drop according to the code they given which is.
http://yuilibrary.com/yui/docs/dd/scroll-list.html
HTML
<body>
<div id="demo">
<ul id="list1">
<li class="list1">Item #1</li>
<li class="list1">Item #2</li>
<li class="list1">Item #3</li>
<li class="list1">Item #4</li>
<li class="list1">Item #5</li>
<li class="list1">Item #6</li>
<li class="list1">Item #7</li>
<li class="list1">Item #8</li>
<li class="list1">Item #9</li>
<li class="list1">Item #10</li>
<li class="list1">Item #11</li>
<li class="list1">Item #12</li>
</ul>
<ul id="list2">
<li class="list2">Item #1</li>
<li class="list2">Item #2</li>
<li class="list2">Item #3</li>
<li class="list2">Item #4</li>
<li class="list2">Item #5</li>
<li class="list2">Item #6</li>
<li class="list2">Item #7</li>
<li class="list2">Item #8</li>
<li class="list2">Item #9</li>
<li class="list2">Item #10</li>
<li class="list2">Item #11</li>
<li class="list2">Item #12</li>
</ul>
</div>
CSS
yui3-dd-proxy {
text-align: left;
}
#demo {
width: 600px;
}
#demo {
border: 1px solid black;
padding: 10px;
margin: 10px;
zoom: 1;
}
#demo ul li {
border: 1px solid black;
background-color: #8DD5E7;
cursor: move;
margin: 3px;
list-style-type: none;
}
#demo:after { display: block; clear: both; visibility: hidden; content: '.'; height: 0;}
#demo ul {
border: 1px solid black;
margin: 10px;
width: 200px;
height: 400px;
float: left;
padding: 0;
zoom: 1;
position: relative;
overflow: auto;
}
#demo ul li.list1 {
background-color: #8DD5E7;
border:1px solid #004C6D;
}
#demo ul li.list2 {
background-color: #EDFF9F;
border:1px solid #CDCDCD;
}
Javascript
YUI().use('dd-constrain', 'dd-proxy', 'dd-drop', 'dd-scroll', function(Y) {
//Listen for all drop:over events
//Y.DD.DDM._debugShim = true;
Y.DD.DDM.on('drop:over', function(e) {
//Get a reference to our drag and drop nodes
var drag = e.drag.get('node'),
drop = e.drop.get('node');
//Are we dropping on a li node?
if (drop.get('tagName').toLowerCase() === 'li') {
//Are we not going up?
if (!goingUp) {
drop = drop.get('nextSibling');
}
//Add the node to this list
e.drop.get('node').get('parentNode').insertBefore(drag, drop);
//Set the new parentScroll on the nodescroll plugin
e.drag.nodescroll.set('parentScroll', e.drop.get('node').get('parentNode'));
//Resize this nodes shim, so we can drop on it later.
e.drop.sizeShim();
}
});
//Listen for all drag:drag events
Y.DD.DDM.on('drag:drag', function(e) {
//Get the last y point
var y = e.target.lastXY[1];
//is it greater than the lastY var?
if (y < lastY) {
//We are going up
goingUp = true;
} else {
//We are going down.
goingUp = false;
}
//Cache for next check
lastY = y;
Y.DD.DDM.syncActiveShims(true);
});
//Listen for all drag:start events
Y.DD.DDM.on('drag:start', function(e) {
//Get our drag object
var drag = e.target;
//Set some styles here
drag.get('node').setStyle('opacity', '.25');
drag.get('dragNode').set('innerHTML', drag.get('node').get('innerHTML'));
drag.get('dragNode').setStyles({
opacity: '.5',
borderColor: drag.get('node').getStyle('borderColor'),
backgroundColor: drag.get('node').getStyle('backgroundColor')
});
});
//Listen for a drag:end events
Y.DD.DDM.on('drag:end', function(e) {
var drag = e.target;
//Put our styles back
drag.get('node').setStyles({
visibility: '',
opacity: '1'
});
});
//Listen for all drag:drophit events
Y.DD.DDM.on('drag:drophit', function(e) {
var drop = e.drop.get('node'),
drag = e.drag.get('node');
//if we are not on an li, we must have been dropped on a ul
if (drop.get('tagName').toLowerCase() !== 'li') {
if (!drop.contains(drag)) {
drop.appendChild(drag);
//Set the new parentScroll on the nodescroll plugin
e.drag.nodescroll.set('parentScroll', e.drop.get('node'));
}
}
});
//Static Vars
var goingUp = false, lastY = 0;
//Get the list of li's in the lists and make them draggable
var lis = Y.all('#demo ul li');
lis.each(function(v, k) {
var dd = new Y.DD.Drag({
node: v,
target: {
padding: '0 0 0 20'
}
}).plug(Y.Plugin.DDProxy, {
moveOnEnd: false
}).plug(Y.Plugin.DDConstrained, {
constrain2node: '#demo'
}).plug(Y.Plugin.DDNodeScroll, {
node: v.get('parentNode')
});
});
Y.one('#make').on('click', function(e) {
YUI().use('dd-drag', 'dd-proxy', function(Y) {
//Selector of the node to make draggable
var dd = new Y.DD.Drag({
container: '#demo',
node: 'li'
}).plug(Y.Plugin.DDProxy); //This config option makes the node a Proxy Drag
var demo =Y.one('#demo ul');
for (var i = 1; i < 11; i++) {
//demo.append('<li class="list3">New item #' + i + '</i><br>');
demo.append('<li class="list3">Item #' + i + '</li>' )
}
})
});
//Create simple targets for the 2 lists.
var uls = Y.all('#demo ul');
uls.each(function(v, k) {
var tar = new Y.DD.Drop({
node: v
});
});
});
YUI().use('dd-delegate', 'dd-drop-plugin', 'dd-constrain', 'dd-proxy', function(Y) {
var del = new Y.DD.Delegate({
container: '#demo',
nodes: 'li'
});
del.on('drag:start', function(e) {
e.target.get('node').setStyle('opacity', '.5');
});
del.on('drag:end', function(e) {
e.target.get('node').setStyle('opacity', '1');
});
del.dd.plug(Y.Plugin.DDConstrained, {
constrain2node: '#play'
});
del.dd.plug(Y.Plugin.DDProxy, {
moveOnEnd: false,
cloneNode: true
});
var drop = Y.one('#drop').plug(Y.Plugin.Drop);
drop.drop.on('drop:hit', function(e) {
drop.set('innerHTML', 'You dropped: <strong>' + e.drag.get('node').get('innerHTML') + '</strong>');
});
});
I would like to Contrain the left drag meaning when i drag the blue over to the yellow. I would like to repopulate the blue item once it is dropped in the yellow area. The YUI guide has something similar to what I want to achieve here:
http://yuilibrary.com/yui/docs/dd/delegate-plugins.html
I am not quite clear on how to implement these two operations together to achieve the effect I need.
Any help would be good.
thanks
Javascript
YUI().use('dd-delegate', 'dd-drop-plugin', 'dd-constrain', 'dd-proxy', function(Y) {
var del = new Y.DD.Delegate({
container: '#demo',
nodes: 'li'
});
del.on('drag:start', function(e) {
e.target.get('node').setStyle('opacity', '.5');
});
del.on('drag:end', function(e) {
e.target.get('node').setStyle('opacity', '1');
});
del.dd.plug(Y.Plugin.DDConstrained, {
constrain2node: '#play'
});
del.dd.plug(Y.Plugin.DDProxy, {
moveOnEnd: false,
cloneNode: true
});
var drop = Y.one('#drop').plug(Y.Plugin.Drop);
drop.drop.on('drop:hit', function(e) {
drop.set('innerHTML', 'You dropped: <strong>' + e.drag.get('node').get('innerHTML') + '</strong>');
});
});
Hello I want to make this two items sortable without using plugins and stuff, only HTML5 and pure javascript:
<ul ondragenter="return dragEnter(event)" ondrop="return dragDrop(event)"
ondragover="return dragOver(event)">
<li draggable="true" ondragstart="return dragStart(event)">Item 1</li>
<li draggable="true" ondragstart="return dragStart(event)">Item 2</li>
</ul>
well i've tried:
function dragStart(ev) {
ev.dataTransfer.effectAllowed = 'move';
ev.dataTransfer.setData("Text", ev.target.getAttribute('class'));
return true;
}
function dragEnter(ev) {
event.preventDefault();
return true;
}
function dragOver(ev) {
return false;
}
function dragDrop(ev) {
var src = ev.dataTransfer.getData("Text");
ev.target.appendChild(document.getElementById(src));
ev.stopPropagation();
return false;
}
Would you like to order alphabetically? Here is a solution without any library.
var items = document.getElementsByTagName("li");
var values = [];
for(var i = 0; i < items.length; i++) {
values.push(items[i].innerHTML);
}
values.sort();
for(var i = 0; i < items.length; i++) {
items[i].innerHTML = values[i];
}
http://jsfiddle.net/GG9gG/
jsfiddle:
http://jsfiddle.net/pMcmL/6/
HTML:
<ul id="sortable">
<li class="ui-state-default">
<span>⇅</span><input type="text"/>Item 1
</li>
<li class="ui-state-default">
<span>⇅</span><input type="text"/>Item 2
</li>
<li class="ui-state-default">
<span>⇅</span><input type="text"/>Item 3
</li>
<li class="ui-state-default">
<span>⇅</span><input type="text"/>Item 4
</li>
<li class="ui-state-default">
<span>⇅</span><input type="text"/>Item 5
</li>
<li class="ui-state-default">
<span>⇅</span><input type="text"/>Item 6
</li>
<li class="ui-state-default">
<span>⇅</span><input type="text"/>Item 7
</li>
</ul>
CSS:
http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.11/themes/base/jquery-ui.css
+
li {
margin: 1px;
width: 130px;
padding:2px;
vertical-align:middle;
}
li span {
color: gray;
font-size: 1.1em;
margin-right: 5px;
margin-left: 5px;
cursor: pointer;
height:100%;
}
input[type="text"] {
width: 32px;
margin-right: 5px;
border: 1px solid lightgay;
color: blue;
text-align: center;
}
Javascript:
sort_ul = $('#sortable'); // * sortable <ul>
itemsCount = $('#sortable li').length; // * total number of items
function updateIndexes() { // * function to update
$('#sortable li input').each( // items numbering
function(i) {
$(this).val(i + 1);
});
}
updateIndexes(); // * start by update items numbering
sort_ul.sortable({handle: 'span', // * apply 'sortable' to <ul>
stop: function(event, ui){
updateIndexes(); // * when sorting is completed,
} // update items numbering
});
$('#sortable li input').keyup( // * watch for keyup on inputs
function(event) {
if (event.keyCode == '13') { // * react only to ENTER press
event.preventDefault(); // * stop the event here
position = parseInt($(this).val());// * get user 'new position'
li = $(this).parent(); // * store current <li> to move
if (position >= 1 // * proceed only if
&& position <= itemsCount){ // 1<=position<=number of items
li.effect('drop', function(){ // * hide <li> with 'drop' effect
li.detach(); // * detach <li> from DOM
if (position == itemsCount)
sort_ul.append(li); // * if pos=last: append
else // else: insert before position-1
li.insertBefore($('#sortable li:eq('+(position - 1)+')'));
updateIndexes(); // * update items numbering
li.effect('slide'); // * apply 'slide' effect when in
}); // new position
}else{ li.effect('highlight'); } // * if invalid position: highlight
}}});
Reference Link
I've searched and searched about how to do this, but to no avail.
Basically I have a pretty standard jQuery sortable list, using a gripper to allow users to rearrange the list
What I would like to add is an input box to each list item, autofilled with that item's #, that allows users to enter any number (so long as it is <== the total # of items in the list)< and then hit "Enter" or press a button to re-order the list.
Please see the YouTube Playlist tool or Netflix Queue as an example of what I am referring to:
http://img195.imageshack.us/img195/7715/youtubeplaylistrearrangc.png
http://www.thedigeratilife.com/images/netflix-queue-big.jpg
I cannot figure this out - Any assistance would be greatly appreciated!
Dave
jsfiddle:
http://jsfiddle.net/pMcmL/6/
HTML:
<ul id="sortable">
<li class="ui-state-default">
<span>⇅</span><input type="text"/>Item 1
</li>
<li class="ui-state-default">
<span>⇅</span><input type="text"/>Item 2
</li>
<li class="ui-state-default">
<span>⇅</span><input type="text"/>Item 3
</li>
<li class="ui-state-default">
<span>⇅</span><input type="text"/>Item 4
</li>
<li class="ui-state-default">
<span>⇅</span><input type="text"/>Item 5
</li>
<li class="ui-state-default">
<span>⇅</span><input type="text"/>Item 6
</li>
<li class="ui-state-default">
<span>⇅</span><input type="text"/>Item 7
</li>
</ul>
CSS:
http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.11/themes/base/jquery-ui.css
+
li {
margin: 1px;
width: 130px;
padding:2px;
vertical-align:middle;
}
li span {
color: gray;
font-size: 1.1em;
margin-right: 5px;
margin-left: 5px;
cursor: pointer;
height:100%;
}
input[type="text"] {
width: 32px;
margin-right: 5px;
border: 1px solid lightgay;
color: blue;
text-align: center;
}
Javascript:
sort_ul = $('#sortable'); // * sortable <ul>
itemsCount = $('#sortable li').length; // * total number of items
function updateIndexes() { // * function to update
$('#sortable li input').each( // items numbering
function(i) {
$(this).val(i + 1);
});
}
updateIndexes(); // * start by update items numbering
sort_ul.sortable({handle: 'span', // * apply 'sortable' to <ul>
stop: function(event, ui){
updateIndexes(); // * when sorting is completed,
} // update items numbering
});
$('#sortable li input').keyup( // * watch for keyup on inputs
function(event) {
if (event.keyCode == '13') { // * react only to ENTER press
event.preventDefault(); // * stop the event here
position = parseInt($(this).val());// * get user 'new position'
li = $(this).parent(); // * store current <li> to move
if (position >= 1 // * proceed only if
&& position <= itemsCount){ // 1<=position<=number of items
li.effect('drop', function(){ // * hide <li> with 'drop' effect
li.detach(); // * detach <li> from DOM
if (position == itemsCount)
sort_ul.append(li); // * if pos=last: append
else // else: insert before position-1
li.insertBefore($('#sortable li:eq('+(position - 1)+')'));
updateIndexes(); // * update items numbering
li.effect('slide'); // * apply 'slide' effect when in
}); // new position
}else{ li.effect('highlight'); } // * if invalid position: highlight
}}});
here is something that moves the li items around by changing the numbers:
function setOrder() {
$.each($('ul li input'), function(index, el) {
el.value = (index + 1);
});
}
setOrder();
$('ul li input').live('change', function() {
var change = (parseInt(this.value) - 1);
if(change > ($('ul li input').length - 1)){
change = $('ul li input').length - 1;
}
var index = $(this).index('ul li input');
var move = $('ul li')[change];
var arr = [];
$.each($('ul li'), function(ind, el) {
arr[ind] = $(this).clone();
})
arr[index] = move;
$('input', move).val(index + 1);
arr[change] = $(this).parent()[0];
arr.sort();
$('ul li').remove();
var indexAt = 0;
$.each(arr, function(index, el) {
$('ul').append(el);
});
setOrder();
})
$('ul').sortable({
stop: function(a, b) {
var arr = [];
var i = 0;
$.each($('ul li'), function(ind, el) {
arr[i] = $(this).clone();
i++;
})
$('ul li').remove();
$.each(arr, function(index, el) {
$('ul').append(el);
});
setOrder()
}
});
html:
<ul>
<li><input/>lijrfxgjh</li>
<li><input/>ghhgfhj</li>
<li><input/>lijrjh</li>
<li><input/>gfreydjgj</li>
<li><input/>rey</li>
<li><input/>gfjgf</li>
</ul>
fiddle: http://jsfiddle.net/maniator/bDvK8/
it is a bit glitchy, but it is a start