class Composite (Plugin):
def __init__ (self, sons=[], *args, **kwds):
- self.sons=sons
Plugin.__init__ (self, *args, **kwds)
+ self.sons=sons
def insert (self, plugin):
self.sons.append(plugin)
from engine.prelude import Prelude
+# set to
+# . False : silent
+# [ 'SliceList', 'TabbedView' ] : to debug these classes
+# True : to debug all slices
+
+DEBUG= [ 'SliceList' ]
+
class Plugin:
uid=0
# e.g. SimpleList (list=[1,2,3]) => _settings = { 'list':[1,2,3] }
# our own settings are not made part of _settings but could be..
self._settings=settings
-# print "Created plugin with settings %s"%self._settings.keys()
+ if self.need_debug():
+ print "Plugin.__init__ Created plugin with settings %s"%self._settings.keys()
+
+ # subclasses might handle some fields in their own way,
+ # in which case this call is needed to capture that setting
+ # see e.g. SimpleList or SliceList for an example of that
+ def add_to_settings (self, setting_name):
+ self._settings[setting_name]=getattr(self,setting_name)
def classname (self):
try: return self.__class__.__name__
def is_hidable (self): return self.hidable
def is_hidden_by_default (self): return self.hidden_by_default
+ ##########
+ def need_debug (self):
+ if not DEBUG: return False
+ if DEBUG is True: return True
+ else: return self.classname() in DEBUG
+
# returns the html code for that plugin
# in essence, wraps the results of self.render_content ()
def render (self, request):
# call render_content
plugin_content = self.render_content (request)
# expose _settings in json format to js
- settings_json = json.dumps(self._settings, separators=(',',':'))
+ settings_json = json.dumps (self._settings, separators=(',',':'))
result = render_to_string ('widget-plugin.html',
- {'uuid':uuid, 'classname':classname,
+ {'uuid':uuid,
+ 'classname':classname,
'visible':self.is_visible(),
'hidable':self.is_hidable(),
'hidden':self.is_hidden_by_default(),
# handle requirements() if defined on this class
try:
self.handle_requirements (request, self.requirements())
- except:
+ except AttributeError:
+ # most likely the object does not have that method defined, which is fine
+ pass
+ except:
import traceback
traceback.print_exc()
pass
# xxx we might need to check that this does not overwrite env..
env.update(self._settings)
result=render_to_string (template, env)
- print "%s.render_content: BEG --------------------"%self.classname()
- print "env=%s"%env.keys()
- print result
- print "%s.render_content: END --------------------"%self.classname()
+ if self.need_debug():
+ print "%s.render_content: BEG --------------------"%self.classname()
+ print "template=%s"%template
+ print "env=%s"%env.keys()
+ # print result
+ print "%s.render_content: END --------------------"%self.classname()
return result
#################### requirements/prelude management
# or from the result of self.requirements()
def handle_requirements (self, request, d):
for (k,v) in d.iteritems():
- print "%s: handling requirement %s"%(self.classname(),v)
+ if self.need_debug():
+ print "%s: handling requirement %s"%(self.classname(),v)
method_name='add_'+k
method=Plugin.__dict__[method_name]
method(self,request,v)
from types import StringTypes, ListType
+from django.template.loader import render_to_string
+
class Prelude:
"""A class for collecting dependencies on js/css files or fragments"""
def add_css_chunks (self, x):
self.css_chunks += Prelude._normalize (x)
+ # first attempt was to use a simple dict like this
+ # env={}
+ # env['js_files']= self.js_files
+ # env['css_files']= self.css_files
+ # env['js_chunks']= '\n'.join(self.js_chunks)
+ # env['css_chunks']='\n'.join(self.css_chunks)
+ # return env
+ # together with this in layout-myslice.html
+ # {% for js_file in js_files %} {% insert_str prelude js_file %} {% endfor %}
+ # {% for css_file in css_files %} {% insert_str prelude css_file %} {% endfor %}
+ # somehow however this would not work too well,
+ # probably insert_above is not powerful enough to handle that
+ #
+ # so a much simpler and safer approach is for use to compute the html header directly
def render_env (self):
env={}
env['js_files']= self.js_files
env['css_files']= self.css_files
- env['js_chunks']= '\n'.join(self.js_chunks)
- env['css_chunks']='\n'.join(self.css_chunks)
- return env
+ env['js_chunks']= self.js_chunks
+ env['css_chunks']=self.css_chunks
+ # not sure how this should be done more cleanly
+ from myslice.settings import STATIC_URL
+ env ['STATIC_URL'] = STATIC_URL
+ # render this with prelude.html and put the result in header_prelude
+ header_prelude = render_to_string ('header-prelude.html',env)
+ return { 'header_prelude' : header_prelude }
--- /dev/null
+{% for js_file in js_files %}
+<script type='text/javascript' src='{{ STATIC_URL }}{{ js_file|safe }}'></script>
+{% endfor %}
+{% for css_file in css_files %}
+<link rel='stylesheet' type='text/css' href='{{ STATIC_URL }}{{ css_file|safe }}' />
+{% endfor %}
+<script type="text/javascript">
+{% for js_chunk in js_chunks %} {{ js_chunk|safe }} {% endfor %}
+</script>
+<style type="text/css">
+{% for css_chunk in css_chunks %} {{ css_chunk|safe }} {% endfor %}
+</style>
from plugins.verticallayout import VerticalLayout
from plugins.simplelist import SimpleList
+from plugins.slicelist import SliceList
from myslice.viewutils import topmenu_items, the_user, hard_wired_slice_names
plugin_main1 = SimpleList (list=hard_wired_list,
header='Hard wired',
- foo='the value for foo')
+ foo='the value for foo',
+ with_datatables=True)
plugin_main2 = SimpleList (hidable=True,
list=hard_wired_slice_names,
headers='Slices in main content')
##########
# lacks a/href to /slice/%s
- plugin_related = SimpleList (visible=True, hidable=True,
- need_datatables='yes',
- list=hard_wired_slice_names,
- header='Slices' )
+ plugin_related = SliceList (visible=True,
+ hidable=True,
+ with_datatables='yes',
+ list=hard_wired_slice_names,
+ header='Slices' )
content_related = plugin_related.render (request)
# likewise but on the side view
template_env [ 'content_related' ] = content_related
# request.plugin_prelude holds a summary of the requirements() for all plugins
# define {js,css}_{files,chunks}
prelude_env = request.plugin_prelude.render_env()
+ print 'prelude_env',prelude_env
template_env.update(prelude_env)
return render_to_response ('view-plugin.html',template_env,
class SimpleList (Plugin) :
+ # it would make sense to *not* define any constructor here and let Plugin kick in
+ # however it feels nicer this way as we document the settings used in our own template
+ # plus it's less confusing for any subclass if they can be sure which constructor to call
+ def __init__ (self, list=[], with_datatables=False, **settings):
+ Plugin.__init__ (self, **settings)
+ self.list=list
+ self.add_to_settings ('list')
+ self.with_datatables = with_datatables
+ self.add_to_settings ('with_datatables')
+
# SimpleList is useless per se anyways
def title (self) : return "Title for Simple List"
def template (self): return "simplelist.html"
def requirements (self):
- return { 'js_files' : [ "js/simplelist.js" ],
+ reqs = { 'js_files' : [ "js/simplelist.js" ],
'css_files': [ "css/simplelist.css" ],
+ }
+ if self.with_datatables:
+ reqs['js_files'].append ("datatables/js/dataTables.js")
+ reqs['js_files'].append ("js/with-datatables.js")
+ print self.classname(),reqs
+ return reqs
# for tests
# 'js_chunks' : "/* a javascript chunk */",
# 'css_chunks': "/* a css style */ ",
- }
--- /dev/null
+from plugins.simplelist import SimpleList
+
+class SliceList (SimpleList):
+
+ def __init__ (self, list=[], **settings):
+ SimpleList.__init__(self, **settings)
+ self.list = [ "<a href='/slice/%s/' class='slicelist'>%s</a>"%(x,x) for x in list ]
+ self.add_to_settings ('list')
+
+ def title (self):
+ return "Slice list"
+
+# def requirements (self):
+# reqs=SimpleList.requirements(self)
+# reqs['js_files'].append('slice.js')
+# reqs['js_files'].append('slice2.js')
+# reqs['css_files'].append('slice.css')
+# reqs['css_files'].append('slice2.css')
+# reqs['js_chunks']=['js chunk1','js chunk2']
+# reqs['css_chunks']=['css chunk1','css chunk2']
+# return reqs
-<table class='simplelist {%if need_datatables %}need-datatables{% endif %}'>
+<table class='simplelist {%if with_datatables %}with-datatables{% endif %}'>
{% if header %}
<thead><tr><th>{{ header }}</th></tr></thead>
{% endif %}
<tbody>
{% for item in list %}
-<tr><td>{{ item }}</td></tr>
+<tr><td>{{ item|safe }}</td></tr>
{% endfor %}
</tbody>
</table>
+++ /dev/null
-/* elements with class 'need-datatables' are set to use datatables */
-$(document).ready(function() {$('.need-datatables').each(function() { $(this).dataTable() } ) } )
--- /dev/null
+/* elements with class 'with-datatables' are set to use datatables */
+$(document).ready(function() {$('.with-datatables').each(function() { window.console.log('here'); $(this).dataTable() } ) } )
<script type="text/javascript">
{# In case we need to add raw js code - use {% insert prelude_js %} ... {% endinsert %} #}
{% container prelude_js %}
-{{ js_chunks }}
</script>
<style type="text/css">
{# In case we need to add raw css code #}
{% container prelude_css %}
-{{ css_chunks }}
</style>
+{{ header_prelude }}
</head>
{# let's add these ones no matter what #}
{% insert_str prelude "js/plugin.js" %}
{% insert_str prelude "css/myslice.css" %}
-{# also add the stuff as collected in a Prelude class #}
-{% for js_file in js_files %} {% insert_str prelude js_file %} {% endfor %}
-{% for css_file in css_files %} {% insert_str prelude css_file %} {% endfor %}
-
<body>
{% block container %}