[gen] Allow to show checkboxes for search results.

This commit is contained in:
Gaetan Delannay 2014-07-19 13:42:39 +02:00
parent b2a2aa5210
commit 792db32f27
4 changed files with 83 additions and 42 deletions

View file

@ -241,7 +241,7 @@ class Ref(Field):
<th if="checkboxes" class="cbCell">
<img src=":url('checkall')" class="clickable"
title=":_('check_uncheck')"
onclick=":'toggleAllRefCbs(%s)' % q(ajaxHookId)"/>
onclick=":'toggleAllCbs(%s)' % q(ajaxHookId)"/>
</th>
</tr>
<!-- Loop on every (tied or selectable) object. -->
@ -272,7 +272,7 @@ class Ref(Field):
</td>
<td if="checkboxes" class="cbCell">
<input if="mayView" type="checkbox" name=":ajaxHookId" checked="checked"
value=":tiedUid" onclick="toggleRefCb(this)"/>
value=":tiedUid" onclick="toggleCb(this)"/>
</td>
</tr>
</table>
@ -286,7 +286,7 @@ class Ref(Field):
<!-- Init checkboxes if present. -->
<script if="checkboxes"
type="text/javascript">:'initRefCbs(%s)' % q(ajaxHookId)
type="text/javascript">:'initCbs(%s)' % q(ajaxHookId)
</script>''')
# 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.

View file

@ -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.'''

View file

@ -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

View file

@ -361,7 +361,10 @@ class ToolWrapper(AbstractWrapper):
# Show query results as a list.
pxQueryResultList = Px('''
<table class="list" width="100%" var="showHeaders=showHeaders|True">
<x var="showHeaders=showHeaders|True;
checkboxes=uiSearch.search.checkboxes;
checkboxesId=rootHookId + '_objs'">
<table class="list" width="100%">
<!-- Headers, with filters and sort arrows -->
<tr if="showHeaders">
<th for="column in columns"
@ -372,6 +375,11 @@ class ToolWrapper(AbstractWrapper):
<x>::ztool.truncateText(_(field.labelId))</x>
<x>:tool.pxSortAndFilter</x><x>:tool.pxShowDetails</x>
</th>
<th if="checkboxes" class="cbCell">
<img src=":url('checkall')" class="clickable"
title=":_('check_uncheck')"
onclick=":'toggleAllCbs(%s)' % q(checkboxesId)"/>
</th>
</tr>
<!-- Results -->
@ -383,8 +391,17 @@ class ToolWrapper(AbstractWrapper):
var2="field=column.field" id=":'field_%s' % field.name"
width=":column.width"
align=":column.align">:tool.pxQueryField</td>
<!-- A checkbox if required -->
<td if="checkboxes" class="cbCell">
<input type="checkbox" name=":checkboxesId" checked="checked"
value=":zobj.id" onclick="toggleCb(this)"/>
</td>
</tr>
</table>''')
</table>
<!-- Init checkboxes if present. -->
<script if="checkboxes"
type="text/javascript">:'initCbs(%s)' % q(checkboxesId)
</script></x>''')
# 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('''
<div id="queryResult"
var="_=ztool.translate;
<div var="ajaxHookId='queryResult';
_=ztool.translate;
className=req['className'];
searchName=req.get('search', '');
rootHookId=rootHookId|'%s_search' % className;
uiSearch=uiSearch|ztool.getSearch(className,searchName,ui=True);
refInfo=ztool.getRefInfo();
refObject=refInfo[0];
refField=refInfo[1];
@ -415,8 +435,6 @@ class ToolWrapper(AbstractWrapper):
refField)) or '';
startNumber=req.get('startNumber', '0');
startNumber=int(startNumber);
searchName=req.get('search', '');
uiSearch=ztool.getSearch(className, searchName, ui=True);
sortKey=req.get('sortKey', '');
sortOrder=req.get('sortOrder', 'asc');
filterKey=req.get('filterKey', '');
@ -430,7 +448,6 @@ class ToolWrapper(AbstractWrapper):
totalNumber=queryResult.totalNumber;
batchSize=queryResult.batchSize;
batchNumber=len(zobjects);
ajaxHookId='queryResult';
navBaseCall='askQueryResult(%s,%s,%s,%s,%s,**v**)' % \
(q(ajaxHookId), q(ztool.absolute_url()), q(className), \
q(searchName),int(inPopup));
@ -440,7 +457,8 @@ class ToolWrapper(AbstractWrapper):
(ztool.absolute_url(), className, refUrlPart);
showSubTitles=req.get('showSubTitles', 'true') == 'true';
resultMode=ztool.getResultMode(className);
target=ztool.getLinksTargetInfo(ztool.getAppyClass(className))">
target=ztool.getLinksTargetInfo(ztool.getAppyClass(className))"
id=":ajaxHookId">
<x if="zobjects">
<!-- Display here POD templates if required. -->
@ -492,10 +510,16 @@ class ToolWrapper(AbstractWrapper):
</div>''')
pxQuery = Px('''
<x var="className=req['className']; searchName=req.get('search', '');
cssJs=None">
<x>:tool.pxPagePrologue</x><x>:tool.pxQueryResult</x>
</x>''', template=AbstractWrapper.pxTemplate, hook='content')
<div var="className=req['className'];
searchName=req.get('search', '');
uiSearch=ztool.getSearch(className, searchName, ui=True);
rootHookId='%s_search' % className;
cssJs=None"
id=":rootHookId">
<script type="text/javascript">:uiSearch.search.getCbJsInit(rootHookId)
</script>
<x if="not inPopup">:tool.pxPagePrologue</x><x>:tool.pxQueryResult</x>
</div>''', template=AbstractWrapper.pxTemplate, hook='content')
pxSearch = Px('''
<x var="className=req['className'];