Index: main/waeup.ikoba/trunk/src/waeup/ikoba/widgets/orderedSelectionList.pt
===================================================================
--- main/waeup.ikoba/trunk/src/waeup/ikoba/widgets/orderedSelectionList.pt	(revision 12506)
+++ main/waeup.ikoba/trunk/src/waeup/ikoba/widgets/orderedSelectionList.pt	(revision 12506)
@@ -0,0 +1,198 @@
+<script type="text/javascript">
+
+function moveItems(from, to)
+  {
+  // shortcuts for selection fields
+  var src = document.getElementById(from);
+  var tgt = document.getElementById(to);
+
+  if (src.selectedIndex == -1) selectionError();
+  else
+    {
+    // iterate over all selected items
+    // --> attribute "selectedIndex" doesn't support multiple selection.
+    // Anyway, it works here, as a moved item isn't selected anymore,
+    // thus "selectedIndex" indicating the "next" selected item :)
+    while (src.selectedIndex > -1)
+      if (src.options[src.selectedIndex].selected)
+        {
+        // create a new virtal object with values of item to copy
+        temp = new Option(src.options[src.selectedIndex].text,
+                      src.options[src.selectedIndex].value);
+        // append virtual object to targe
+        tgt.options[tgt.length] = temp;
+        // want to select newly created item
+        temp.selected = true;
+        // delete moved item in source
+        src.options[src.selectedIndex] = null;
+      }
+    }
+  }
+
+// move item from "from" selection to "to" selection
+function from2to(name)
+  {
+  moveItems(name+".from", name+".to");
+  copyDataForSubmit(name);
+  }
+
+// move item from "to" selection back to "from" selection
+function to2from(name)
+  {
+  moveItems(name+".to", name+".from");
+  copyDataForSubmit(name);
+  }
+
+function swapFields(a, b)
+  {
+  // swap text
+  var temp = a.text;
+  a.text = b.text;
+  b.text = temp;
+  // swap value
+  temp = a.value;
+  a.value = b.value;
+  b.value = temp;
+  // swap selection
+  temp = a.selected;
+  a.selected = b.selected;
+  b.selected = temp;
+  }
+
+// move selected item in "to" selection one up
+function moveUp(name)
+  {
+  // shortcuts for selection field
+  var toSel = document.getElementById(name+".to");
+
+  if (toSel.selectedIndex == -1)
+      selectionError();
+  else if (toSel.options[0].selected)
+      alert("Cannot move further up!");
+  else for (var i = 0; toSel.length > i; i++)
+    if (toSel.options[i].selected)
+      {
+      swapFields(toSel.options[i-1], toSel.options[i]);
+      copyDataForSubmit(name);
+      }
+  }
+
+// move selected item in "to" selection one down
+function moveDown(name)
+  {
+    // shortcuts for selection field
+    var toSel = document.getElementById(name+".to");
+
+    if (toSel.selectedIndex == -1) {
+        selectionError();
+    } else if (toSel.options[toSel.length-1].selected) {
+        alert("Cannot move further down!");
+    } else {
+      for (var i = toSel.length-1; i >= 0; i--) {
+        if (toSel.options[i].selected) {
+          swapFields(toSel.options[i+1], toSel.options[i]);
+        }
+      }
+      copyDataForSubmit(name);
+    }
+  }
+
+// copy each item of "toSel" into one hidden input field
+function copyDataForSubmit(name)
+  {
+  // shortcuts for selection field and hidden data field
+  var toSel = document.getElementById(name+".to");
+  var toDataContainer = document.getElementById(name+".toDataContainer");
+
+  // delete all child nodes (--> complete content) of "toDataContainer" span
+  while (toDataContainer.hasChildNodes())
+      toDataContainer.removeChild(toDataContainer.firstChild);
+
+  // create new hidden input fields - one for each selection item of
+  // "to" selection
+  for (var i = 0; toSel.options.length > i; i++)
+    {
+    // create virtual node with suitable attributes
+    var newNode = document.createElement("input");
+    var newAttr = document.createAttribute("name");
+    newAttr.nodeValue = name;
+    newNode.setAttributeNode(newAttr);
+
+    newAttr = document.createAttribute("type");
+    newAttr.nodeValue = "hidden";
+    newNode.setAttributeNode(newAttr);
+
+    newAttr = document.createAttribute("value");
+    newAttr.nodeValue = toSel.options[i].value;
+    newNode.setAttributeNode(newAttr);
+
+    // actually append virtual node to DOM tree
+    toDataContainer.appendChild(newNode);
+    }
+  }
+
+// error message for missing selection
+function selectionError()
+  {alert("Must select something!")}
+
+</script>
+
+<table border="0" class="ordered-selection-field">
+  <tr>
+    <td>
+      <select id="from" name="from" size="5" multiple=""
+          tal:attributes="name string:${view/name}.from;
+                          id string:${view/name}.from;
+                          size view/size"
+                          >
+        <option tal:repeat="entry view/choices"
+                tal:attributes="value entry/value"
+                tal:content="entry/text" i18n:translate=""/>
+      </select>
+    </td>
+    <td>
+      <button name="from2toButton" type="button" value=" -&gt;"
+          onclick="javascript:from2to()"
+          tal:attributes="onClick string:javascript:from2to('${view/name}')"
+          >&nbsp;-&gt;</button>
+      <br />
+      <button name="to2fromButton" type="button" value="&lt;- "
+          onclick="javascript:to2from()"
+          tal:attributes="onClick string:javascript:to2from('${view/name}')"
+          >&lt;-&nbsp;</button>
+    </td>
+    <td>
+      <select id="to" name="to" size="5" multiple=""
+          tal:attributes="name string:${view/name}.to;
+                          id string:${view/name}.to;
+                          size view/size">
+        <option tal:repeat="entry view/selected"
+                tal:attributes="value entry/value"
+                tal:content="entry/text" i18n:translate=""/>
+      </select>
+      <input name="foo-empty-marker" type="hidden"
+        tal:attributes="name string:${view/name}-empty-marker"/>
+      <span id="toDataContainer"
+            tal:attributes="id string:${view/name}.toDataContainer">
+        <script type="text/javascript" tal:content="string:
+          copyDataForSubmit('${view/name}');">
+          // initial copying of field "field.to" --> "field"
+          copyDataForSubmit("<i tal:replace="${view/name}"/>");
+        </script>
+      </span>
+    </td>
+    <td>
+      <button
+          name="upButton" type="button" value="^"
+          onclick="javascript:moveUp()"
+          tal:attributes="onClick string:javascript:moveUp('${view/name}')"
+          >^</button>
+      <br />
+      <button
+          name="downButton" type="button" value="v"
+          onclick="javascript:moveDown()"
+          tal:attributes="onClick string:javascript:moveDown('${view/name}')"
+          >v</button>
+    </td>
+  </tr>
+</table>
Index: main/waeup.ikoba/trunk/src/waeup/ikoba/widgets/overrides.zcml
===================================================================
--- main/waeup.ikoba/trunk/src/waeup/ikoba/widgets/overrides.zcml	(revision 12505)
+++ main/waeup.ikoba/trunk/src/waeup/ikoba/widgets/overrides.zcml	(revision 12506)
@@ -53,3 +53,13 @@
       />      
 
