In this round, the objective is to add a feature in ordered folders
in CPS, that let the user drag elements and drop them within the same
page, to change the elements order.
This is quite simple, even though the javascript part gets a bit
longer and tougher to create than the previous rounds,
but more interesting because we are going to add server-side code
that can be reused later on in Zope 3.
Doing this feature in Zope 3, would involve coding some kind
of Ajax view that would know how to deal with the current context
(ie: the ordered folder) and a directive in the zcml, in order
to hook the view with a method associated to the current folder.
Thanks to Five, we can use this path within Zope 2.
The view which is quite simple, introduces a method that simply
gets the id of the element that is beeing dragged and the id of the
element that receives the drop. It returns the new order, so
the javascript side can play with the DOM to reorder the list:
from Products.Five import BrowserView
class AjaxFolderView(BrowserView):
def moveElement(self, from_id, to_id):
if (not from_id.startswith('draggable') or
not to_id.startswith('droppable')):
return ''
from_id = from_id[len('draggable'):]
to_id = to_id[len('droppable'):]
if from_id == to_id:
return ''
proxy_folder = self.context
to_position = proxy_folder.getObjectPosition(to_id)
proxy_folder.moveObjectToPosition(from_id, to_position)
return ':'.join([id for id in proxy_folder.objectIds()
if not id.startswith('.')])
This view derives from Five's BrowserView, in order to be able to hook
it in the zcml. The zcml just associates the IOrderedContainer interface:
<configure xmlns="http://namespaces.zope.org/zope"
xmlns:five="http://namespaces.zope.org/five"
xmlns:browser="http://namespaces.zope.org/browser"
xmlns:i18n="http://namespaces.zope.org/i18n"
i18n_domain="cpsdefault"
>
<browser:page
for="OFS.interfaces.IOrderedContainer"
name="ajaxMoveElement"
class=".browser.ajaxfolderview.AjaxFolderView"
attribute="moveElement"
permission="zope.Public"/> <!-- TODO: secure the method -->
</configure>
That's it ! The server-side infrastructure provides now a method in all ordered
folders that can be used asynchronously by any ajax toolkit.