Merge branch 'onelab' of ssh://git.onelab.eu/git/myslice into onelab
[unfold.git] / unfold / prelude.py
1 from types import StringTypes, ListType
2
3 from django.template.loader import render_to_string
4
5 from myslice.settings import logger
6
7 debug=False
8
9 # the need for js_init_chunks is because we need to have the plugins initialized
10 # before the queries fly
11 # and when writing a view it is not very easy to remember in which order
12 # all the js initialization will end up, so we use these 2 categories 
13 # as a simple way to enforce this dependency
14 # far from perfect but good enough for now
15 class Prelude:
16
17     """A class for collecting dependencies on js/css stuff
18     files are expected from your 'static' area, typically 'css/foo.css' or 'js/foo.js'
19     fragments (chunks) is for raw code
20     you can specify a string or a list of strings
21     js_init_chunks get collated with js_chunks but come first
22     """
23
24     keys=[ 'js_files', 'css_files', 'js_init_chunks', 'js_chunks', 'css_chunks' ]
25     def __init__ (self, js_files=None, css_files=None, js_init_chunks=None, js_chunks=None, css_chunks=None):
26         # it's tempting to use sets but sets are not ordered..
27         self.js_files  = Prelude._normalize(js_files)
28         self.css_files = Prelude._normalize(css_files)
29         self.js_init_chunks = Prelude._normalize(js_init_chunks)
30         self.js_chunks = Prelude._normalize(js_chunks)
31         self.css_chunks= Prelude._normalize(css_chunks)
32
33     @staticmethod
34     def _normalize (input):
35         if not input:                           return []
36         elif isinstance (input, ListType):      return input
37         elif isinstance (input, StringTypes):   return [ input ]
38         else:                                   return list (input)
39
40     def add_js_files (self, x):
41         for i in Prelude._normalize (x):
42             if i not in self.js_files: self.js_files.append(i)
43     def add_css_files (self, x):
44         for i in Prelude._normalize (x):
45             if i not in self.css_files: self.css_files.append(i)
46     def add_js_init_chunks (self, x):
47         self.js_init_chunks += Prelude._normalize (x)
48     def add_js_chunks (self, x):
49         self.js_chunks += Prelude._normalize (x)
50     def add_css_chunks (self, x):
51         self.css_chunks += Prelude._normalize (x)
52
53     def inspect_string (self,msg):
54         result =  'Prelude.inspect %s (%s) with '%(msg,self)
55         result += ",".join( [ "%s->%s"%(k,len(getattr(self,k))) for k in Prelude.keys ] )
56         return result
57     def inspect (self,msg):
58         logger.debug(self.inspect_string(msg))
59
60     # first attempt was to use a simple dict like this
61     #    env={}
62     #    env['js_files']=  self.js_files
63     #    env['css_files']= self.css_files
64     #    env['js_chunks']= '\n'.join(self.js_chunks)
65     #    env['css_chunks']='\n'.join(self.css_chunks)
66     #    return env
67     # together with this in prelude.html
68     # {% for js_file in js_files %} {% insert_str prelude js_file %} {% endfor %}
69     # {% for css_file in css_files %} {% insert_str prelude css_file %} {% endfor %}
70     # somehow however this would not work too well, 
71     # probably insert_above is not powerful enough to handle that
72     # 
73     # so a much simpler and safer approach is for us to compute the html header directly
74     # this requires  to filter on full urls
75     #
76     @staticmethod
77     def full_url (input):
78         if input.startswith("http://") or input.startswith("https://"):
79             return input
80         else:
81             from myslice.settings import STATIC_URL
82             return "%s%s"%(STATIC_URL,input)
83         
84     def prelude_env (self): 
85         env={}
86         env['js_urls'] = [ Prelude.full_url (js_file) for js_file in self.js_files ]
87         env['css_urls'] = [ Prelude.full_url (css_file) for css_file in self.css_files ]
88         env['all_js_chunks']= self.js_init_chunks + self.js_chunks
89         env['css_chunks']=self.css_chunks
90         if debug:
91             logger.debug("prelude has {} js_files, {} css files, ({}+{}) js chunks and {} css_chunks"\
92                          .format (len(self.js_files), len(self.css_files),
93                                   len(self.js_init_chunks), len(self.js_chunks), len(self.css_chunks),))
94         # render this with prelude.html and put the result in header_prelude
95         header_prelude = render_to_string ('prelude.html',env)
96         return { 'header_prelude' : header_prelude }