Skip to content

Commit

Permalink
Add suppport for jquery ui sortable connected lists (dragging and dro…
Browse files Browse the repository at this point in the history
…pping between lists) and also enable passing sortable options through the Knockout JS binding

Merge remote-tracking branch 'jbosse/master'

Conflicts:
	knockout.jQueryUI-sortable.js
  • Loading branch information
ivanz committed Oct 3, 2012
2 parents d6a9daa + bef3416 commit 1890215
Show file tree
Hide file tree
Showing 3 changed files with 89 additions and 47 deletions.
21 changes: 17 additions & 4 deletions README.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,21 @@ Knockout JS jQuery UI Sortable List Binding

Usage:

<ul data-bind="sortableList: yourObservableArray" >
{{each(i, arrayItem) yourObservableArray}}
<li data-bind="sortableItem: arrayItem"></li>
{{/each}}
<h2>Column 1</h3>
<ul class="mySortableColumn" data-bind="sortableList: yourObservableArray1, sortableOptions: { connectWith: '.mySortableColumn' }" >
<!-- ko foreach: yourObservableArray1 -->
<li data-bind="sortableItem: arrayItem"></li>
<!-- /ko -->
</ul>
<h2>Column 2</h3>
<ul class="mySortableColumn" data-bind="sortableList: yourObservableArray2, sortableOptions: { connectWith: '.mySortableColumn' }" >
<!-- ko foreach: yourObservableArray2 -->
<li data-bind="sortableItem: arrayItem"></li>
<!-- /ko -->
</ul>
<h2>Column 3</h3>
<ul class="mySortableColumn" data-bind="sortableList: yourObservableArray3, sortableOptions: { connectWith: '.mySortableColumn' }" >
<!-- ko foreach: yourObservableArray3 -->
<li data-bind="sortableItem: arrayItem"></li>
<!-- /ko -->
</ul>
90 changes: 56 additions & 34 deletions example/example.html
Original file line number Diff line number Diff line change
@@ -1,29 +1,40 @@
<html>
<head>
<script src="http://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.5.1.min.js" type="text/javascript"></script>
<script src="http://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.7.1.min.js" type="text/javascript"></script>
<script src="http://ajax.aspnetcdn.com/ajax/jquery.ui/1.8.14/jquery-ui.min.js" type="text/javascript"></script>
<script src="http://ajax.aspnetcdn.com/ajax/jquery.validate/1.8.1/jquery.validate.min.js" type="text/javascript"></script>
<script src="http://ajax.aspnetcdn.com/ajax/jquery.templates/beta1/jquery.tmpl.min.js" type="text/javascript"></script>
<script src="https://raw.github.com/SteveSanderson/knockout/master/build/output/knockout-latest.js" type="text/javascript"></script>
<script src="https://raw.github.com/ivanz/knockout.jQueryUI-sortable.js/master/knockout.jQueryUI-sortable.js" type="text/javascript"></script>
<script src="../knockout.jQueryUI-sortable.js" type="text/javascript"></script>

