97 lines
No EOL
6 KiB
JavaScript
97 lines
No EOL
6 KiB
JavaScript
! function(factory) {
|
|
"use strict";
|
|
if ("function" == typeof define && define.amd) define(["knockout"], factory);
|
|
else if ("function" == typeof require && "object" == typeof exports && "object" == typeof module) {
|
|
var ko = require("knockout");
|
|
factory(ko)
|
|
} else factory(window.ko)
|
|
}(function(ko) {
|
|
"use strict";
|
|
var init = function(element, valueAccessor, allBindings, viewModel, bindingContext, sortableOptions) {
|
|
var options = buildOptions(valueAccessor, sortableOptions);
|
|
["onStart", "onEnd", "onRemove", "onAdd", "onUpdate", "onSort", "onFilter"].forEach(function(e) {
|
|
(options[e] || eventHandlers[e]) && (options[e] = function(eventType, parentVM, parentBindings, handler, e) {
|
|
var itemVM = ko.dataFor(e.item),
|
|
bindings = ko.utils.peekObservable(parentBindings()),
|
|
bindingHandlerBinding = bindings.sortable || bindings.draggable,
|
|
collection = bindingHandlerBinding.collection || bindingHandlerBinding.foreach;
|
|
handler && handler(e, itemVM, parentVM, collection, bindings), eventHandlers[eventType] && eventHandlers[eventType](e, itemVM, parentVM, collection, bindings)
|
|
}.bind(void 0, e, viewModel, allBindings, options[e]))
|
|
});
|
|
var sortableElement = Sortable.create(element, options);
|
|
return ko.utils.domNodeDisposal.addDisposeCallback(element, function() {
|
|
sortableElement.destroy()
|
|
}), ko.bindingHandlers.template.init(element, valueAccessor)
|
|
},
|
|
update = function(element, valueAccessor, allBindings, viewModel, bindingContext, sortableOptions) {
|
|
return ko.bindingHandlers.template.update(element, valueAccessor, allBindings, viewModel, bindingContext)
|
|
},
|
|
eventHandlers = function(handlers) {
|
|
var moveOperations = [],
|
|
tryMoveOperation = function(e, itemVM, parentVM, collection, parentBindings) {
|
|
var currentOperation = {
|
|
event: e,
|
|
itemVM: itemVM,
|
|
parentVM: parentVM,
|
|
collection: collection,
|
|
parentBindings: parentBindings
|
|
},
|
|
existingOperation = moveOperations.filter(function(op) {
|
|
return op.itemVM === currentOperation.itemVM
|
|
})[0];
|
|
if (existingOperation) {
|
|
moveOperations.splice(moveOperations.indexOf(existingOperation), 1);
|
|
var removeOperation = "remove" === currentOperation.event.type ? currentOperation : existingOperation,
|
|
addOperation = "add" === currentOperation.event.type ? currentOperation : existingOperation;
|
|
moveItem(itemVM, removeOperation.collection, addOperation.collection, addOperation.event.clone, addOperation.event)
|
|
} else moveOperations.push(currentOperation)
|
|
},
|
|
moveItem = function(itemVM, from, to, clone, e) {
|
|
var fromArray = from(),
|
|
originalIndex = fromArray.indexOf(itemVM),
|
|
newIndex = e.newIndex;
|
|
e.item.previousElementSibling && (newIndex = fromArray.indexOf(ko.dataFor(e.item.previousElementSibling)), originalIndex > newIndex && (newIndex += 1)), e.item.parentNode.removeChild(e.item), fromArray.splice(originalIndex, 1), from.valueHasMutated(), clone && from !== to && (fromArray.splice(originalIndex, 0, itemVM), from.valueHasMutated()), to().splice(newIndex, 0, itemVM), to.valueHasMutated()
|
|
};
|
|
return handlers.onRemove = tryMoveOperation, handlers.onAdd = tryMoveOperation, handlers.onUpdate = function(e, itemVM, parentVM, collection, parentBindings) {
|
|
moveItem(itemVM, collection, collection, !1, e)
|
|
}, handlers
|
|
}({}),
|
|
buildOptions = function(bindingOptions, options) {
|
|
var merge = function(into, from) {
|
|
for (var prop in from) "[object Object]" === Object.prototype.toString.call(from[prop]) ? ("[object Object]" !== Object.prototype.toString.call(into[prop]) && (into[prop] = {}), into[prop] = merge(into[prop], from[prop])) : into[prop] = from[prop];
|
|
return into
|
|
},
|
|
unwrappedOptions = ko.utils.peekObservable(bindingOptions()).options || {};
|
|
return options = merge({}, options), unwrappedOptions.group && "[object Object]" !== Object.prototype.toString.call(unwrappedOptions.group) && (unwrappedOptions.group = {
|
|
name: unwrappedOptions.group
|
|
}), merge(options, unwrappedOptions)
|
|
};
|
|
ko.bindingHandlers.draggable = {
|
|
sortableOptions: {
|
|
group: {
|
|
pull: "clone",
|
|
put: !1
|
|
},
|
|
sort: !1
|
|
},
|
|
init: function(element, valueAccessor, allBindings, viewModel, bindingContext) {
|
|
return init(element, valueAccessor, allBindings, viewModel, 0, ko.bindingHandlers.draggable.sortableOptions)
|
|
},
|
|
update: function(element, valueAccessor, allBindings, viewModel, bindingContext) {
|
|
return update(element, valueAccessor, allBindings, viewModel, bindingContext, ko.bindingHandlers.draggable.sortableOptions)
|
|
}
|
|
}, ko.bindingHandlers.sortable = {
|
|
sortableOptions: {
|
|
group: {
|
|
pull: !0,
|
|
put: !0
|
|
}
|
|
},
|
|
init: function(element, valueAccessor, allBindings, viewModel, bindingContext) {
|
|
return init(element, valueAccessor, allBindings, viewModel, 0, ko.bindingHandlers.sortable.sortableOptions)
|
|
},
|
|
update: function(element, valueAccessor, allBindings, viewModel, bindingContext) {
|
|
return update(element, valueAccessor, allBindings, viewModel, bindingContext, ko.bindingHandlers.sortable.sortableOptions)
|
|
}
|
|
}
|
|
}); |