From: Olivier Lamy Date: Mon, 13 Feb 2012 13:55:09 +0000 (+0000) Subject: [MRM-1576] rewrite proxies connector page X-Git-Tag: archiva-1.4-M3~1309 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=a96f6d845ce5cc009bb4d38bc0da57cc47907bd4;p=archiva.git [MRM-1576] rewrite proxies connector page add sortable knockout binding. git-svn-id: https://svn.apache.org/repos/asf/archiva/trunk@1243512 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/archiva-modules/archiva-web/archiva-webapp-js/src/main/webapp/js/knockout-sortable.js b/archiva-modules/archiva-web/archiva-webapp-js/src/main/webapp/js/knockout-sortable.js new file mode 100644 index 000000000..ec928b1ba --- /dev/null +++ b/archiva-modules/archiva-web/archiva-webapp-js/src/main/webapp/js/knockout-sortable.js @@ -0,0 +1,137 @@ +//knockout-sortable | (c) 2012 Ryan Niemeyer | http://www.opensource.org/licenses/mit-license +(function(ko, $, undefined) { +var prepareTemplateOptions = function(valueAccessor) { + var result = {}, + options = ko.utils.unwrapObservable(valueAccessor()); + + //build our options to pass to the template engine + if (options.data) { + result.foreach = options.data; + result.name = options.template; + result.afterAdd = options.afterAdd; + result.beforeRemove = options.beforeRemove; + result.afterRender = options.afterRender; + result.includeDestroyed = options.includeDestroyed; + result.templateEngine = options.templateEngine; + } else { + result.foreach = valueAccessor(); + } + + //use an afterRender function to add meta-data + if (options.afterRender) { + //wrap the existing function, if it was passed + result.afterRender = function(element, data) { + ko.bindingHandlers.sortable.afterRender.call(data, element, data); + options.afterRender.call(data, element, data); + }; + } else { + result.afterRender = ko.bindingHandlers.sortable.afterRender; + } + + //return options to pass to the template binding + return result; +}; + +//connect items with observableArrays +ko.bindingHandlers.sortable = { + init: function(element, valueAccessor, allBindingsAccessor, data, context) { + var value = ko.utils.unwrapObservable(valueAccessor()), + templateOptions = prepareTemplateOptions(valueAccessor), + sortable = ko.bindingHandlers.sortable, + connectClass = value.connectClass || sortable.connectClass, + allowDrop = value.allowDrop === undefined ? sortable.allowDrop : value.allowDrop, + beforeMove = value.beforeMove || sortable.beforeMove, + afterMove = value.afterMove || sortable.afterMove, + options = value.options || sortable.options; + + //if allowDrop is an observable or a function, then execute it in a computed observable + if (ko.isObservable(allowDrop) || typeof allowDrop == "function") { + ko.computed({ + read: function() { + var value = ko.utils.unwrapObservable(allowDrop), + shouldAdd = typeof value == "function" ? value.call(this, templateOptions.foreach) : value; + ko.utils.toggleDomNodeCssClass(element, connectClass, shouldAdd); + }, + disposeWhenNodeIsRemoved: element + }, this); + } else { + ko.utils.toggleDomNodeCssClass(element, connectClass, allowDrop); + } + + //attach meta-data + $(element).data("ko_sortList", templateOptions.foreach); + $(element).sortable(ko.utils.extend(options, { + update: function(event, ui) { + var sourceParent, targetParent, targetIndex, arg, + item = ui.item.data("ko_sortItem"); + + if (item) { + //identify parents + sourceParent = ui.item.data("ko_parentList"); + targetParent = ui.item.parent().data("ko_sortList"); + targetIndex = ko.utils.arrayIndexOf(ui.item.parent().children(), ui.item[0]); + + if (beforeMove || afterMove) { + arg = { + item: item, + sourceParent: sourceParent, + sourceIndex: sourceParent.indexOf(item), + targetParent: targetParent, + targetIndex: targetIndex, + cancelDrop: false + }; + } + + if (beforeMove) { + beforeMove.call(this, arg, event, ui); + if (arg.cancelDrop) { + $(ui.sender).sortable('cancel'); + return; + } + } + + if (targetIndex >= 0) { + sourceParent.remove(item); + targetParent.splice(targetIndex, 0, item); + } + //rendering is handled by manipulating the observableArray; ignore dropped element + ui.item.remove(); + + //allow binding to accept a function to execute after moving the item + if (afterMove) { + afterMove.call(this, arg, event, ui); + } + } + }, + connectWith: "." + connectClass + })); + + //handle disposal + ko.utils.domNodeDisposal.addDisposeCallback(element, function() { + $(element).sortable("destroy"); + }); + + //we are wrapping the template binding + return ko.bindingHandlers.template.init(element, function() { return templateOptions; }, allBindingsAccessor, data, context); + }, + update: function(element, valueAccessor, allBindingsAccessor, data, context) { + var templateOptions = prepareTemplateOptions(valueAccessor); + + //call the actual template binding + ko.bindingHandlers.template.update(element, function() { return templateOptions; }, allBindingsAccessor, data, context); + }, + afterRender: function(elements, data) { + ko.utils.arrayForEach(elements, function(element) { + if (element.nodeType === 1) { + $(element).data("ko_sortItem", data); + $(element).data("ko_parentList", $(element).parent().data("ko_sortList")); + } + }); + }, + connectClass: 'ko_container', + allowDrop: true, + afterMove: null, + beforeMove: null, + options: {} +}; +})(ko, jQuery); \ No newline at end of file