I have a list created using SortableJS and has a few items which cannot be dragged and dropped. Here is an example of how it looks:
<ul id="user_selections">
<li class="no_drag">Fixed</li>
<li>Item 1</li>
<li class="no_drag">Fixed</li>
<li>Item 2</li>
<li class="no_drag">Fixed</li>
<li>Item 3</li>
<li class="no_drag">Fixed</li>
</ul>
Class no_drag are the items that are fixed.
Now when I move Items 3 above Item 1 the structure should be like this:
<ul id="user_selections">
<li class="no_drag">Fixed</li>
<li>Item 3</li>
<li class="no_drag">Fixed</li>
<li>Item 1</li>
<li class="no_drag">Fixed</li>
<li>Item 2</li>
<li class="no_drag">Fixed</li>
</ul>
Can anyone please help me how to achieve this kind of behaviour.
Here is the JS code I have tried:
var el = document.getElementById('user_selections');
if (el) {
const sortable = Sortable.create(el, {
filter: '.no_drag',
onMove(evt, oe) {
return evt.related.className.indexOf('no_drag') === -1;
},
preventOnFilter: false,
onEnd: function(/**Event*/evt) {
// Some ajax call to save the new indexes
}
});
}
I have found a solution that works perfectly for first and last elements.
Add this in options:
onMove: function(e) {
if(e.related.classList.contains('no_drag')) {
return false;
}
},
If drop target is something you don't want moved it will return false, i.e. it will be ignored as drop target.
Elements in the middle will also be ignored, but you can still target elements after (or before) them, so they will be moved.
Related
How do I iteratively add children elements to a (for example) a .
<ul id="my-list">
<li>item 1</li>
<li>item 2</li>
</ul>
If I have a JS script that runs something like this several times:
document.getElementById('my-list').appendChild('someListItemICreated')
the current 2 list items are removed. How do I add new li items to the ul without losing the current list itmes?
You need to provide an element as the argument for appendChild and not a string. Like this:
const li = document.createElement("li");
li.innerText = "Item 3";
document.getElementById("my-list").appendChild(li);
<ul id="my-list">
<li>Item 1</li>
<li>Item 2</li>
</ul>
A much easier and a cleaner approach that I prefer in most of cases is:
document.getElementById("my-list").innerHTML += "<li>Item 3</li>";
<ul id="my-list">
<li>Item 1</li>
<li>Item 2</li>
</ul>
const c = document.createElement('li');
c.innerText = 'item 3';
document.getElementById('my-list').appendChild(c);
<ul id="my-list">
<li>item 1</li>
<li>item 2</li>
</ul>
I think you need to be more specific with what your code is actually doing, but I can say that someListItemICreated should not be a string, if that's what you're passing. Here's an example I made that's similar to what you're referring to that runs fine.
<ul id="my-list">
<li>Item 1</li>
<li>Item 2</li>
</ul>
let someListItemICreated = document.createElement("li");
someListItemICreated.appendChild(document.createTextNode("item 3"));
document.getElementById("my-list").appendChild(someListItemICreated)
is it possible, to add auto incremental classes to a list
<ul id="list">
<li>Element 1</li>
<li>Element 2</li>
<li>Element 3</li>
<li>Element 4</li>
<li>Element 5</li>
</ul>
Now, If I hover on Element 3 then, add auto incremental classes to li like example below...
<ul id="list">
<li class="left2">Element 1</li>
<li class="left1">Element 2</li>
<li>Element 3</li>
<li class="right1">Element 4</li>
<li class="right2">Element 5</li>
</ul>
Again if hover on Element 1 then, add auto incremental classes to li like example below...
<ul id="list">
<li>Element 1</li>
<li class="right1">Element 2</li>
<li class="right2">Element 3</li>
<li class="right3">Element 4</li>
<li class="right4">Element 5</li>
</ul>
sorry about my poor English. Thank you.
$('li').hover(function() {
$('li').removeClass();
var next = $(this).nextAll();
next.each(function(i, v) {
$(this).addClass('right' + (i+1))
})
var prev = $(this).prevAll();
prev.each(function(i, v) {
$(this).addClass('left' + (i+1))
})
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul id="list">
<li>Element 1</li>
<li>Element 2</li>
<li>Element 3</li>
<li>Element 4</li>
<li>Element 5</li>
</ul>
Use .prevAll() and .nextAll()
Description: Get all preceding siblings of each element in the set of matched elements, optionally filtered by a selector.
Description: Get all following siblings of each element in the set of matched elements, optionally filtered by a selector.
then iterate on the li and assign the index. make sure to remove the li classes so it wont stack up
Based on example, I cleared all the class in <li> when mouseenter anyone of the <li> and add new class for them.
left1+n will add to previous all <li> and right1+n will add to next all <li>
$("#list > li").on("mouseenter", function(){
$("#list > li").attr("class", "");
$(this).prevAll("li").each(function(i) {
$(this).addClass('left' + (i+1));
});
$(this).nextAll("li").each(function(i) {
$(this).addClass('right' + (i+1));
});
});
I have a list, some items with a class "sort":
<ul id="items">
<li class="sort">ITEM 1 Fix Position</li>
<li class="sort">ITEM 2 Fix Position</li>
<li class="sort">ITEM 3 Fix Position</li>
<li class="sort">ITEM 4 Fix Position</li>
<li>ITEM 5</li>
<li>ITEM 6</li>
<li>ITEM 7</li>
<li>ITEM 8</li>
</ul>
I have then initialised the list as sortable for all items with the class "sort".
$("#items").sortable({
items: "li.sort"
});
This works fine, however, I want to be able to fix the position of the sortable items so that they can no longer be dragged. I've started by adding a button to remove the class "sort" from the list item. This is the code for the button:
$("#items").on("click", ".fix-position", function(e){
e.preventDefault();
$(this).parent().removeClass("sort");
$(this).remove();
});
This does prevent the other items from using it as a drop target, but the item can still be dragged itself. See JS FIDDLE: http://jsfiddle.net/3Js5u/1/
I have also tried to refresh the list:
$("#items").sortable("refresh");
but that does not seem to work.
Only other option I can think of is to destroy the sortable list and recreate it like this:
$("#items").sortable( "destroy" );
$("#items").sortable({
items: "li.sort"
});
JS FIDDLE for that option: http://jsfiddle.net/3Js5u/3/. Not sure if that's the best way to go though. Any help appreciated. Thanks.
Do the opposite and use cancel option instead.
HTML:
<ul id="items">
<li>ITEM 1 Fix Position</li>
<li>ITEM 2 Fix Position</li>
<li>ITEM 3 Fix Position</li>
<li>ITEM 4 Fix Position</li>
<li class="static">ITEM 5</li>
<li class="static">ITEM 6</li>
<li class="static">ITEM 7</li>
<li class="static">ITEM 8</li>
</ul>
JavaScript:
$("#items").sortable({
cancel: ".static"
});
$("#items").on("click", ".fix-position", function(e) {
$(this).parent().addClass("static").end().remove();
e.preventDefault();
});
DEMO: http://jsfiddle.net/3Js5u/2/
The menu is supposed to show sub-items upon hover. Here's the code (from http://docs.jquery.com/Cookbook/Navigation):
<ul id="menu">
<li class="menu">Sub 1
<ul>
<li>test 1</li>
<li>test 2</li>
<li>test 3</li>
<li>test 4</li>
</ul>
</li>
<li class="menu">Sub 2
<ul>
<li>test 1</li>
<li>test 2</li>
<li>test 3</li>
<li>test 4</li>
</ul>
</li>
</ul>
jQuery code:
$(document).ready(function() {
var toggle = function(direction, display) {
return function() {
var self = this;
var ul = $("ul", this);
if( ul.css("display") == display && !self["block" + direction] ) {
self["block" + direction] = true;
ul["slide" + direction]("slow", function() {
self["block" + direction] = false;
});
}
};
}
$("li.menu").hover(toggle("Down", "none"), toggle("Up", "block"));
$("li.menu ul").hide();
});
What is this in the toggle function above? How is the code working? What is being selected by $("ul", this); ?
The "this" refers to the jQuery object $("li.menu") - when the hover method call applies the toggle function to that object. $("ul", this) selects ul elements that are children of the context provided in the second argument ("this"), thus it selects the ul elements nested within the li.menu elements. Hopefully that makes the hover/toggle functions make sense.
I'm trying to implement drag/drop/sort between 2 list elements:
<ul id="first">
<li>item 1</li>
<li>item 2</li>
<li>item 3</li>
</ul>
<ul id="second">
<li>item 4</li>
<li>item 5</li>
<li>item 6</li>
</ul>
Basically I just want to be able to pass items between the lists and sort the items in each list. What's the simplest way to implement this using jQuery?
jQueryUI Sortable - this is exactly what you want.
Very simple:
<script>
$(function() {
$('#first').sortable( { connectWith : '#second' });
$('#second').sortable( { connectWith : '#first' });
});
</script>
I've noticed that an earlier version of jQuery-UI (1.6rc5) I tried this with didn't accept the css selector for connectWith. I threw a curve and got it to work with actual jQuery elements instead:
<script>
$(function() {
$('#first').sortable( { connectWith : $('#second') });
$('#second').sortable( { connectWith : $('#first') });
});
</script>