diff --git a/fields/ref.py b/fields/ref.py index 7dcb8b0..07ebfa6 100644 --- a/fields/ref.py +++ b/fields/ref.py @@ -241,7 +241,7 @@ class Ref(Field): + onclick=":'toggleAllCbs(%s)' % q(ajaxHookId)"/> @@ -272,7 +272,7 @@ class Ref(Field): + value=":tiedUid" onclick="toggleCb(this)"/> @@ -286,7 +286,7 @@ class Ref(Field): ''') # PX that displays the list of objects the user may select to insert into a @@ -608,7 +608,10 @@ class Ref(Field): # NOTE that when a method is defined in field "masterValue" (see parent # class "Field"), it will be used instead of select (or sselect below). self.select = select - if isinstance(select, Search): self.select.name = '_field_' + if isinstance(select, Search): + select.name = '_field_' + select.checkboxes = True + select.checkboxesDefault = False # If you want to specify, for the search screen, a list of objects that # is different from the one produced by self.select, define an # alternative method in field "sselect" below. @@ -1145,7 +1148,7 @@ class Ref(Field): and may hold "unchecked" (initial semantics) or "checked" (inverted semantics). Inverting semantics allows to keep the array small even when checking/unchecking all checkboxes. - + The mentioned JS arrays and variables are stored as attributes of the DOM node representing this field.''' # The initial semantics depends on the checkboxes default value. diff --git a/fields/search.py b/fields/search.py index e602224..4a4f9f0 100644 --- a/fields/search.py +++ b/fields/search.py @@ -26,7 +26,8 @@ class Search: '''Used for specifying a search for a given class.''' def __init__(self, name, group=None, sortBy='', sortOrder='asc', limit=None, default=False, colspan=1, translated=None, show=True, - translatedDescr=None, **fields): + translatedDescr=None, checkboxes=False, checkboxesDefault=True, + **fields): self.name = name # Searches may be visually grouped in the portlet. self.group = Group.get(group) @@ -46,6 +47,10 @@ class Search: # In the dict below, keys are indexed field names or names of standard # indexes, and values are search values. self.fields = fields + # Do we need to display checkboxes for every object of the query result? + self.checkboxes = checkboxes + # Default value for checkboxes + self.checkboxesDefault = checkboxesDefault @staticmethod def getIndexName(fieldName, usage='search'): @@ -140,6 +145,14 @@ class Search: return gutils.callMethod(tool, self.show, klass=klass) return self.show + def getCbJsInit(self, hookId): + '''Returns the code that creates JS data structures for storing the + status of checkboxes for every result of this search.''' + default = self.checkboxesDefault and 'unchecked' or 'checked' + return '''var node=document.getElementById('%s'); + node['_appy_objs_cbs'] = {}; + node['_appy_objs_sem'] = '%s';''' % (hookId, default) + class UiSearch: '''Instances of this class are generated on-the-fly for manipulating a Search from the User Interface.''' diff --git a/gen/ui/appy.js b/gen/ui/appy.js index f09abde..308d0bf 100644 --- a/gen/ui/appy.js +++ b/gen/ui/appy.js @@ -224,7 +224,8 @@ function askQueryResult(hookId, objectUrl, className, searchName, popup, params['filterValue'] = filterWidget.value; } } - askAjaxChunk(hookId, 'GET', objectUrl, 'pxQueryResult', params); + askAjaxChunk(hookId, 'GET', objectUrl, 'pxQueryResult', params, null, + evalInnerScripts); } function askObjectHistory(hookId, objectUrl, maxPerPage, startNumber) { @@ -316,7 +317,7 @@ function _rsplit(s, delimiter, limit) { } // (Un)checks a checkbox corresponding to a linked object. -function toggleRefCb(checkbox) { +function toggleCb(checkbox) { var name = checkbox.getAttribute('name'); var elems = _rsplit(name, '_', 3); // Get the DOM node corresponding to the Ref field. @@ -336,8 +337,8 @@ function toggleRefCb(checkbox) { } } -// Initialise checkboxes of a Ref field. -function initRefCbs(id) { +// Initialise checkboxes of a Ref field or Search. +function initCbs(id) { var elems = _rsplit(id, '_', 3); // Get the DOM node corresponding to the Ref field. var node = document.getElementById(elems[0] + '_' + elems[1]); @@ -354,8 +355,8 @@ function initRefCbs(id) { } } -// Toggle all checkboxes of a Ref field. -function toggleAllRefCbs(id) { +// Toggle all checkboxes of a Ref field or Search. +function toggleAllCbs(id) { var elems = _rsplit(id, '_', 3); // Get the DOM node corresponding to the Ref field. var node = document.getElementById(elems[0] + '_' + elems[1]); @@ -367,7 +368,7 @@ function toggleAllRefCbs(id) { if (node[semAttr] == 'unchecked') node[semAttr] = 'checked'; else node[semAttr] = 'unchecked'; // Update the visible checkboxes - initRefCbs(id); + initCbs(id); } // Shows/hides a dropdown menu diff --git a/gen/wrappers/ToolWrapper.py b/gen/wrappers/ToolWrapper.py index d888295..80a8077 100644 --- a/gen/wrappers/ToolWrapper.py +++ b/gen/wrappers/ToolWrapper.py @@ -361,30 +361,47 @@ class ToolWrapper(AbstractWrapper): # Show query results as a list. pxQueryResultList = Px(''' - - - - - + +
- ::ztool.truncateText(_(field.labelId)) - :tool.pxSortAndFilter:tool.pxShowDetails -
+ + + + + - - + + - -
+ ::ztool.truncateText(_(field.labelId)) + :tool.pxSortAndFilter:tool.pxShowDetails + + +
:tool.pxQueryField
''') + + + + + + + + ''') # Show query results as a grid. pxQueryResultGrid = Px(''' @@ -405,9 +422,12 @@ class ToolWrapper(AbstractWrapper): # Show paginated query results as a list or grid. pxQueryResult = Px(''' -
+ target=ztool.getLinksTargetInfo(ztool.getAppyClass(className))" + id=":ajaxHookId"> @@ -492,10 +510,16 @@ class ToolWrapper(AbstractWrapper):
''') pxQuery = Px(''' - - :tool.pxPagePrologue:tool.pxQueryResult - ''', template=AbstractWrapper.pxTemplate, hook='content') +
+ + :tool.pxPagePrologue:tool.pxQueryResult +
''', template=AbstractWrapper.pxTemplate, hook='content') pxSearch = Px('''