joonis Logo

Auto generate server-side KSS rules in Zope

Outdated! Instead use the function generate_kss_rules of the Python server-side KSS library as an external method.

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 auto_generate 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) "auto_generate"
##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 "auto_generate(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

Can I
  help you?


Just drop me a line at
giraffe@joonis.de