Im trying to create a draggable list with list.js but when I try to edit, add or delete an item nothing happen, I guess is something with the callbacks but I cant find the solution.
this is my html:
<script src="http://listjs.com/assets/javascripts/list.min.js"></script>
<div id="contacts">
<ul id="sortable">
<li class="id">
<img src="http://lorempixum.com/100/100/nature/1" class="img" >
<h3>The Grasslands</h3>
<p class="description">Lorem ipsum dolor sit amet, consectetur adipiscing elit. .</p>
<td class="edit"><button class="edit-item-btn">Edit</button></td>
<td class="remove"><button class="remove-item-btn">Remove</button> </td>
</li>
<li class="id">
<img src="http://lorempixum.com/100/100/nature/2" class="img" >
<h3>Paradise Found</h3>
<p class="description">Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>
<td class="edit"><button class="edit-item-btn">Edit</button></td>
<td class="remove"><button class="remove-item-btn">Remove</button></td>
</li>
<li class="id">
<img src="http://lorempixum.com/100/100/nature/3" class="img" >
<h3 >Smoke On The Water</h3>
<p class="description">Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>
<td class="edit"><button class="edit-item-btn">Edit</button></td>
<td class="remove"><button class="remove-item-btn">Remove</button></td>
</li>
<li class="id">
<img src="http://lorempixum.com/100/100/nature/4" class="img" >
<h3>Headline</h3>
<p class="description">Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>
<td class="edit"><button class="edit-item-btn">Edit</button></td>
<td class="remove"><button class="remove-item-btn">Remove</button></td>
</li>
</ul>
<table>
<td class="img">
<input type="hidden" id="id-field" />
<input type="text" id="img-field" placeholder="Img" />
</td>
<td class="description">
<input type="text" id="description-field" placeholder="Description" />
</td>
<td class="add">
<button id="add-btn">Add</button>
<button id="edit-btn">Edit</button>
</td>
</table>
</div>
and this is my js code:
/*sortable */
$(function() {
$( "#sortable" ).sortable();
$( "#sortable" ).disableSelection();
});
/* listjs */
var options = {
valueNames: [ 'id', 'description', 'img', ]
};
// Init list
var contactList = new Sortable('contacts', options);
var idField = $('#id-field'),
descriptionField = $('#description-field'),
imgField = $('#img-field'),
addBtn = $('#add-btn'),
editBtn = $('#edit-btn').hide(),
removeBtns = $('.remove-item-btn'),
editBtns = $('.edit-item-btn');
// Sets callbacks to the buttons in the list
refreshCallbacks();
addBtn.click(function() {
contactList.add({
id: Math.floor(Math.random()*110000),
description: descriptionField.val(),
img: imgField.val(),
});
clearFields();
refreshCallbacks();
});
editBtn.click(function() {
var item = contactList.get('id', idField.val())[0];
item.values({
id:idField.val(),
description: descriptionField.val(),
img: imgField.val(),
});
clearFields();
editBtn.hide();
addBtn.show();
});
function refreshCallbacks() {
// Needed to add new buttons to jQuery-extended object
removeBtns = $(removeBtns.selector);
editBtns = $(editBtns.selector);
removeBtns.click(function() {
var itemId = $(this).closest('li').find('.id').text();
contactList.remove('id', itemId);
});
editBtns.click(function() {
var itemId = $(this).closest('li').find('.id').text();
var itemValues = contactList.get('id', itemId)[0].values();
idField.val(itemValues.id);
descriptionField.val(itemValues.description);
imgField.val(itemValues.img);
editBtn.show();
addBtn.hide();
});
}
function clearFields() {
descriptionField.val('');
imgField.val('');
}
Thanks in advance
I have not used listjs, so I do not know if this is what you're trying to do. I did find the following: http://listjs.com/examples/add-get-remove/
From that and your example, I built this: https://jsfiddle.net/Twisty/q7LhmaLb/6/
HTML
<div id="contacts">
<ul id="sortable" class="list">
<li class="id">
<img src="https://lorempixel.com/100/100/nature/1/" class="img">
<h3 class="title">The Grasslands</h3>
<p class="description">Lorem ipsum dolor sit amet, consectetur adipiscing elit. .</p>
<td class="edit">
<button class="edit-item-btn">Edit</button>
</td>
<td class="remove">
<button class="remove-item-btn">Remove</button>
</td>
</li>
<li class="id">
<img src="https://lorempixel.com/100/100/nature/2/" class="img">
<h3 class="title">Paradise Found</h3>
<p class="description">Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>
<td class="edit">
<button class="edit-item-btn">Edit</button>
</td>
<td class="remove">
<button class="remove-item-btn">Remove</button>
</td>
</li>
<li class="id">
<img src="https://lorempixel.com/100/100/nature/3/" class="img">
<h3 class="title">Smoke On The Water</h3>
<p class="description">Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>
<td class="edit">
<button class="edit-item-btn">Edit</button>
</td>
<td class="remove">
<button class="remove-item-btn">Remove</button>
</td>
</li>
<li class="id">
<img src="https://lorempixel.com/100/100/nature/4/" class="img">
<h3 class="title">Headline</h3>
<p class="description">Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>
<td class="edit">
<button class="edit-item-btn">Edit</button>
</td>
<td class="remove">
<button class="remove-item-btn">Remove</button>
</td>
</li>
</ul>
<table>
<td class="img">
<input type="hidden" id="id-field" />
<input type="text" id="img-field" placeholder="Img" />
</td>
<td class="">
<input type="text" id="title-field" placeholder="Title" />
</td>
<td class="description">
<input type="text" id="description-field" placeholder="Description" />
</td>
<td class="add">
<button id="add-btn">Add</button>
<button id="edit-btn">Edit</button>
</td>
</table>
</div>
CSS
body {
font-family: sans-serif;
}
.list {
list-style: none;
padding: 0;
margin: 0;
}
.list li {
border: 1px solid #ccc;
border-radius: 6px;
padding: 10px;
margin-bottom: 10px;
}
.list li:after {
content: "";
display: table;
clear: both;
}
.list .img {
display: inline-block;
float: left;
margin-right: 5px;
}
.list .title {
display: inline-block;
padding: 0;
margin: 0;
}
.list .description {
font-size: 0.65em;
padding: 0;
margin:0;
}
JavaScript
/*sortable */
$(function() {
$("#sortable").sortable().disableSelection();
});
/* listjs */
var options = {
valueNames: ['id', 'title', 'description', 'img', ]
};
// Init list
var contactList = new List('contacts', options);
var idField = $('#id-field'),
titleField = $("#titleField"),
descriptionField = $('#description-field'),
imgField = $('#img-field'),
addBtn = $('#add-btn'),
editBtn = $('#edit-btn').hide(),
removeBtns = $('.remove-item-btn'),
editBtns = $('.edit-item-btn'),
sortList = $("#sortable");
// Sets callbacks to the buttons in the list
refreshCallbacks();
addBtn.click(function() {
contactList.add({
id: Math.floor(Math.random() * 110000),
description: descriptionField.val(),
img: imgField.val(),
});
clearFields();
refreshCallbacks();
sortList.sortable("refresh");
});
editBtn.click(function() {
var item = contactList.get('id', idField.val())[0];
item.values({
id: idField.val(),
description: descriptionField.val(),
img: imgField.val(),
});
clearFields();
editBtn.hide();
addBtn.show();
});
function refreshCallbacks() {
// Needed to add new buttons to jQuery-extended object
removeBtns = $(removeBtns.selector);
editBtns = $(editBtns.selector);
removeBtns.click(function() {
var itemId = $(this).closest('li').find('.id').text();
contactList.remove('id', itemId);
});
editBtns.click(function() {
var itemId = $(this).closest('li').find('.id').text();
var itemValues = contactList.get('id', itemId)[0].values();
idField.val(itemValues.id);
descriptionField.val(itemValues.description);
imgField.val(itemValues.img);
editBtn.show();
addBtn.hide();
});
}
function clearFields() {
descriptionField.val('');
imgField.val('');
}
It allows you to sort the list and add items. Since an item is being added dynamically, $("#sortable").sortable("refresh");
should be called when items are added.
Hope that helps.
Update 1
I found a number of little issues and tinkered with the styling more for jQuery UI. Play with it here: https://jsfiddle.net/Twisty/q7LhmaLb/11/
JavaScript
/* listjs */
var options = {
valueNames: ['id', {
attr: 'src',
name: 'img'
}, 'title', 'description']
};
// Init list
var contactList = new List('contacts', options);
var idField = $('#id-field'),
titleField = $("#title-field"),
descriptionField = $('#description-field'),
imgField = $('#img-field'),
addBtn = $('#add-btn'),
editBtn = $('#edit-btn').hide(),
removeBtns = $('.remove-item-btn'),
editBtns = $('.edit-item-btn'),
sortList = $("#sortable");
// Sets callbacks to the buttons in the list
refreshCallbacks();
addBtn.click(function() {
contactList.add({
id: Math.floor(Math.random() * 110000),
title: titleField.val(),
description: descriptionField.val(),
img: imgField.val()
});
clearFields();
refreshCallbacks();
sortList.sortable("refresh");
});
editBtn.click(function() {
var item = contactList.get('id', idField.val())[0];
item.values({
id: idField.val(),
title: titleField.val(),
description: descriptionField.val(),
img: imgField.val(),
});
clearFields();
editBtn.hide();
addBtn.show();
});
function refreshCallbacks() {
// Needed to add new buttons to jQuery-extended object
console.log("Callback selectors: ", removeBtns.attr("class"), editBtns.attr("class"));
removeBtns = $("." + removeBtns.attr("class"));
editBtns = $("." + editBtns.attr("class"));
removeBtns.click(function(e) {
console.log(e);
var itemId = $(this).closest('li').find('.id').text();
contactList.remove('id', itemId);
});
editBtns.click(function(e) {
console.log(e);
var itemId = $(this).closest('li').find('.id').text();
var itemValues = contactList.get('id', itemId)[0].values();
idField.val(itemValues.id);
titleField.val(itemValues.title);
descriptionField.val(itemValues.description);
imgField.val(itemValues.img);
editBtn.show();
addBtn.hide();
});
}
function clearFields() {
titleField.val("");
descriptionField.val("");
imgField.val("");
}
/*sortable */
$(function() {
$("#sortable").sortable().disableSelection();
$(".edit-item-btn").button({
icon: "ui-icon-comment",
showLabel: false
});
$(".remove-item-btn").button({
icon: "ui-icon-close",
showLabel: false
});
$(".buttons").controlgroup();
$('#search-field').on('keyup', function() {
var searchString = $(this).val();
contactList.search(searchString);
});
});
I did a lot of little things, as you can see, one is fixing the use of .selector
. I switched to .attr("class")
to get the class name and used it as a class selector. This works since the element only has 1 class defined. Might hunt around to see if there is better solution.
This is used in refreshCallbacks()
like so:
// Needed to add new buttons to jQuery-extended object
removeBtns = $("." + removeBtns.attr("class"));
editBtns = $("." + editBtns.attr("class"));
This function just re-assigns all the elements (in case any new ones were created) back to the variable. This fixed the issue with "Edit" and "Remove" buttons. I noticed edits were not capturing the Image Source url. I found that here: http://listjs.com/examples/data-attributes-custom-attributes/ So to fix it in your project, we do:
var options = {
valueNames: ['id', {
attr: 'src',
name: 'img'
}, 'title', 'description']
};
That I think will do you well.
Update 2
I spoke too soon.
https://jsfiddle.net/Twisty/q7LhmaLb/12/
The id
was not being read, so edits would always pull up the first item. Fixed by updating the li
with a data-id
attribute. I had to go in and repair some of the jQuery to line up with this.
Update 3
Found another add, when sorting, the order is changed. When this happens, the List Index needs to be updated. Simple fix:
$("#sortable").sortable({
update: function(e, ui) {
contactList.reIndex();
}
}).disableSelection();