I have an ul list and a multipe selectbox, i would like to know how can i use sortable to sort option's as li element (i have to start/stop position of sortable) using Jquery UI.
Example (my jsfiddle) :
<select id="myselect" multiple>
<option value="vA">A</option>
<option value="vB">B</option>
<option value="vC">C</option>
<option value="vD">D</option>
</select>
<ul class="myul">
<li>AnElementP1</li>
<li>AnElementP2</li>
<li>AnElementP3</li>
<li>AnElementP4</li>
</ul>
Javascript
$(document).ready(function () {
$(".myul").sortable({
start: function(event, ui) {
ui.item.startPosition = ui.item.index();
},
stop: function(event, ui) {
console.log("Start position: " + ui.item.startPosition);
console.log("New position: " + ui.item.index());
// How can i sort the select box option's
}
});
});
Get it !
Maybe this can help someone.
Link to Jsfiddle
$(document).ready(function () {
$(".myul").sortable({
start: function(event, ui) {
ui.item.startPosition = ui.item.index();
},
stop: function(event, ui) {
var El = $("#myselect option").eq(ui.item.startPosition);
var cpy = El.clone();
if (El.is(':selected'))
{
cpy.attr("selected","selected");
}
El.remove();
if (ui.item.index() === 0)
$("#myselect").prepend(cpy);
else
$("#myselect option").eq(ui.item.index() -1).after(cpy);
}
});
});
EDIT
.clone() doesn't clone selected value (See ticket), that's why i've add a condition.
if (El.is(':selected'))
{
cpy.attr("selected","selected");
}
It looks like you've solved it already yourself :)
Was trying out a variant without cloning myself, will post it here as an alternative:
$(document).ready(function () {
$(".myul").sortable({
start: function(event, ui) {
ui.item.startPos = ui.item.index();
},
stop: function(event, ui) {
var newPos = ui.item.index();
var startPos =ui.item.startPos;
if(newPos < startPos)newPos--;
var dropdown = $("#myselect")[0];
var tomove = $(dropdown.options[startPos]);
if(newPos===-1)
$(dropdown.options[0]).before(tomove);
else
$(dropdown.options[newPos]).after(tomove);
}
});
});
Related
I am trying to make the list items (cards) sortable, but for usability improvements I want to show the user an placeholder on the old (with text "FROM") and one on the new (with text "TO") before user releases mouse (ends .sortable).
helper: 'clone',
placeholder: {
element: function(currentItem) {
return $('<li class="placeholder">FROM or TO</li>')[0];
},
update: function(container, p) {
return;
},
}
right above, you see what I have for now, but is it possible to split "FROM" and "TO"?
I made it myself. Was quite complicated to introduce a second "placeholder" on old position. See here:
If you move an li, you now have an "FROM"-Container at old-pos and and "TO"-Container on future-pos, wich will be removed after positioning.
$(function() {
var oldList, newList, item;
$(".selector").sortable({
start: function(event, ui) {
item = ui.item;
newList = oldList = ui.item.parent().parent();
var activeElem = item.index();
$(this).children().eq(activeElem).after('<li class="placeholder">From</li>');
},
stop: function(event, ui) {
//alert("Moved " + item.text() + " from " + oldList.attr('id') + " to " + newList.attr('id'));
$(".selector > li").remove(".placeholder");
},
change: function(event, ui) {
if(ui.sender) newList = ui.placeholder.parent().parent();
},
connectWith: ".selector",
helper: 'clone',
placeholder: {
element: function(currentItem) {
return $('<li class="placeholder">To</li>')[0];
},
update: function(container, p) {
return;
}
}
}).disableSelection();
});
I'm trying to re-order the elements of a list in a jquery sortable when it is created based on which order they are in in a list.
var CACHES = ["WayBack Machine", "Google Cache", "Coral CDN"];
var HTML = ["Google Cache", "WayBack Machine", "Coral CDN"];
$("#sortable").sortable({
stop: function(event, ui) {
console.log("New position: " + ui.item.index());
},
change: function(event, ui) {
// When the item postion is changed while dragging a item, I want it's position
console.log("New position: " + ui.item.index());
},
create: function(event, ui) {
console.log("Sortable Created");
var ul = $('#sortable');
var li = ul.children('li').get();
li.sort(function(a,b) {
$(a).attr('id')
var value = CACHES.indexOf($(a).attr('id')) < CACHES.indexOf($(b).attr('id')) ? 1 : -1
console.log(value)
return value
});
ul.append(li);
}
});
var HTML is the order that they are in in the HTML of the page. var CACHES is the order that I want to put them in. It does seem to reorder the elements, but not correctly.
http://www.w3schools.com/jsref/jsref_sort.asp
use - instead of < and ternary
var value = CACHES.indexOf($(a).attr('id')) - CACHES.indexOf($(b).attr('id'));
$("li").draggable({
helper: "clone"
});
$("#div1").droppable({
drop: function (event, ui) {
$("<p></p>").appendTo("#div1");
}
});
I have objects in a list that can be dragged and dropped into a div named div1. But when I drop one into the div i don't want to be able to drop another into it. I have tried using, for, if and while loops with a count.
Here is a full solution, it allows only one item dropped, but also, if one exists, it gets replaced on the next drop with the new one. (Usefull if someone changes their mind. Just call
refreshDragDrop(dragClassName,dropDivId);
refreshDragDrop = function(dragClassName,dropDivId) {
$( "." + dragClassName ).draggable({
connectToSortable: "#" + dropDivId,
helper: "clone",
revert: "invalid"
});
$("#" + dropDivId).droppable({
accept: '.' + dragClassName,
drop: function (event, ui) {
var $this = $(this),
maxItemsCount = 1;
if ($this.children('div').length == maxItemsCount ){
//more than one item,just replace
$(this).html($(ui.draggable).clone());
} else {
$(this).append($(ui.draggable).clone());
}
}
});
}
This should help:
drop: function (event, ui) {
var $this = $(this),
maxItemsCount = 1;
if ($this.children('li').length > maxItemsCount ){
ui.sender.draggable('cancel');
alert("To much items!");
}
}
I've a peculiar situation. I have two lists. 1 list contains all items, and 2 contains top list. Obviously items overlap, and items in the second list are marked with class clone-23 clone-25 according to which element from list 1 are they cloned from.
Example:
List 1
1 run
2 eat
3 drink
4 play
List 2 (TOP)
1 run (class clone)
2 eat (class clone)
When re-arranged data is saved to DB.
I would like to avoid refresh and re-pulling of data from DB. So I would like to sync position of elements in two lists.
So whenever user drags around item in list 1, list 2 automatically shows changed positions and vice versa.
I initiate my sortable:
// Initiate jquery ui sortable
$(".word-list").sortable({
tolerance: 'pointer',
cursor: 'move',
forcePlaceholderSize: true,
dropOnEmpty: true,
connectWith: 'ol.word-list',
//containment: "body",
//
start: function(event, ui) {
// Starting position of the word element
//ui.item.startPos = ui.item.index();
//console.dir(ui.item.startPos);
},
//
stop: function(event, ui) {
//
},
update: function(event, ui) {
//
save_word_order(this);
//
},
out: function(event, ui) {
//
},
over: function(event, ui) {
//
},
placeholder: "ui-state-highlight"
});
Clone element html:
<li data-con-id="94" data-order-id="1" data-note="" class="ui-state-default clone-94"</li>
Lists are simply:
<ol id="tabs-1" class="word-list"></ol>
<ol id="tabs-2" class="word-list"></ol>
Any thoughts?
See this fiddle for code which syncs the order of items common to both lists:
http://jsfiddle.net/Fresh/22jc2/
Note that in my example I have simplified list two's li elements by not including the clone attributes; instead I am comparing items in both list by the list item's innerText value. It should be fairly easy for you to refactor my solution to use the clone item attributes if you really need to use them.
The script which I've used to achieve the synchronisation of the order of the common list items is:
var reorderLists = function (list1, list2) {
$('#' + list1 + ' li').each(function (index) {
var sortableItemWithText = $('#' + list2 + ' li:contains(' + this.textContent + ')');
if (sortableItemWithText.length === 1) {
sortableItemWithText.appendTo('#' + list2);
return;
}
});
};
$("#sortable1, #sortable2").sortable({
update: function (event, ui) {
var parentNodeId = ui.item[0].parentNode.id;
if (parentNodeId == "sortable1") {
reorderLists("sortable1", "sortable2");
}
if (parentNodeId == "sortable2") {
reorderLists("sortable2", "sortable1");
}
}
});
$("#tabs").tabs();
Note that the syncing of the order of common list items works if you change the position of items in either list 1 or list 2.
Also note that by commenting out:
$("#tabs").tabs();
You'll be able to see the lists updating automatically when you move the list items; this makes it easier to confirm that the re-order routine is work as expected.
perhaps this can help :
See this fiddle for code which syncs the order of items common to both
lists:
http://jsfiddle.net/penjepitkertasku/6bk7B/1/
$(function() {
var dragElementID = "";
var dropElementID = "";
var dragElementItemName = "";
var allElementItemName = "";
$(".word-list").sortable({
tolerance: 'pointer',
cursor: 'move',
helper: 'clone',
//revert: 'invalid',
forcePlaceholderSize: true,
dropOnEmpty: true,
connectWith: 'ol.word-list',
start: function(e, ui){
var id = $('ol.word-list').children().index($(ui.item[0]));
var name = $('ol.word-list').children(':eq(' + id + ')').text();
dragElementItemName = name;
dragElementID = this.id;
},
stop: function(event, ui) {
var id = $('ol.word-list').children().index($(ui.item[0]));
//validate
if(dragElementID == dropElementID) { return; }
if(id == -1)return;
if(dragElementID == "tabs-1")
{
if(allElementItemName.indexOf(dragElementItemName,1) > 0) { $(this).sortable('cancel'); return; }
var elm = $(ui.item[0]).clone(true).removeClass('box ui-draggable ui-draggable-dragging').addClass('box-clone');
$('ol.word-list').children(':eq(' + id + ')').after(elm);
$(this).sortable('cancel');
}else{
ui.item.remove();
}
},
update: function(event, ui) {
//
//save_word_order(this);
//
},
out: function(event, ui) {
//
},
over: function(event, ui) {
//
dropElementID = this.id;
allElementItemName = '|' + $('#' + dropElementID + ' li').text() + '|';
},
placeholder: "ui-state-highlight"
});
});
i'm using selectable jquery, i want to cater the value for selectable once the use select or unselect the item. My problem is, the last value of unselectable won't update.
Full code here http://jsfiddle.net/duQH6/ When I select Mon and Tue, then I unselect the Tue, the value is updated, but then when I click Mon, the value is not updated. Please advice.
Here my jquery code
$(function() {
$("#selectday1").bind('mousedown', function (e) {
e.metaKey = true;
}).selectable();
});
$('document').ready(function(){
$( "#selectday1" ).selectable({
selected: function(event, ui) {
var result=[];
jQuery(".ui-selected", this).each(function()
{
result.push(this.id);
$("#days").val(result.join(','))
});
}
});
$( "#selectday1" ).selectable({
unselected: function(event, ui) {
var result=[];
jQuery(".ui-selected", this).each(function()
{
result.push(this.id);
$("#days").val(result.join(','))
});
}
});
});
Thanks..
The problem is, you are updating the days value within the each loop, so when you unselect the last element the loop callback is never executed, that is why it is happening.
The days value is supposed to be updated once the each() loop is completed.
$(document).ready(function () {
$("#selectday1").selectable({
selected: function (event, ui) {
var result = [];
jQuery(".ui-selected", this).each(function () {
result.push(this.id);
});
$("#days").val(result.join(','))
},
unselected: function (event, ui) {
var result = [];
jQuery(".ui-selected", this).each(function () {
result.push(this.id);
});
$("#days").val(result.join(','))
}
});
});
Demo: Fiddle
But it can be simplified to
jQuery(function ($) {
function serialize(event, ui) {
var result = $(this).find(".ui-selected").map(function () {
return this.id;
}).get();
$("#days").val(result.join(','))
}
$("#selectday1").selectable({
selected: serialize,
unselected: serialize
});
});
Demo: Fiddle