diff --git a/gen/__init__.py b/gen/__init__.py
index e84af8f..f7f3091 100644
--- a/gen/__init__.py
+++ b/gen/__init__.py
@@ -583,7 +583,6 @@ class Type:
else:
master, masterValue = masterData
reqValue = master.getRequestValue(obj.REQUEST)
- reqValue = master.getStorableValue(reqValue)
# reqValue can be a list or not
if type(reqValue) not in sequenceTypes:
return reqValue in masterValue
@@ -783,10 +782,21 @@ class Type:
return res
return value
- def getRequestValue(self, request):
- '''Gets the string (or list of strings if multi-valued)
- representation of this field as found in the p_request.'''
- return request.get(self.name, None)
+ def getRequestValue(self, request, requestName=None):
+ '''Gets a value for this field as carried in the request object. In the
+ simplest cases, the request value is a single value whose name in the
+ request is the name of the field.
+
+ Sometimes (ie: a Date: see the overriden method in the Date class),
+ several request values must be combined.
+
+ Sometimes (ie, a field which is a sub-field in a List), the name of
+ the request value(s) representing the field value do not correspond
+ to the field name (ie: the request name includes information about
+ the container field). In this case, p_requestName must be used for
+ searching into the request, instead of the field name (self.name).'''
+ name = requestName or self.name
+ return request.get(name, None)
def getStorableValue(self, value):
'''p_value is a valid value initially computed through calling
@@ -1474,11 +1484,12 @@ class Date(Type):
res += ' %s' % value.strftime('%H:%M')
return res
- def getRequestValue(self, request):
+ def getRequestValue(self, request, requestName=None):
+ name = requestName or self.name
# Manage the "date" part
value = ''
for part in self.dateParts:
- valuePart = request.get('%s_%s' % (self.name, part), None)
+ valuePart = request.get('%s_%s' % (name, part), None)
if not valuePart: return None
value += valuePart + '/'
value = value[:-1]
@@ -1486,7 +1497,7 @@ class Date(Type):
if self.format == self.WITH_HOUR:
value += ' '
for part in self.hourParts:
- valuePart = request.get('%s_%s' % (self.name, part), None)
+ valuePart = request.get('%s_%s' % (name, part), None)
if not valuePart: return None
value += valuePart + ':'
value = value[:-1]
@@ -1544,8 +1555,9 @@ class File(Type):
if not value: return value
return value._zopeFile
- def getRequestValue(self, request):
- return request.get('%s_file' % self.name)
+ def getRequestValue(self, request, requestName=None):
+ name = requestName or self.name
+ return request.get('%s_file' % name)
def getDefaultLayouts(self): return {'view':'l-f','edit':'lrv-f'}
@@ -2251,25 +2263,22 @@ class List(Type):
for n, field in self.fields:
if n == name: return field
- def getRequestValue(self, request):
+ def getRequestValue(self, request, requestName=None):
'''Concatenates the list from distinct form elements in the request.'''
- prefix = self.name + '*' + self.fields[0][0] + '*'
+ name = requestName or self.name # A List may be into another List (?)
+ prefix = name + '*' + self.fields[0][0] + '*'
res = {}
for key in request.keys():
if not key.startswith(prefix): continue
# I have found a row. Gets its index
row = Object()
+ if '_' in key: key = key[:key.index('_')]
rowIndex = int(key.split('*')[-1])
if rowIndex == -1: continue # Ignore the template row.
- for name, field in self.fields:
- keyName = '%s*%s*%s' % (self.name, name, rowIndex)
- if request.has_key(keyName):
- # Simulate the request as if it was for a single value
- request.set(field.name, request[keyName])
- v = field.getRequestValue(request)
- else:
- v = None
- setattr(row, name, v)
+ for subName, subField in self.fields:
+ keyName = '%s*%s*%s' % (name, subName, rowIndex)
+ v = subField.getRequestValue(request, requestName=keyName)
+ setattr(row, subName, v)
res[rowIndex] = row
# Produce a sorted list.
keys = res.keys()
@@ -2280,7 +2289,7 @@ class List(Type):
# instead of taking it from the specific request key. Indeed, specific
# request keys contain row indexes that may be wrong after row deletions
# by the user.
- request.set(self.name, res)
+ request.set(name, res)
return res
def getStorableValue(self, value):
@@ -2301,6 +2310,22 @@ class List(Type):
if i >= len(outerValue): return ''
return getattr(outerValue[i], name, '')
+ def getCss(self, layoutType):
+ '''Gets the CSS required by sub-fields if any.'''
+ res = ()
+ for name, field in self.fields:
+ css = field.getCss(layoutType)
+ if css: res += css
+ return res
+
+ def getJs(self, layoutType):
+ '''Gets the JS required by sub-fields if any.'''
+ res = ()
+ for name, field in self.fields:
+ js = field.getJs(layoutType)
+ if js: res += js
+ return res
+
# Workflow-specific types and default workflows --------------------------------
appyToZopePermissions = {
'read': ('View', 'Access contents information'),
diff --git a/gen/mixins/ToolMixin.py b/gen/mixins/ToolMixin.py
index 7c964cb..db85a04 100644
--- a/gen/mixins/ToolMixin.py
+++ b/gen/mixins/ToolMixin.py
@@ -121,7 +121,7 @@ class ToolMixin(BaseMixin):
p_code.'''
return languages.get(code)[2]
- def getCssJs(self):
+ def getGlobalCssJs(self):
'''Returns the list of CSS and JS files to include in the main template.
The method ensures that appy.css and appy.js come first.'''
names = self.getPhysicalRoot().ui.objectIds('File')
diff --git a/gen/mixins/__init__.py b/gen/mixins/__init__.py
index a199253..9442dd8 100644
--- a/gen/mixins/__init__.py
+++ b/gen/mixins/__init__.py
@@ -562,7 +562,10 @@ class BaseMixin:
field is supposed to belong to self's class.'''
isInnerType = '*' in name # An inner type lies within a List type.
subName = None
- if isInnerType: name, subName, i = name.split('*')
+ if isInnerType:
+ elems = name.split('*')
+ if len(elems) == 2: name, subName = elems
+ else: name, subName, i = elems
if not className:
klass = self.__class__.wrapperClass
else:
@@ -614,10 +617,10 @@ class BaseMixin:
res.append(appyType)
return res
- def getCssAndJs(self, fields, layoutType):
+ def getCssJs(self, fields, layoutType):
'''Gets the list of Javascript and CSS files required by Appy types
p_fields when shown on p_layoutType.'''
- # lists css and js below are not sets, because order of Javascript
+ # Lists css and js below are not sets, because order of Javascript
# inclusion can be important, and this could be losed by using sets.
css = []
js = []
diff --git a/gen/ui/appy.css b/gen/ui/appy.css
index f7321bb..35907a3 100644
--- a/gen/ui/appy.css
+++ b/gen/ui/appy.css
@@ -12,18 +12,18 @@ acronym {cursor: help;}
input[type=image] { border: 0; background: none; }
input[type=checkbox] { border: 0; background: none; cursor: pointer;}
input[type=radio] { border: 0; background: none; cursor: pointer;}
-input[type=file] { border: 0px solid #cccccc;
+input[type=file] { border: 0px solid #D7DEE4;
background-color: #f8f8f8; cursor: pointer;}
-input[type=button] { border: 1px solid #cccccc;
+input[type=button] { border: 1px solid #D7DEE4;
background-color: #f8f8f8; cursor: pointer;}
-input[type=submit] { border: 1px solid #cccccc; background-color: #f8f8f8;
+input[type=submit] { border: 1px solid #D7DEE4; background-color: #f8f8f8;
cursor: pointer; }
-input[type=password] { border: 1px solid #cccccc; background-color: #f8f8f8;
+input[type=password] { border: 1px solid #D7DEE4; background-color: #f8f8f8;
font-family: Helvetica,Arial,sans-serif;}
-input[type=text] { border: 1px solid #cccccc; background-color: #f8f8f8;
+input[type=text] { border: 1px solid #D7DEE4; background-color: #f8f8f8;
font-family: Helvetica,Arial,sans-serif;
margin-bottom: 1px}
-select { border: 1px solid #cccccc; background-color: #f8f8f8;}
+select { border: 1px solid #D7DEE4; background-color: #f8f8f8;}
textarea { width: 99%; font: 100% Helvetica,Arial,sans-serif;
border: 1px solid #a79e9e; background-color: #f8f8f8;}
@@ -82,7 +82,7 @@ img {border: 0}
.section2 { font-size: 110%; font-style: italic; margin: 0.45em 0em 0.2em 0;
border-bottom: 2px solid grey; }
.section3 { font-size: 100%; font-style: italic; margin: 0.45em 0em 0.1em 0;
- background-color: #efeae8; text-align: center; color: grey; }
+ background-color: #F4F5F6; text-align: center; color: grey; }
.odd { background-color: white; }
.even { background-color: #F4F5F6; }
.summary {margin-bottom: 5px;}
diff --git a/gen/ui/appy.js b/gen/ui/appy.js
index 99fdd96..a1ca1ab 100644
--- a/gen/ui/appy.js
+++ b/gen/ui/appy.js
@@ -502,26 +502,58 @@ function updateRowNumber(row, rowIndex, action) {
with new p_rowIndex. If p_action is 'set', p_rowIndex becomes the new
index. If p_action is 'add', new index becomes:
existing index + p_rowIndex. */
- tagTypes = ['input', 'select'];
- currentIndex = -1;
+ var tagTypes = ['input', 'select', 'img'];
+ var currentIndex = -1;
for (var i=0; i < tagTypes.length; i++) {
- widgets = row.getElementsByTagName(tagTypes[i]);
+ var widgets = row.getElementsByTagName(tagTypes[i]);
for (var j=0; j < widgets.length; j++) {
- id = widgets[j].id;
- name = widgets[j].name;
+ var id = widgets[j].id;
+ if (!id) continue;
+ var name = widgets[j].name;
+ // Extract the suffix if there is one (ie, if the field is a Date part:
+ // _img, _day,...).
+ var iSuffix = id.lastIndexOf('_');
+ var idSuffix = '';
+ if (iSuffix != -1) {
+ idSuffix = id.substring(iSuffix);
+ id = id.substring(0, iSuffix);
+ }
+ var nSuffix = name.lastIndexOf('_');
+ var nameSuffix = '';
+ if (nSuffix != -1) {
+ nameSuffix = id.substring(nSuffix);
+ name = name.substring(0, nSuffix);
+ }
+ // Compute the current row index if not already done.
idNbIndex = id.lastIndexOf('*') + 1;
nameNbIndex = name.lastIndexOf('*') + 1;
- // Compute the current row index if not already done.
if (currentIndex == -1) {
currentIndex = parseInt(id.substring(idNbIndex));
}
// Compute the new values for attributes "id" and "name".
newId = id.substring(0, idNbIndex);
- newName = id.substring(0, nameNbIndex);
+ newName = name.substring(0, nameNbIndex);
newIndex = rowIndex;
if (action == 'add') newIndex = newIndex + currentIndex;
- widgets[j].id = newId + String(newIndex);
- widgets[j].name = newName + String(newIndex);
+ var oldId = widgets[j].id;
+ widgets[j].id = newId + String(newIndex) + idSuffix;
+ if (name) widgets[j].name = newName + String(newIndex) + nameSuffix;
+ /* In the case of an img that must show a calendar, update the script that
+ is triggered when clicking on it. */
+ if ((tagTypes[i] == 'img') && (idSuffix == '_img')) {
+ var scripts = row.getElementsByTagName('script');
+ for (var k=0; k < scripts.length; k++) {
+ var text = scripts[k].text;
+ if (text.indexOf(oldId) != -1) {
+ var oldIdField = oldId.substring(0, oldId.length-4);
+ var newIdField = widgets[j].id.substring(0, widgets[j].id.length-4);
+ text = text.replace(oldIdField, newIdField);
+ scripts[k].text = text.replace(oldId, widgets[j].id);
+ eval(scripts[k].text);
+ break;
+ }
+ }
+ }
}
}
}
@@ -530,9 +562,9 @@ function insertRow(tableId) {
table = document.getElementById(tableId);
newRow = table.rows[1].cloneNode(true);
newRow.style.display = 'table-row';
- // Within newRow, I must include in field names and ids the row number
- updateRowNumber(newRow, table.rows.length-3, 'set');
+ // Within newRow, incorporate the row number within field names and ids.
table.tBodies[0].appendChild(newRow);
+ updateRowNumber(newRow, table.rows.length-4, 'set');
}
function deleteRow(tableId, deleteImg) {
diff --git a/gen/ui/edit.pt b/gen/ui/edit.pt
index b5560d3..9d579bd 100644
--- a/gen/ui/edit.pt
+++ b/gen/ui/edit.pt
@@ -9,7 +9,7 @@
phaseInfo python: contextObj.getAppyPhases(currentOnly=True, layoutType=layoutType);
phase phaseInfo/name;
page request/page|python:'main';
- cssJs python: contextObj.getCssAndJs(contextObj.getAppyTypes(layoutType, page), layoutType);
+ cssJs python: contextObj.getCssJs(contextObj.getAppyTypes(layoutType, page), layoutType);
confirmMsg request/confirmMsg | nothing;"
tal:on-error="structure python: tool.manageError(error)">
diff --git a/gen/ui/search.pt b/gen/ui/search.pt
index 065eeab..9d91287 100644
--- a/gen/ui/search.pt
+++ b/gen/ui/search.pt
@@ -4,7 +4,7 @@
tal:define="className request/className;
refInfo request/ref|nothing;
searchInfo python: tool.getSearchInfo(className, refInfo);
- cssJs python: tool.getCssAndJs(searchInfo['fields'], 'edit')">
+ cssJs python: tool.getCssJs(searchInfo['fields'], 'edit')">