diff --git a/gen/__init__.py b/gen/__init__.py
index d7040f6..d9d7146 100644
--- a/gen/__init__.py
+++ b/gen/__init__.py
@@ -22,6 +22,13 @@ validatorTypes = (types.FunctionType, types.UnboundMethodType,
emptyTuple = ()
labelTypes = ('label', 'descr', 'help')
+def initMasterValue(v):
+ '''Standardizes p_v as a list.'''
+ if not v: res = []
+ elif type(v) not in sequenceTypes: res = [v]
+ else: res = v
+ return res
+
# Descriptor classes used for refining descriptions of elements in types
# (pages, groups,...) ----------------------------------------------------------
class Page:
@@ -153,26 +160,10 @@ class Group:
# Header labels will be used as labels for the tabs.
self.hasHeaders = True
self.css_class = css_class
- self.master = None
- self.masterValue = None
- if master:
- self._addMaster(master, masterValue)
- self.label = label # See similar attr of Type class.
-
- def _addMaster(self, master, masterValue):
- '''Specifies this group being a slave of another field: we will add css
- classes allowing to show/hide, in Javascript, its widget according
- to master value.'''
self.master = master
- self.masterValue = masterValue
- classes = 'slave_%s' % self.master.id
- if type(self.masterValue) not in sequenceTypes:
- masterValues = [self.masterValue]
- else:
- masterValues = self.masterValue
- for masterValue in masterValues:
- classes += ' slaveValue_%s_%s' % (self.master.id, masterValue)
- self.css_class += ' ' + classes
+ self.masterValue = initMasterValue(masterValue)
+ if master: master.slaves.append(self)
+ self.label = label # See similar attr of Type class.
def _setColumns(self):
'''Standardizes field "columns" as a list of Column instances. Indeed,
@@ -440,17 +431,14 @@ class Type:
# If the widget is in a group with multiple columns, the following
# attribute specifies on how many columns to span the widget.
self.colspan = colspan
+ # The list of slaves of this field, if it is a master
+ self.slaves = []
# The behaviour of this field may depend on another, "master" field
self.master = master
- self.slaves = [] # The list of slaves of this field, if it is a master
- # Every HTML input field corresponding to a master must get some
- # CSS classes for controlling its slaves.
- self.master_css = ''
if master:
self.master.slaves.append(self)
- self.master.master_css = 'appyMaster master_%s' % self.master.id
# When master has some value(s), there is impact on this field.
- self.masterValue = masterValue
+ self.masterValue = initMasterValue(masterValue)
# If a field must retain attention in a particular way, set focus=True.
# It will be rendered in a special way.
self.focus = focus
@@ -494,7 +482,8 @@ class Type:
# Recompute the ID (and derived attributes) that may have changed if
# we are in debug mode (because we recreate new Type instances).
self.id = id(self)
- if self.slaves: self.master_css = 'appyMaster master_%s' % self.id
+ # Remember master name on every slave
+ for slave in self.slaves: slave.masterName = name
# Determine ids of i18n labels for this field
labelName = name
trPrefix = None
@@ -591,13 +580,10 @@ class Type:
master, masterValue = masterData
reqValue = master.getRequestValue(obj.REQUEST)
reqValue = master.getStorableValue(reqValue)
- # Manage the fact that values can be lists or single values
- multiMaster = type(masterValue) in sequenceTypes
- multiReq = type(reqValue) in sequenceTypes
- if not multiMaster and not multiReq: return reqValue == masterValue
- elif multiMaster and not multiReq: return reqValue in masterValue
- elif not multiMaster and multiReq: return masterValue in reqValue
- else: # multiMaster and multiReq
+ # reqValue can be a list or not
+ if type(reqValue) not in sequenceTypes:
+ return reqValue in masterValue
+ else:
for m in masterValue:
for r in reqValue:
if m == r: return True
@@ -674,19 +660,6 @@ class Type:
layouts['cell'] = Table(other=layouts['view'], derivedType='cell')
# Put the required CSS classes in the layouts
layouts['cell'].addCssClasses('noStyle')
- if self.master:
- # This type has a master (so is a slave): we add css classes
- # allowing to show/hide, in Javascript, its widget according to
- # master value.
- classes = 'slave_%s' % self.master.id
- if type(self.masterValue) not in sequenceTypes:
- masterValues = [self.masterValue]
- else:
- masterValues = self.masterValue
- for masterValue in masterValues:
- classes += ' slaveValue_%s_%s' % (self.master.id, masterValue)
- layouts['view'].addCssClasses(classes)
- layouts['edit'].addCssClasses(classes)
if self.focus:
# We need to make it flashy
layouts['view'].addCssClasses('appyFocus')
diff --git a/gen/plone25/mixins/ToolMixin.py b/gen/plone25/mixins/ToolMixin.py
index 39ffed1..cfc4b2d 100644
--- a/gen/plone25/mixins/ToolMixin.py
+++ b/gen/plone25/mixins/ToolMixin.py
@@ -1,5 +1,5 @@
# ------------------------------------------------------------------------------
-import re, os, os.path, time, Cookie, types
+import re, os, os.path, time, types
from appy.shared import mimeTypes
from appy.shared.utils import getOsTempFolder
import appy.gen
@@ -84,7 +84,6 @@ class ToolMixin(BaseMixin):
'''Returns the (translated) names of fields of p_contentType.'''
res = []
for appyType in self.getAllAppyTypes(className=contentType):
- if appyType.name == 'title': continue # Will be included by default.
res.append((appyType.name, self.translate(appyType.labelId)))
# Add object state
res.append(('state', self.translate('workflow_state')))
@@ -611,13 +610,6 @@ class ToolMixin(BaseMixin):
res.append(dSearch)
return res
- def getCookieValue(self, cookieId, default=''):
- '''Server-side code for getting the value of a cookie entry.'''
- cookie = Cookie.SimpleCookie(self.REQUEST['HTTP_COOKIE'])
- cookieValue = cookie.get(cookieId)
- if cookieValue: return cookieValue.value
- return default
-
def getQueryUrl(self, contentType, searchName, startNumber=None):
'''This method creates the URL that allows to perform a (non-Ajax)
request for getting queried objects from a search named p_searchName
diff --git a/gen/plone25/model.py b/gen/plone25/model.py
index c37e05b..4acd667 100644
--- a/gen/plone25/model.py
+++ b/gen/plone25/model.py
@@ -14,9 +14,9 @@ class Protos:
protos = {}
# List of attributes that can't be given to a Type constructor
notInit = ('id', 'type', 'pythonType', 'slaves', 'isSelect', 'hasLabel',
- 'hasDescr', 'hasHelp', 'master_css', 'required', 'filterable',
- 'validable', 'backd', 'isBack', 'sync', 'pageName',
- 'shownInfoWidths')
+ 'hasDescr', 'hasHelp', 'required', 'filterable', 'validable',
+ 'backd', 'isBack', 'sync', 'pageName', 'shownInfoWidths',
+ 'masterName')
@classmethod
def get(self, appyType):
'''Returns a prototype instance for p_appyType.'''
diff --git a/gen/plone25/skin/appy.css b/gen/plone25/skin/appy.css
index 7d4edb3..e02e318 100644
--- a/gen/plone25/skin/appy.css
+++ b/gen/plone25/skin/appy.css
@@ -8,18 +8,26 @@ table { font-size: 100%; border-spacing: 0px; border-collapse:collapse;}
form { margin: 0; padding: 0;}
p { margin: 0;}
acronym {cursor: help;}
-input { border: 1px solid #cccccc; background-color: #f8f8f8;
- font-family: Lucida,Helvetica,Arial,sans-serif; margin-bottom: 1px}
-input[type=image] { border-width: 0px; background: none; }
-input[type=button] { cursor: pointer; }
+input[type=image] { border: 0; background: none; }
+input[type=checkbox] { border: 0; background: none; cursor: pointer;}
+input[type=button] { border: 1px solid #cccccc; background-color: #f8f8f8;
+ cursor: pointer;}
+input[type=submit] { border: 1px solid #cccccc; background-color: #f8f8f8;
+ cursor: pointer; }
+input[type=text] { border: 1px solid #cccccc; background-color: #f8f8f8;
+ font-family: Lucida,Helvetica,Arial,sans-serif;
+ margin-bottom: 1px}
+select { border: 1px solid #cccccc; background-color: #f8f8f8;}
+
textarea { width: 99%; font: 100% Lucida,Helvetica,Arial,sans-serif;
border: 1px solid #a79e9e; background-color: #f8f8f8;}
label { font-weight: 600; font-style: italic; line-height: 1.4em;}
-legend { padding-bottom: 2px; padding-right: 3px;}
+legend { padding-bottom: 2px; padding-right: 3px; color: black;}
ul { line-height: 1.2em; margin: 0 0 0.2em 0.6em; padding: 0;
list-style: none outside none;}
li { margin: 0; background-image: url("skyn/li.gif"); padding-left: 10px;
background-repeat: no-repeat; background-position: 0 4px;}
+img {border: 0;}
.main { width: 900px; background-color: white; box-shadow: 3px 3px 3px #A9A9A9;
border-style: solid; border-width: 1px; border-color: grey; }
diff --git a/gen/plone25/skin/appy.js b/gen/plone25/skin/appy.js
index 2a04f9a..5ad6094 100644
--- a/gen/plone25/skin/appy.js
+++ b/gen/plone25/skin/appy.js
@@ -177,8 +177,8 @@ function askRefField(hookId, objectUrl, fieldName, innerRef, startNumber,
action, actionParams){
// Sends an Ajax request for getting the content of a reference field.
var startKey = hookId + '_startNumber';
- var params = {'fieldName': fieldName, 'innerRef': innerRef, };
- params[startKey] = startNumber;
+ var params = {'fieldName': fieldName, 'innerRef': innerRef };
+ params[startKey] = startNumber;
if (action) params['action'] = action;
if (actionParams) {
for (key in actionParams) { params[key] = actionParams[key]; };
@@ -201,70 +201,94 @@ function toggleCheckbox(visibleCheckbox, hiddenBoolean) {
}
// Functions used for master/slave relationships between widgets
-function getMasterValue(widget) {
- // Returns an array of selected options in a select widget
- res = new Array();
- if (widget.type == 'checkbox') {
- var mv = widget.checked + '';
- mv = mv.charAt(0).toUpperCase() + mv.substr(1);
- res.push(mv);
+function getSlaveInfo(slave, infoType) {
+ // Returns the appropriate info about slavery, depending on p_infoType.
+ cssClasses = slave.className.split(' ');
+ // Find the CSS class containing master-related info.
+ for (var j=0; j < cssClasses.length; j++) {
+ if (cssClasses[j].indexOf('slave_') == 0) {
+ // Extract, from this CSS class, master name or master values.
+ masterInfo = cssClasses[j].split('_');
+ if (infoType == 'masterName') return masterInfo[1];
+ else return masterInfo.slice(2); // Master values
+ }
+ }
+}
+
+function getMasterValues(master) {
+ // Returns the list of values that p_master currently has.
+ if (master.tagName == 'SPAN') {
+ res = master.attributes['value'].value;
+ if ((res[0] == '(') || (res[0] == '[')) {
+ // There are multiple values, split it
+ values = res.substring(1, res.length-1).split(',');
+ res = [];
+ for (var i=0; i < values.length; i++){
+ v = values[i].replace(' ', '');
+ res.push(v.substring(1, v.length-1));
+ }
+ }
+ else res = [res]; // A single value
+ }
+ else if (master.type == 'checkbox') {
+ res = master.checked + '';
+ res = res.charAt(0).toUpperCase() + res.substr(1);
+ res = [res];
}
else { // SELECT widget
- for (var i=0; i < widget.options.length; i++) {
- if (widget.options[i].selected) res.push(widget.options[i].value);
+ res = [];
+ for (var i=0; i < master.options.length; i++) {
+ if (master.options[i].selected) res.push(master.options[i].value);
}
}
return res;
}
-function updateSlaves(masterValues, appyTypeId) {
- // Given the value(s) selected in a master field, this function updates the
- // state of all corresponding slaves.
- var slaves = cssQuery('table.slave_' + appyTypeId);
- for (var i=0; i< slaves.length; i++){
- slaves[i].style.display = "none";
- }
- for (var i=0; i < masterValues.length; i++) {
- var activeSlaves = cssQuery('table.slaveValue_' + appyTypeId + '_' + masterValues[i]);
- for (var j=0; j < activeSlaves.length; j++){
- activeSlaves[j].style.display = "";
+function getSlaves(master) {
+ // Gets all the slaves of master.
+ allSlaves = document.getElementsByName('slave');
+ res = [];
+ slavePrefix = 'slave_' + master.attributes['name'].value + '_';
+ for (var i=0; i < slaves.length; i++){
+ cssClasses = slaves[i].className.split(' ');
+ for (var j=0; j < cssClasses.length; j++) {
+ if (cssClasses[j].indexOf(slavePrefix) == 0) {
+ res.push(slaves[i]);
+ break;
+ }
}
}
+ return res;
+}
+
+function updateSlaves(master) {
+ // Given the value(s) in a master field, we must update slave's visibility.
+ slaves = getSlaves(master);
+ masterValues = getMasterValues(master);
+ for (var i=0; i < slaves.length; i++) {
+ showSlave = false;
+ slaveryValues = getSlaveInfo(slaves[i], 'masterValues');
+ for (var j=0; j < slaveryValues.length; j++) {
+ for (var k=0; k< masterValues.length; k++) {
+ if (slaveryValues[j] == masterValues[k]) showSlave = true;
+ }
+ }
+ if (showSlave) slaves[i].style.display = "";
+ else slaves[i].style.display = "none";
+ }
}
function initSlaves() {
// When the current page is loaded, we must set the correct state for all
// slave fields.
- var masters = cssQuery('.appyMaster');
- for (var i=0; i < masters.length; i++) {
- var cssClasses = masters[i].className.split(' ');
- for (var j=0; j < cssClasses.length; j++) {
- if (cssClasses[j].indexOf('master_') == 0) {
- var appyId = cssClasses[j].split('_')[1];
- var masterValue = [];
- if (masters[i].nodeName == 'SPAN'){
- var idField = masters[i].id;
- if (idField == '') {
- masterValue.push(idField);
- }
- else {
- if ((idField[0] == '(') || (idField[0] == '[')) {
- // There are multiple values, split it
- var subValues = idField.substring(1, idField.length-1).split(',');
- for (var k=0; k < subValues.length; k++){
- var subValue = subValues[k].replace(' ','');
- masterValue.push(subValue.substring(1, subValue.length-1));
- }
- }
- else { masterValue.push(masters[i].id);
- }
- }
- }
- else { masterValue = getMasterValue(masters[i]);
- }
- updateSlaves(masterValue, appyId);
- }
- }
+ slaves = document.getElementsByName('slave');
+ walkedMasters = {}; // Remember the already walked masters.
+ for (var i=0; i < slaves.length; i++) {
+ masterName = getSlaveInfo(slaves[i], 'masterName');
+ if (masterName in walkedMasters) continue;
+ master = document.getElementById(masterName);
+ updateSlaves(master);
+ walkedMasters[masterName] = 'walked';
}
}
diff --git a/gen/plone25/skin/import.pt b/gen/plone25/skin/import.pt
index afff3f5..bb91d41 100644
--- a/gen/plone25/skin/import.pt
+++ b/gen/plone25/skin/import.pt
@@ -24,7 +24,7 @@
|
---|