A decided advantage of KSS is the fact that all the client-side logic can be shifted to the server-side. Nevertheless you have to create the KSS rule separately from the corresponding action script. But we can simplify that procedure.
Create the following Python Script with the id autoGenerate and two parameters: folder, recursive=True
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 | ## Script (Python) "autoGenerate"
##bind container=container
##bind context=context
##bind namespace=
##bind script=script
##bind subpath=traverse_subpath
##parameters=folder, recursive=True
##title=
##
kss = '/* %s */\n\n' % folder.title_or_id()
for id in folder.objectIds('Script (Python)'):
obj = folder[id]
title = obj.title
if title.find(':') == -1:
continue
event = title.split(':')[-1]
rule = '%s {\n' % title
rule = rule + '\taction-server: %s;\n' % id
rule = rule + '\t%s-kssUrl: "/%s";\n' % (id, obj.absolute_url(relative=True))
params = []
for param in obj.params().split(','):
if len(params) and param.find('=') < 0:
params[-1] = params[-1] + ',' + param
else:
params.append(param)
for param in params:
param = param.split('=', 1)
name = param[0].strip()
if name.startswith('*'):
continue
if len(param) == 1:
value = ''
else:
value = param[1].strip()
if value.startswith("'") or value.startswith('"'):
value = value[1:]
if value.endswith("'") or value.endswith('"'):
value = value[:-1]
value = value.strip()
if not value:
rule = '%s {\n' % title
rule = rule + '\taction-client: alert;\n'
rule = rule + '\talert-message: "Failed to automatically generate kss for server action %s";\n' % id
break
if name.startswith('evt_'):
rule = rule + '\tevt-%s-%s: %s;\n' % (event, name.replace('evt_', ''), value)
else:
rule = rule + '\t%s-%s: %s;\n' % (id, name, value)
rule = rule + '}\n\n'
kss = kss + rule
if recursive:
for id in folder.objectIds('Folder'):
kss = kss + script(folder[id], True)
return kss
|
Now create a folder named kss_actions where all your server-side action scripts live. For each action create a usual Python Script. We will misuse the title property for the css selector.
Your client-side KSS rules should be stored within a DTML Method where you add the following DTML tag:
<dtml-var "autoGenerate(kss_actions)">
As a result the corresponding KSS rule will be added automatically for each server-side script.
Example:
The following script ...
## Script (Python) "my_kss_action"
##bind container=container
##bind context=context
##bind namespace=
##bind script=script
##bind subpath=traverse_subpath
##parameters=url='nodeAttr(href)', title='nodeAttr(title)', evt_preventdefault=True, evt_allowbubbling=True
##title=a.popup:click
##
# Here goes the logic and a KSS response will be returned
... will produce the following KSS rule:
/* kss_actions */
a.popup:click {
action-server: my_kss_action;
my_kss_action-kssUrl: "/path/to/kss_actions/my_kss_action";
my_kss_action-url: nodeAttr(href);
my_kss_action-title: nodeAttr(title);
evt-click-preventdefault: True;
evt-click-allowbubbling: True;
}
Error handling:
It is also useful to add a Python Script named standard_error_message to the kss_actions folder:
## Script (Python) "standard_error_message"
##bind container=container
##bind context=context
##bind namespace=
##bind script=script
##bind subpath=traverse_subpath
##parameters=**kwargs
##title=
##
error_type = kwargs.get('error_type', 'UnknownError')
error_value = kwargs.get('error_value', 'no error message given')
message = '%s: %s' % (error_type, error_value)
# Now you could return a KSS alert message