+  <!-- Register IkobaSourceOrderedMultiSelectWidget for IterableSource -->
+  <adapter
+      for="zope.schema.interfaces.IList
+           zope.schema.interfaces.IIterableSource
+           zope.publisher.interfaces.browser.IBrowserRequest"
+      provides="zope.formlib.interfaces.ISimpleInputWidget"
+      factory="waeup.ikoba.widgets.source.IkobaSourceOrderedMultiSelectWidget"
+      permission="zope.Public"
+      />
+
 </configure>
Index: main/waeup.ikoba/trunk/src/waeup/ikoba/widgets/source.py
===================================================================
--- main/waeup.ikoba/trunk/src/waeup/ikoba/widgets/source.py	(revision 12506)
+++ main/waeup.ikoba/trunk/src/waeup/ikoba/widgets/source.py	(revision 12506)
@@ -0,0 +1,31 @@
+## $Id$
+##
+## Copyright (C) 2015 Uli Fouquet & Henrik Bettermann
+## This program is free software; you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published by
+## the Free Software Foundation; either version 2 of the License, or
+## (at your option) any later version.
+##
+## This program is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+## GNU General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with this program; if not, write to the Free Software
+## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+##
+"""Improved source widgets.
+
+"""
+
+from zope.browserpage import ViewPageTemplateFile
+from zope.formlib.source import SourceOrderedMultiSelectWidget
+
+class IkobaSourceOrderedMultiSelectWidget(SourceOrderedMultiSelectWidget):
+    """A multi-selection widget with ordering support."""
+
+    template = ViewPageTemplateFile('orderedSelectionList.pt')
+
+    def __call__(self):
+        return self.template()
