root/trunk/yui/templatetags/yui.py @ 215

Revision 215, 6.0 kB (checked in by akaihola, 2 years ago)

[yui] Added the editor template tag.

  • Property svn:eol-style set to native
Line 
1#!/usr/bin/python
2# -*- encoding: utf-8 -*-
3
4from django import template
5from django.template import Context
6from django.template.loader import render_to_string
7
8register = template.Library()
9
10LOADER_URL = 'http://yui.yahooapis.com/2.5.1/build/' \
11             'yuiloader/yuiloader-beta-min.js'
12
13
14def make_script_tag(script, src):
15    if src:
16        src_attrib = ' src="%s"' % src
17    else:
18        src_attrib = ''
19    return '<script type="text/javascript"%s>%s</script>\n' % (
20        src_attrib, script)
21
22
23def script(script):
24    return make_script_tag(script, None)
25
26
27def script_src(src):
28    return make_script_tag('', src)
29
30
31def context_setdefault(context, varname, value):
32    if varname not in context:
33        context[varname] = value
34    return context[varname]
35
36
37@register.tag
38def YUI(parser, token):
39    bits = token.split_contents()[1:]
40    if len(bits) < 1:
41        raise template.TemplateSyntaxError, \
42              'YUI requires at least the command name as an argument'
43    cmd = bits.pop(0)
44
45    if cmd == 'loader':
46        if len(bits) > 2:
47            raise template.TemplateSyntaxError, \
48                  'YUI loader takes zero, one or two arguments'
49        return YUILoaderNode(*bits)
50
51    elif cmd == 'require':
52        nodelists_add_module = []
53        nodelist_on_success = parser.parse(('addModule', 'endYUI',))
54        while True:
55            token = parser.next_token()
56            if token.contents == 'addModule':
57                nodelists_add_module.append(
58                    parser.parse(('addModule', 'endYUI',)))
59            else:
60                break
61        return YUIRequireNode(bits, nodelist_on_success, nodelists_add_module)
62
63    elif cmd == 'alias':
64        aliases = [bit.split('=') for bit in bits]
65        return YUIAliasNode((varname, module) for varname, module in aliases)
66        # todo: tuple extraction error handling
67
68    elif cmd == 'onDOMReady':
69        if bits:
70            raise template.TemplateSyntaxError, \
71                  'YUI onDOMReady takes no arguments'
72        nodelist = parser.parse(('endYUI',))
73        parser.delete_first_token()
74        return YUIOnDomReadyNode(nodelist)
75
76    elif cmd == 'editor':
77        if len(bits) != 1:
78            raise template.TemplateSyntaxError, \
79                  'YUI editor takes exactly one argument'
80        return YUIEditorNode(bits[0])
81
82
83def init(url):
84    return ''.join((
85        script_src(url),
86        script('_DOMReady_funcs=[];'
87               'function _onDOMReady(f){_DOMReady_funcs.push(f);}')))
88
89ONDOMREADY = ('for(var i=0;i<_DOMReady_funcs.length;++i)'
90              '_DOMReady_funcs[i]();'
91              '_onDOMReady=function(f){f()};')
92
93
94class YUILoaderNode(template.Node):
95
96    def __init__(self, url=None, filter=None):
97        self.url = url and template.Variable(url)
98        self.filter = filter and template.Variable(filter)
99
100    def render(self, context):
101        config = context_setdefault(context, '_yui', {})
102        if self.filter is None:
103            config['filter'] = None
104        else:
105            config['filter'] = self.filter.resolve(context)
106        if self.url is None:
107            config['source'] = LOADER_URL
108        else:
109            config['source'] = self.url.resolve(context)
110        return YUIRequireNode(['dom', 'event']).render(context)
111
112
113class YUIRequireNode(template.Node):
114
115    def __init__(self, modules,
116                 nodelist_on_success=None, nodelists_add_module=None):
117        self.modules = modules
118        self.nodelist_on_success = nodelist_on_success
119        self.nodelists_add_module = nodelists_add_module or ()
120
121    def render(self, context):
122        result = []
123        success_scripts = []
124        config = context_setdefault(context, '_yui', {})
125
126        if 'initialized' not in config:
127            url = config.setdefault('source', LOADER_URL)
128            result.append(init(url))
129            success_scripts.append(ONDOMREADY)
130            config['initialized'] = True
131        result.append(script('_yui_loader = new YAHOO.util.YUILoader();'))
132
133        if self.nodelist_on_success is not None:
134            success_scripts.append(
135                self.nodelist_on_success.render(context).strip())
136        if success_scripts:
137            on_success = ',onSuccess:function(){%s}' % ''.join(success_scripts)
138        else:
139            on_success = ''
140
141        if config.get('filter', None):
142            filtr = ',filter:"%s"' % config['filter']
143            if config['filter'].lower() == 'debug':
144                filtr += ',allowRollup:false'
145        else:
146            filtr = ''
147
148        add_module = ''.join(
149            '_yui_loader.addModule(%s);\n' % nodelist.render(context)
150            for nodelist in self.nodelists_add_module)
151
152        result.append(script(
153            '%s_yui_loader.insert({require:[%s]%s%s});' % (
154            add_module,
155            ','.join('"%s"' % m for m in self.modules),
156            filtr,
157            on_success)))
158        return ''.join(result)
159
160
161class YUIAliasNode(template.Node):
162    def __init__(self, aliases):
163        self.aliases = aliases
164    def render(self, context):
165        assigned = context_setdefault(context, '_yui_assigned_aliases', set())
166        assignments = [assignment for assignment in self.aliases
167                       if assignment not in assigned]
168        if not assignments:
169            return ''
170        assigned.update(assignments)
171        return script('_onDOMReady(function(){%s});' %
172                      ''.join('%s=%s;' % (varname, module)
173                              for varname, module in assignments))
174
175
176class YUIOnDomReadyNode(template.Node):
177    def __init__(self, nodelist):
178        self.nodelist = nodelist
179    def render(self, context):
180        return script('_onDOMReady(%s);') % self.nodelist.render(context)
181
182
183class YUIEditorNode(template.Node):
184    def __init__(self, textarea_id):
185        self.textarea_id = template.Variable(textarea_id)
186
187    def render(self, context):
188        textarea_id = self.textarea_id.resolve(context)
189        return render_to_string(
190            'yui/editor.html',
191            {'yui_editor_textarea_id': textarea_id},
192            Context())
Note: See TracBrowser for help on using the browser.