diff --git a/product/ERP5Form/ListBox.py b/product/ERP5Form/ListBox.py index 609aaca3d2ffdf58692179344db39ac8b80d089b..7ad79c29275d91419c6377af31d015a0cd5464ba 100644 --- a/product/ERP5Form/ListBox.py +++ b/product/ERP5Form/ListBox.py @@ -34,6 +34,7 @@ from Products.Formulator import Widget, Validator from Products.Formulator.Field import ZMIField from Products.Formulator.Errors import FormValidationError, ValidationError from Selection import Selection, DomainSelection +from SelectionTool import createFolderMixInPageSelectionMethod from Products.ERP5Type.Utils import getPath from Products.ERP5Type.Document import newTempBase from Products.CMFCore.utils import getToolByName @@ -1944,6 +1945,9 @@ class ListBoxHTMLRendererLine(ListBoxRendererLine): html_list = [] + # Generate page selection methods based on the Listbox id + createFolderMixInPageSelectionMethod(field_id) + # Check is there is a validation error at the level of the listbox # as a whole. This will be required later to decide wherer to # display values from (ie. from the REQUEST or from the object) diff --git a/product/ERP5Form/SelectionTool.py b/product/ERP5Form/SelectionTool.py index 741734799891e99125ed04802b94d361bb847126..65ab5bfbd18b413bf829874691e0ee6db55afc47 100644 --- a/product/ERP5Form/SelectionTool.py +++ b/product/ERP5Form/SelectionTool.py @@ -1465,6 +1465,9 @@ from ZPublisher.mapply import mapply method_id_filter_list = [x for x in FolderMixIn.__dict__ if callable(getattr(FolderMixIn, x))] candidate_method_id_list = [x for x in SelectionTool.__dict__ if callable(getattr(SelectionTool, x)) and not x.startswith('_') and not x.endswith('__roles__') and x not in method_id_filter_list] +# Monkey patch FolderMixIn with SelectionTool methods +# kept here for compatibility with previous implementations +# of Listbox HTML renderer. See bellow new implementation for property_id in candidate_method_id_list: def portal_selection_wrapper(self, wrapper_property_id=property_id, *args, **kw): """ @@ -1480,3 +1483,50 @@ for property_id in candidate_method_id_list: security_property = getattr(SelectionTool, security_property_id, None) if security_property is not None: setattr(FolderMixIn, security_property_id, security_property) + +def createFolderMixInPageSelectionMethod(listbox_id): + """ + This method must be called by listbox at rendering time. + It dynamically creates methods on FolderMixIn in line + with the naming of the listbox field. Generated method + are able to convert request parameters in order to + mimic the API of a listbox with ID "listbox". This + approach was required for example to implement + multiple multi-page listboxes in view mode. It also + opens the way towards multiple editable listboxes in the same + page although this is something which we can not recommend. + """ + # Immediately return in the method already exists + test_method_id = "%s_nextPage" % listbox_id + if hasattr(FolderMixIn, test_method_id): + return + # Monkey patch FolderMixIn + for property_id in candidate_method_id_list: + def portal_selection_wrapper(self, wrapper_listbox_id=listbox_id, + wrapper_property_id=property_id, *args, **kw): + """ + Wrapper method for SelectionTool. + """ + portal_selection = getToolByName(self, 'portal_selections') + request = self.REQUEST + selection_name_property_id = "%s_list_selection_name" % listbox_id + listbox_uid_property_id = "%s_uid" % listbox_id + list_start_property_id = "%s_list_start" % listbox_id + # Rename request parameters + if request.has_key(selection_name_property_id): + request.form['list_selection_name'] = request[selection_name_property_id] + if request.has_key(listbox_uid_property_id): + request.form['listbox_uid'] = request[listbox_uid_property_id] + if request.has_key(list_start_property_id): + request.form['list_start'] = request[list_start_property_id] + # Call the wrapper + method = getattr(portal_selection, wrapper_property_id) + return mapply(method, positional=args, keyword=request, + context=self, bind=1) + new_property_id = "%s_%s" % (listbox_id, property_id) + setattr(FolderMixIn, new_property_id, portal_selection_wrapper) + security_property_id = '%s__roles__' % (property_id, ) + security_property = getattr(SelectionTool, security_property_id, None) + if security_property is not None: + new_security_property_id = '%s__roles__' % (new_property_id, ) + setattr(FolderMixIn, new_security_property_id, security_property) \ No newline at end of file diff --git a/product/ERP5Form/www/ListBox_asHTML.zpt b/product/ERP5Form/www/ListBox_asHTML.zpt index 5de590819d5b635ccc20c94600983dea4478b514..9eba51a4c84b4e52dbd2a5393415747779f8be24 100644 --- a/product/ERP5Form/www/ListBox_asHTML.zpt +++ b/product/ERP5Form/www/ListBox_asHTML.zpt @@ -22,6 +22,9 @@ "> <!-- ListBox starts here. --> <input type="hidden" name="list_selection_name" value="default" tal:attributes="value selection_name" /> + <input type="hidden" name="list_selection_name" value="default" + tal:attributes="value selection_name; + name string:${field_id}_list_selection_name" /> <input tal:condition="md5_string" type="hidden" name="md5_object_uid_list" value="checksum" tal:attributes="value md5_string" /> <tal:replace tal:content="nothing"> @@ -144,6 +147,7 @@ id="listbox_previous_page" type="image" src="1leftarrowv.png" title="Previous Page" name="previousPage:method" tal:attributes="id string:${field_id}_previous_page; + name string:${field_id}_previousPage:method; src string:${portal_url_string}/images/1leftarrowv.png" i18n:domain="ui" i18n:attributes="title" /> </td> @@ -151,7 +155,8 @@ <select id="listbox_page_selection" name="list_start" title="Change Page" size="1" tal:define="lines here/getMaxLineNumber" tal:attributes="id string:${field_id}_page_selection; - onChange string:submitAction(this.form, '${context_url}/setPage')" + name string:${field_id}_list_start; + onChange string:submitAction(this.form, '${context_url}/${field_id}_setPage')" i18n:domain="ui" i18n:attributes="title"> <option value="0" tal:repeat="p python: range(0, here.total_pages)" @@ -165,6 +170,7 @@ id="listbox_next_page" type="image" src="1rightarrowv.png" title="Next Page" name="nextPage:method" tal:attributes="id string:${field_id}_next_page; + name string:${field_id}_nextPage:method; src string:${portal_url_string}/images/1rightarrowv.png" i18n:domain="ui" i18n:attributes="title" /> </td> @@ -192,10 +198,12 @@ name="checkAll:method" value="1" src="checkall.png" alt="Check All" title="Check All" tal:attributes="id string:${field_id}_check_all; + name string:${field_id}_checkAll:method; src string:${portal_url_string}/images/checkall.png" i18n:domain="ui" i18n:attributes="title" /> <input id="listbox_uncheck_all" type="image" name="uncheckAll:method" value="1" src="%(portal_url_string)s/images/decheckall.png" style="border: 0" alt="Uncheck All" title="Uncheck All" tal:attributes="id string:${field_id}_uncheck_all; + name string:${field_id}_uncheckAll:method; src string:${portal_url_string}/images/decheckall.png" i18n:domain="ui" i18n:attributes="title" /> </td>