Skip to content

Instantly share code, notes, and snippets.

@dydx
Created November 27, 2016 06:57
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save dydx/8919196d0ef1dba471fcf32f6c47b34e to your computer and use it in GitHub Desktop.
Save dydx/8919196d0ef1dba471fcf32f6c47b34e to your computer and use it in GitHub Desktop.
require('./bootstrap');
var sortableContainer = document.getElementById('sortable-container');
var sortableItems = sortableContainer.children;
var saveButton = document.getElementById('save');
/**
* Set data-starting-position on sortableItems
* @param items
*/
function setInitialIndexes (items) {
for (var i = 0; i < items.length; i++) {
items[i].dataset.startingPosition = i + 1;
}
}
/**
* Set data-new-position on sortableItems
* @param items
*/
function setNewIndexes (items) {
for (var i = 0; i < items.length; i++) {
items[i].dataset.newPosition = i + 1;
}
}
/**
* Send list of updated indices to the server
* @param items
*/
function sendUpdatedIndices (items) {
$.ajax({
url: 'sort',
type: 'PUT',
data: {
_token: window.Laravel.csrfToken,
sorted: items
},
dataType: 'JSON',
success: function (data) {
console.log(data);
}
});
}
// set the initial indices
(function () {
setInitialIndexes(sortableItems);
})();
var drake = dragula({
containers: [sortableContainer]
});
// whenever an item is dragged and dropped, set the indices
drake.on('drop', function () {
setNewIndexes(sortableItems);
});
// send modified indices to server for updating records
saveButton.addEventListener('click', function (e) {
var movedItems = [];
for (var i = 0; i < sortableItems.length; i++) {
var item = sortableItems[i];
var itemId = item.dataset.id;
var startingPosition = item.dataset.startingPosition;
var newPosition = item.dataset.newPosition;
if (startingPosition != newPosition) {
movedItems.push([itemId, newPosition]);
}
}
sendUpdatedIndices(movedItems);
});
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<meta name="csrf-token" content="{{ csrf_token() }}">
<link href="/css/app.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/dragula/3.7.2/dragula.min.css">
<script>
window.Laravel = <?php echo json_encode([
'csrfToken' => csrf_token(),
]); ?>
</script>
<title>Sortable</title>
<link rel="stylesheet" href="/css/app.css">
</head>
<body>
<div class="container">
<div class="page-header">
<h1>Sortable</h1>
</div>
<div class="panel panel-default">
<ul class="list-group" id="sortable-container">
@foreach ($todos as $todo)
<li class="list-group-item"
data-id="{{ $todo->id }}"
data-starting-position="{{ $todo->position }}"
data-new-position="{{ $todo->position }}"
>{{ $todo->name }}</li>
@endforeach
</ul>
</div>
<a href="#" id="save" class="btn btn-primary pull-right">Save Order</a>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/dragula/3.7.2/dragula.min.js"></script>
<script src="/js/app.js"></script>
</body>
</html>
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Todo;
class TodosController extends Controller
{
/**
* Display a listing of the resource.
*
* @return \Illuminate\Http\Response
*/
public function index()
{
$todos = Todo::orderBy('position')->get();
return view('todos.index', compact('todos'));
}
/**
* Update positions for supplied items
*
* @param Request $request
* @return \Illuminate\Http\Response
*/
public function sort(Request $request)
{
$sorted = $request->sorted;
foreach ($sorted as $sortedItem) {
$item = Todo::findOrFail($sortedItem[0]);
$item->position = $sortedItem[1];
$item->save();
}
return response()->json($sorted);
}
}
<?php
Route::get('/', 'TodosController@index');
Route::put('/sort', 'TodosController@sort');
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment