I'm having difficulty disabling sorting on a specific li in my ul.
I'm using SortableJS.
<ul id="items">
<li class="static">
<div class="image"><img src="image.jpg" /></div>
<div class="text">Static</div>
<div class="clearboth"></div>
</li>
<li>
<div class="image"><img src="image.jpg" /></div>
<div class="text">Dynamic</div>
<div class="clearboth"></div>
</li>
<li>
<div class="image"><img src="image.jpg" /></div>
<div class="text">Dynamic</div>
<div class="clearboth"></div>
</li>
</ul>
One li with class static should NOT be sortable. The others should be sortable.
var el = document.getElementById('items');
var sortable = new Sortable(el, {
onUpdate: function (evt) {
var itemEl = evt.item;
// here happens some stuff
},
filter: '.js-remove',
onFilter: function (evt) {
// here happens some stuff
}
});
I know you can do it in jQuery UI sortable like this:
$( ".sortable" ).sortable({
cancel: ".static"
});
How can I do this in SortableJS?
Further to #BenG comment, you need to use filter instead of cancel.
var el = document.getElementById('items');
var sortable = Sortable.create(el, {
filter: ".static"
});
<script src="//cdnjs.cloudflare.com/ajax/libs/Sortable/1.4.2/Sortable.min.js"></script>
<link href="http://rubaxa.github.io/Sortable/st/app.css" rel="stylesheet" />
<ul id="items" class="block__list block__list_words">
<li>item 1</li>
<li class="static">item 2</li>
<li>item 3</li>
</ul>
As Bob Stein mentionend in the comments:
You need to add both:
the filter: 'selector' property
the onMove: function (e) { return e.related.className.indexOf('static') === -1; } callback listener function
to completely prevent an element from being rearranged at the beginning or end of a list.
Working with multiple sortable instances:
If you have multiple lists, from which you can exchange elements, you would add the same code to the sortable instances. This is because a dragged element from another sortable instance does not call the callback functions of the sortable instance to be added, but those of its source sortable instance. See this example below:
var el = document.getElementById('items');
var sortable = Sortable.create(el, {
filter: ".static",
group: {
name: 'list'
},
onMove(e) {
return e.related.className.indexOf('static') === -1;
}
});
var items2 = document.getElementById('items2');
var sortable = Sortable.create(items2, {
filter: ".static",
group: {
name: 'list'
},
onMove(e) {
return e.related.className.indexOf('static') === -1;
}
});
<script src="//cdnjs.cloudflare.com/ajax/libs/Sortable/1.14.0/Sortable.min.js"></script>
<link href="http://rubaxa.github.io/Sortable/st/app.css" rel="stylesheet" />
<ul id="items" class="block__list block__list_words">
<li class="static">FRUITS</li>
<li>Strawberry</li>
<li>Banana</li>
<li>Peach</li>
</ul><ul id="items2" class="block__list block__list_words">
<li class="static">COMPANIES</li>
<li>Microsoft</li>
<li>Apple</li>
<li>Intel</li>
</ul>
Related
How can I compress my jQuery useful? I want to add a function to show an element when I hover another one. The function below is exactly what I want, but I want it more dynamic. Maybe with an data attribute?
var item_first = $('.item_first');
var item_second = $('.item_second');
var item_third = $('.item_third');
var item_fourth = $('.item_fourth');
var image_first = $('.image_first');
var image_second = $('.image_second');
var image_third = $('.image_third');
var image_fourth = $('.image_fourth');
$(document).ready(function () {
item_first.hover(function () {
image_first.addClass('active');
}, function () {
image_first.removeClass('active');
});
item_second.hover(function () {
image_second.addClass('active');
}, function () {
image_second.removeClass('active');
});
item_third.hover(function () {
image_third.addClass('active');
}, function () {
image_third.removeClass('active');
});
item_fourth.hover(function () {
image_fourth.addClass('active');
}, function () {
image_fourth.removeClass('active');
});
});
https://jsfiddle.net/gt5kw00q/
Sorry for my bad English. I try to write so that you understand it.
I would write the code like below.
$('img') will select all your images and apply the code to them on hover.
$('img').hover(function(){
$(this).addClass('active');
},function(){
$(this).removeClass('active');
});
Based on your fiddle, try this approach
$( ".left__item" ).hover( function(){
$(".right__image").eq( $(this).index() ).addClass( "active" );
}, function(){
$(".right__image").eq( $(this).index() ).removeClass( "active" );
})
Demo
$(document).ready(function() {
$(".left__item").hover(function() {
$(".right__image").eq($(this).index()).addClass("active");
}, function() {
$(".right__image").eq($(this).index()).removeClass("active");
})
});
.right__image {
display: none;
}
.right__image.active {
display: block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="left">
<ul class="left__inner">
<li class="left__item item_first active">
Werte
</li>
<li class="left__item item_second">
Team
</li>
<li class="left__item item_third">
Arbeitsweise
</li>
<li class="left__item item_fourth">
Standort
</li>
</ul>
</div>
<div class="right">
<div class="right__inner">
<div class="right__image image_first">
IMAGE 1 HERE
</div>
<div class="right__image image_second">
IMAGE 2 HERE
</div>
<div class="right__image image_third">
IMAGE 3 HERE
</div>
<div class="right__image image_fourth">
IMAGE 4 HERE
</div>
</div>
</div>
Give your elements a class name and a data attribute with the target(id):
<div class="myHoverElement" id="ele1" data-targetid="image_1"></div>
<div class="myHoverElement" id="ele2" data-targetid="image_2"></div>
<img id="image_1">
<img id="image_2">
You can then bind a hover event to all those elements at once:
$('.myHoverElement').hover(
function() { $('#' + $(this).data('targetid')).addClass('active') },
function() { $('#' + $(this).data('targetid')).removeClass('active') }
);
$(this) is a reference to the currently hovered element.
Please find working solution below, enjoy :)
var items = {
item_first: 'image_first',
item_second: 'image_second',
item_third: 'image_third',
item_fourth: 'image_fourth'
}
$(document).ready(function() {
function addClass(key) {
$('.' + items[key]).addClass('active');
}
function removeClass(key) {
$('.' + items[key]).removeClass('active');
}
for (var key in items) {
$('.' + key).hover(addClass.bind(null, key), removeClass.bind(null, key))
}
});
.right__image {
display: none;
}
.right__image.active {
display: block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="left">
<ul class="left__inner">
<li class="left__item item_first active">
Werte
</li>
<li class="left__item item_second">
Team
</li>
<li class="left__item item_third">
Arbeitsweise
</li>
<li class="left__item item_fourth">
Standort
</li>
</ul>
</div>
<div class="right">
<div class="right__inner">
<div class="right__image image_first active">
IMAGE 1 HERE
</div>
<div class="right__image image_second">
IMAGE 2 HERE
</div>
<div class="right__image image_third">
IMAGE 3 HERE
</div>
<div class="right__image image_fourth">
IMAGE 4 HERE
</div>
</div>
</div>
I need help with my code for a hamburger menu. I need to use this array to create the menu elements in jquery:
var menu = [{
'title': 'Save',
'onclick': function() {
alert('Open clicked');
}
}, {
'title': 'Load',
'onclick': function() {
alert('Close clicked');
}
}, {
'title': 'Hide menu',
'onclick': function() {
//put a code to close menu
}
}];
Here is what I have so far and I need to use the array above to update it to work with the array.
jQuery
$(document).ready(function() {
$('#menulink').click(function(event) {
event.preventDefault();
if($('.navigation-wrapper').hasClass('show-menu')) {
$('.navigation-wrapper').removeClass('show-menu');
$('.navigation').hide();
$('.navigation li').removeClass('small-padding');
} else {
$('.navigation-wrapper').addClass('show-menu');
$('.navigation').fadeIn();
$('.navigation li').addClass('small-padding');
}
});
});
HTML
<a id="menulink" href="#">
<div class="hamburger-wrapper">
<div class="inner-hamburger-wrapper">
<div class="hamburger"></div>
<div class="hamburger"></div>
<div class="hamburger"></div>
</div>
<div class="menu-title"><p>Menu</p></div>
</div>
</a>
<ul class="navigation">
<li>Home</li>
<li>Menu Item 2</li>
<li>Menu Item 3</li>
<li>Menu Item 4</li>
<li>Menu Item 5</li>
<li>Menu Item 6</li>
</ul>
It would be nice to get any help that I can.
Using jQuery .append() you can append the array items to a list for creation.
We have to target the functions seperately, but included is a solution where you could put them inline, if you converted the menu[i] items to strings.
// Generate an element, append index to referencing the executing function
$.each(menu, function(index, element) {
$('ul.navigation').append('<li data-index="'+index+'">'+element.title+'</li>');
});
// Run the executing function associated with item
$('ul.navigation > li').click(function() {
var item = $(this).attr('data-index');
menu[item].onclick();
});
// This could be done easier like so:
// $.each(menu, function(index, element) {
// $('ul.navigation').append('<li data-index="'+index+'">'+element.title+'</li>');
// });
// but would require modifying the menu[i] items' functions to just be strings
Here's an updated Fiddle.
I am trying to drag an element from out site of kendoSortable and drop it into kendoSortable.
I set connectWith property of kendoSortable. But it`s not working.
In Kendo UI demo i did not find this kind of example.
Here is my Code :
<h1>Sortable</h1>
<ul id="sortable">
<li class="list-item">Apples</li>
<li class="list-item">Grapefruits</li>
<li class="list-item">Bananas</li>
</ul>
<h1>Dragable</h1>
<ul id="dragable">
<li class="list-item">D1</li>
<li class="list-item">D2</li>
<li class="list-item">D3</li>
</ul>
<script>
$("#sortable").kendoSortable({
connectWith: "#dragable",
placeholder: function placeholder(element) {
return $("<li class='list-item' id='placeholder'>Drop Here!</li>");
},
});
$("#dragable li").kendoDraggable({
hint: function () {
return $("<li class='list-item' id='placeholder'>GOOOOOO!</li>");
}
});
$("#sortable").kendoDropTarget({
dragenter: function () {
console.log("enter");
},
dragleave: function () {
console.log("leve");
},
drop: function (e) {
}
});
</script>
In dojo.telerik
Given your two lists:
<h1>Sortable</h1>
<ul id="sortable">
<li class="list-item">Apples</li>
<li class="list-item">Grapefruits</li>
<li class="list-item">Bananas</li>
</ul>
<h1>Dragable</h1>
<ul id="dragable">
<li class="list-item">D1</li>
<li class="list-item">D2</li>
<li class="list-item">D3</li>
</ul>
and assuming that you want to copy it from the second (#draggable) into the first (#sortable), what you should do define connectWith in the second (origin of the copy):
$("#sortable").kendoSortable({
placeholder: function placeholder(element) {
return $("<li class='list-item' id='placeholder'>Drop Here 1!</li>");
}
});
$("#dragable").kendoSortable({
connectWith: "#sortable",
placeholder: function placeholder(element) {
return $("<li class='list-item' id='placeholder'>Drop Here 2!</li>");
}
});
Also important to note that placeholder probably be defined in both. The first is used when you move from this list while the second is used when the origin is in the second list (no matter if the drop is the first or the second).
You can see it here: http://dojo.telerik.com/#OnaBai/oJIy
I have a draggable list, and a sortable list. The draggable list will have ALL possible items. The sortable list is the user's selections.
I want the sortable to do a check on receive to see if the item already exists, and if so, stop the sort and revert the item back to the draggable list. However, even when the cancel event fires, the update event continues and the revert never happens.
What am I missing?
Here's the fiddle: http://jsfiddle.net/XW48M/1/
HTML:
<div class="container-fluid">
<div class="row">
<div class="col-md-5">
<ul id="teams" class="list-group">
<li class="list-group-item poll-assets" data-id="1" data-name="Team 1">Team 1</li>
<li class="list-group-item poll-assets" data-id="2" data-name="Team 2">Team 2</li>
<li class="list-group-item poll-assets" data-id="3" data-name="Team 3">Team 3</li>
</ul>
</div>
<div class="col-md-5">
<ul id="poll" class="list-group">
<li id="1" class="list-group-item poll-item" data-id="1" data-name="Team 1">Team 1</li>
<li id="4" class="list-group-item poll-item" data-id="4" data-name="Team 4">Team 4</li>
<li id="5" class="list-group-item poll-item" data-id="5" data-name="Team 5">Team 5</li>
</ul>
</div>
</div>
</div>
Javascript:
$(document).ready(function () {
$("#poll").sortable({
revert: true,
update: function (event, ui) {
console.log('update');
var order = $("#poll").sortable("toArray");
if ($(ui.item).hasClass('ui-draggable')) {
$(ui.item).addClass('poll-item').removeClass('ui-draggable draggable').attr('id', $(ui.item).data('id'));
}
},
receive: function (event, ui) {
console.log('receive');
var order = $( "#poll" ).sortable( "toArray" );
var id = $(ui.item.data('id'));
if ($.inArray(id, order)) {
$("#poll").sortable('cancel');
console.log('CANCELLED');
return;
} else {
$(ui.item).remove();
}
}
}).disableSelection();
$('#teams')
.find('.poll-assets').draggable({
opacity: 0.75,
appendTo: document.body,
helper: 'clone',
connectToSortable: '#poll',
}).disableSelection();
});
I don't quite understand why you went with draggable + sortable instead of 2 connected sortables.
So i gave it a try using this method and i came with something like that :
$("#teams").sortable({
revert: true,
connectWith: "#poll",
start: function () {
console.log('start');
var order = $('#poll').sortable("toArray", {
attribute: "data-id"
});
$('#poll').data('order', order);
}
}).disableSelection();
$("#poll").sortable({
revert: true,
receive: function (event, ui) {
console.log('receive');
var order = $('#poll').data('order');
var id = $(ui.item).data('id').toString();
if ($.inArray(id, order) != -1) {
console.log('CANCELLED');
$(ui.sender).sortable("cancel");
} else {
console.log('NOT CANCELLED');
}
}
}).disableSelection();
Main issue was to get the correct item array, because on receive event, the array is already updated with the "newly" added item. I had to put it inside data on the start event of the other sortable and to get it back on receive event.
I still find a few things not very satisfying:
Using id selectors inside start and receive callbacks; but event arguments didn't contain the elements i needed
The revert effect is quite ... weird
Anyhow, it is the closest i could get to what you expected; i also made a jsfiddle for you to check.
Let me know if it helps / post your code if you can get anything better.
HTML:
<div class="leftDiv">
<div class="item item1">Item 1</div>
<div class="item item2">Item 2</div>
<div class="item item3">Item 3</div>
<div class="item item4">Item 4</div>
<div class="item item5">Item 5</div>
<div class="item item6">Item 6</div>
</div>
<div class="rightDiv">
</div>
JS:
$(document).ready(function(){
$(".leftDiv .item").draggable({
helper: function(ev, ui) {
return "<span class='helperPick'>"+$(this).html()+"</span>";
},
connectToSortable: ".rightDiv"
});
$(".rightDiv").sortable({
'items': ".item",
'receive': function(event, ui){
// find the class of the dropped ui, look for the one with the integer suffix.
var clazz = getClassNameWithNumberSuffix(ui.item);
$('.leftDiv .' + clazz).draggable( "option", "revert", true )
if($('.rightDiv .' + clazz).length > 1){
$('.rightDiv .' + clazz + ':not(:first)').remove();
}
}
});
});
function getClassNameWithNumberSuffix(el) {
var className = null;
var regexp = /\w+\d+/;
$($(el).attr('class').split(' ')).each(function() {
if (regexp.test(this)) {
className = this;
return false;
}
});
return className;
}
CSS:
.leftDiv, .rightDiv {width:120px; float:left; border:1px solid #000; padding:5px; margin:10px; min-height:130px}
.rightDiv {margin-left:40px}
.item {height:20px; line-height:20px; text-align:center; border:1px solid #EEE; background-color:#FFF}
.helperPick {border:1px dashed red; height:20px; line-height:20px; text-align:center; width:120px}
Source: http://jsfiddle.net/perrytew/RxKkA/3/
I am trying to figure why the nav links wont open the accordion. I am sure there is just some jquery that is not in proper syntax. I changed the selectors in the jquery code and now it wont work.
Im sure to a trained eye this should be a quick fix.
Can anyone help?
////////////////////////////
// http://www.adipalaz.com/experiments/jquery/accordion.html
///////////////////////////
(function($) {
//http://www.mail-archive.com/jquery-en#googlegroups.com/msg43851.html
$.fn.orphans = function(){
var txt = [];
this.each(function(){$.each(this.childNodes, function() {
if (this.nodeType == 3 && $.trim(this.nodeValue)) txt.push(this)
})});
return $(txt);
};
//http://www.learningjquery.com/2008/02/simple-effects-plugins:
$.fn.fadeToggle = function(speed, easing, callback) {
return this.animate({opacity: 'toggle'}, speed, easing, callback);
};
$.fn.slideFadeToggle = function(speed, easing, callback) {
return this.animate({opacity: 'toggle', height: 'toggle'}, speed, easing, callback);
};
})(jQuery);
////////////////////////////
$(function() {
$('.collapse').hide();
$('.expand').orphans().wrap('');
//demo 4 - div.demo:eq(3) - queued slide effects:
$('div.demo .expand').click(function() {
var $thisCllps = $(this).next('.collapse');
var $cllpsVisible = $(this).ul('.expand').next('.collapse:visible');
($cllpsVisible.length) ? $(this).toggleClass('open').siblings('.expand').removeClass('open')
.next('.collapse:visible').slideUp(400, function() {
$thisCllps.slideDown();
}) : $thisCllps.slideToggle().prev('.expand').toggleClass('open');
return false;
});
});
<div class="demo">
<ul class="collapse" class="ul" style="display: none; ">
<li>Item 1.1.</li>
<li>Item 1.2.</li>
</ul>
<ul class="collapse" class="ul" style="display: none; ">
<li>Item 2.1.</li>
<li>Item 2.2.</li>
</ul>
<ul class="collapse" class="ul" style="display: none; ">
<li>Item 3.1.</li>
<li>Item 3.2.</li>
</ul>
</div>
<ul>
<li>
<h4 class="expand">Slide Up/Down UL 1</h4>
</li>
<li>
<h4 class="expand">Slide Up/Down UL 2</h4>
</li>
<li>
<h4 class="expand">Slide Up/Down UL 3</h4>
</li>
</ul>
Why not just use the Jquery accordion function?
http://docs.jquery.com/UI/Accordion