<script type="text/javascript">
var viewModel = {
favouriteMovies: ko.observableArray([{"Title":"Movie 1","Rating":5},
{"Title":"Movie 2","Rating":10},
{"Title":"Movie 3","Rating":12}]),
favouriteSciFiMovies: ko.observableArray([{"Title":"SciFi Movie 1","Rating":5},
{"Title":"SciFi Movie 2","Rating":10},
{"Title":"SciFi Movie 3","Rating":12}]),
favouriteActionMovies: ko.observableArray([{"Title":"Action Movie 1","Rating":5},
{"Title":"Action Movie 2","Rating":10},
{"Title":"Action Movie 3","Rating":12}]),
lastSavedJson: ko.observable(""),

addMovie: function() {
viewModel.favouriteMovies.push({"Title":null,"Rating":0});
addSciFiMovie: function() {
viewModel.favouriteSciFiMovies.push({"Title":null,"Rating":0});
},

addActionMovie: function() {
viewModel.favouriteActionMovies.push({"Title":null,"Rating":0});
},

removeMovie: function(movie) {
ko.utils.arrayRemoveItem(viewModel.favouriteMovies, movie);
viewModel.favouriteSciFiMovies.remove(movie);
viewModel.favouriteActionMovies.remove(movie);
},

save: function() {
viewModel.lastSavedJson(JSON.stringify(viewModel.favouriteMovies()));
var save = {
scifi: ko.toJS(viewModel.favouriteSciFiMovies()),
action: ko.toJS(viewModel.favouriteActionMovies())
}
viewModel.lastSavedJson(JSON.stringify(save));
}
}

Expand All @@ -36,33 +47,44 @@
</head>
<body>
<h1>Knockout JS jQuery UI Sortable List Binding Sample</h1>
<h2>My Favourite Movies</h2>

<ul id="moviesEditor" style="list-style-type: none"
data-bind="template: { name: 'moviesTemplate', data: favouriteMovies }, sortableList: viewModel.favouriteMovies" >

<h2>My Favourite SciFi Movies</h2>
<ul class="favouriteMovies" style="list-style-type: none"
data-bind="sortableList: favouriteSciFiMovies, sortableOptions: { connectWith: '.favouriteMovies' }" >
<!-- ko foreach: favouriteSciFiMovies -->
<li data-bind="sortableItem: $data">
<div>
<img src="https://github.com/ivanz/knockout.jQueryUI-sortable.js/raw/master/example/draggable-icon.png" style="cursor: move" alt=""/>
<label>Title:</label>
<input type="text" data-bind="value: Title"/>
<label>Rating:</label>
<input type="text" data-bind="value: Rating"/>
<a href="#" data-bind="click: $root.removeMovie">Delete</a>
</div>
</li>
<!-- /ko -->
</ul>

<h2>My Favourite Action Movies</h2>
<ul class="favouriteMovies" style="list-style-type: none"
data-bind="sortableList: favouriteActionMovies, sortableOptions: { connectWith: '.favouriteMovies' }" >
<!-- ko foreach: favouriteActionMovies -->
<li data-bind="sortableItem: $data">
<div>
<img src="https://github.com/ivanz/knockout.jQueryUI-sortable.js/raw/master/example/draggable-icon.png" style="cursor: move" alt=""/>
<label>Title:</label>
<input type="text" data-bind="value: Title"/>
<label>Rating:</label>
<input type="text" data-bind="value: Rating"/>
<a href="#" data-bind="click: $root.removeMovie">Delete</a>
</div>
</li>
<!-- /ko -->
</ul>

<script id="moviesTemplate" type="text/x-jquery-template">
{{each(i, movie) $data}}
<li data-bind="sortableItem: movie">
<div data-bind="template: { name: 'movieTemplate', data: movie }"></div>
</li>
{{/each}}
</script>

<script id="movieTemplate" type="text/x-jquery-template">
<img src="https://github.com/ivanz/knockout.jQueryUI-sortable.js/raw/master/example/draggable-icon.png" style="cursor: move" alt=""/>

<label>Title:</label>
<input type="text" data-bind="value: Title"/>

<label>Rating:</label>
<input type="text" data-bind="value: Rating"/>

<a href="#" data-bind="click: function() { viewModel.removeMovie(this); }">Delete</a>
</script>
<button data-bind="click: addSciFiMovie">Add another Scifi Movie</button>

<button data-bind="click: addMovie">Add another</button>
<button data-bind="click: addActionMovie">Add another Action Movie</button>

<p>
<button data-bind="click: save">Save to JSON</button>
Expand Down
25 changes: 16 additions & 9 deletions knockout.jQueryUI-sortable.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,24 +6,31 @@
$(function() {
ko.bindingHandlers.sortableList = {
_dataItemKey: "data-ko-collectionItem",

// Detects when an HTML from a JQuery UI Sortabe has been moved
// and applies the same move to the ViewModel collection item
init: function (element, valueAccessor, allBindingsAccessor) {
$(element).sortable({
update: function (event, ui) {
options = allBindingsAccessor().sortableOptions || {};
options.update = function (event, ui) {
var newIndex = $(element).children().index(ui.item);

var collection = ko.utils.unwrapObservable(valueAccessor());
var collectionItem = $(ui.item).data(ko.bindingHandlers.sortableList._dataItemKey);
var oldIndex = ko.utils.arrayIndexOf(collection, collectionItem);

// move the item from the old index to the new index in the collection.
collection.splice(oldIndex, 1);
collection.splice(newIndex, 0, collectionItem);
valueAccessor().valueHasMutated();
}
});
};
options.remove = function (event, ui) {
var collection = ko.utils.unwrapObservable(valueAccessor());
var collectionItem = $(ui.item).data(ko.bindingHandlers.sortableList._dataItemKey);
var oldIndex = ko.utils.arrayIndexOf(collection, collectionItem);
collection.splice(oldIndex, 1);
};
options.receive = function (event, ui) {
var newIndex = $(element).children().index(ui.item);
var collection = ko.utils.unwrapObservable(valueAccessor());
var collectionItem = $(ui.item).data(ko.bindingHandlers.sortableList._dataItemKey);
collection.splice(newIndex, 0, collectionItem);
};
$(element).sortable(options);
}
};

Expand Down

0 comments on commit 1890215

Please sign in to comment.