utils.py
changeset 7277 acd7f0e9f276
parent 7187 496f51b92154
child 7278 1144a2d90314
equal deleted inserted replaced
7276:f9a68136eb87 7277:acd7f0e9f276
   235     # content-types (xml/html) and all possible browsers is very
   235     # content-types (xml/html) and all possible browsers is very
   236     # tricky, see http://www.hixie.ch/advocacy/xhtml for an in-depth discussion
   236     # tricky, see http://www.hixie.ch/advocacy/xhtml for an in-depth discussion
   237     xhtml_safe_script_opening = u'<script type="text/javascript"><!--//--><![CDATA[//><!--\n'
   237     xhtml_safe_script_opening = u'<script type="text/javascript"><!--//--><![CDATA[//><!--\n'
   238     xhtml_safe_script_closing = u'\n//--><!]]></script>'
   238     xhtml_safe_script_closing = u'\n//--><!]]></script>'
   239 
   239 
   240     def __init__(self):
   240     def __init__(self, datadir_url=None):
   241         super(HTMLHead, self).__init__()
   241         super(HTMLHead, self).__init__()
   242         self.jsvars = []
   242         self.jsvars = []
   243         self.jsfiles = []
   243         self.jsfiles = []
   244         self.cssfiles = []
   244         self.cssfiles = []
   245         self.ie_cssfiles = []
   245         self.ie_cssfiles = []
   246         self.post_inlined_scripts = []
   246         self.post_inlined_scripts = []
   247         self.pagedata_unload = False
   247         self.pagedata_unload = False
       
   248         self.datadir_url = datadir_url
   248 
   249 
   249 
   250 
   250     def add_raw(self, rawheader):
   251     def add_raw(self, rawheader):
   251         self.write(rawheader)
   252         self.write(rawheader)
   252 
   253 
   279         :param jsfile: the script's URL
   280         :param jsfile: the script's URL
   280         """
   281         """
   281         if jsfile not in self.jsfiles:
   282         if jsfile not in self.jsfiles:
   282             self.jsfiles.append(jsfile)
   283             self.jsfiles.append(jsfile)
   283 
   284 
   284     def add_css(self, cssfile, media):
   285     def add_css(self, cssfile, media='all'):
   285         """adds `cssfile` to the list of javascripts used in the webpage
   286         """adds `cssfile` to the list of javascripts used in the webpage
   286 
   287 
   287         This function checks if the file has already been added
   288         This function checks if the file has already been added
   288         :param cssfile: the stylesheet's URL
   289         :param cssfile: the stylesheet's URL
   289         """
   290         """
   298     def add_unload_pagedata(self):
   299     def add_unload_pagedata(self):
   299         """registers onunload callback to clean page data on server"""
   300         """registers onunload callback to clean page data on server"""
   300         if not self.pagedata_unload:
   301         if not self.pagedata_unload:
   301             self.post_inlined_scripts.append(self.js_unload_code)
   302             self.post_inlined_scripts.append(self.js_unload_code)
   302             self.pagedata_unload = True
   303             self.pagedata_unload = True
       
   304 
       
   305     def concat_urls(self, urls):
       
   306         """concatenates urls into one url usable by Apache mod_concat
       
   307 
       
   308         This method returns the url without modifying it if there is only
       
   309         one element in the list
       
   310         :param urls: list of local urls/filenames to concatenate
       
   311         """
       
   312         if len(urls) == 1:
       
   313             return urls[0]
       
   314         len_prefix = len(self.datadir_url)
       
   315         concated = u','.join(url[len_prefix:] for url in urls)
       
   316         return (u'%s??%s' % (self.datadir_url, concated))
       
   317 
       
   318     def group_urls(self, urls_spec):
       
   319         """parses urls_spec in order to generate concatenated urls
       
   320         for js and css includes
       
   321 
       
   322         This method checks if the file is local and if it shares options
       
   323         with direct neighbors
       
   324         :param urls_spec: entire list of urls/filenames to inspect
       
   325         """
       
   326         concatable = []
       
   327         prev_islocal = False
       
   328         prev_key = None
       
   329         for url, key in urls_spec:
       
   330             islocal = url.startswith(self.datadir_url)
       
   331             if concatable and (islocal != prev_islocal or key != prev_key):
       
   332                 yield (self.concat_urls(concatable), prev_key)
       
   333                 del concatable[:]
       
   334             if not islocal:
       
   335                 yield (url, key)
       
   336             else:
       
   337                 concatable.append(url)
       
   338             prev_islocal = islocal
       
   339             prev_key = key
       
   340         if concatable:
       
   341             yield (self.concat_urls(concatable), prev_key)
       
   342 
   303 
   343 
   304     def getvalue(self, skiphead=False):
   344     def getvalue(self, skiphead=False):
   305         """reimplement getvalue to provide a consistent (and somewhat browser
   345         """reimplement getvalue to provide a consistent (and somewhat browser
   306         optimzed cf. http://stevesouders.com/cuzillion) order in external
   346         optimzed cf. http://stevesouders.com/cuzillion) order in external
   307         resources declaration
   347         resources declaration
   316                     vardecl = (u'if (typeof %s == "undefined") {%s}' %
   356                     vardecl = (u'if (typeof %s == "undefined") {%s}' %
   317                                (var, vardecl))
   357                                (var, vardecl))
   318                 w(vardecl + u'\n')
   358                 w(vardecl + u'\n')
   319             w(self.xhtml_safe_script_closing)
   359             w(self.xhtml_safe_script_closing)
   320         # 2/ css files
   360         # 2/ css files
   321         for cssfile, media in self.cssfiles:
   361         for cssfile, media in (self.group_urls(self.cssfiles) if self.datadir_url else self.cssfiles):
   322             w(u'<link rel="stylesheet" type="text/css" media="%s" href="%s"/>\n' %
   362             w(u'<link rel="stylesheet" type="text/css" media="%s" href="%s"/>\n' %
   323               (media, xml_escape(cssfile)))
   363               (media, xml_escape(cssfile)))
   324         # 3/ ie css if necessary
   364         # 3/ ie css if necessary
   325         if self.ie_cssfiles:
   365         if self.ie_cssfiles:
   326             for cssfile, media, iespec in self.ie_cssfiles:
   366             ie_cssfiles = ((x, (y, z)) for x, y, z in self.ie_cssfiles)
       
   367             for cssfile, (media, iespec) in (self.group_urls(ie_cssfiles) if self.datadir_url else ie_cssfiles):
   327                 w(u'<!--%s>\n' % iespec)
   368                 w(u'<!--%s>\n' % iespec)
   328                 w(u'<link rel="stylesheet" type="text/css" media="%s" href="%s"/>\n' %
   369                 w(u'<link rel="stylesheet" type="text/css" media="%s" href="%s"/>\n' %
   329                   (media, xml_escape(cssfile)))
   370                   (media, xml_escape(cssfile)))
   330             w(u'<![endif]--> \n')
   371             w(u'<![endif]--> \n')
   331         # 4/ js files
   372         # 4/ js files
   332         for jsfile in self.jsfiles:
   373         jsfiles = ((x, None) for x in self.jsfiles)
       
   374         for jsfile, media in self.group_urls(jsfiles) if self.datadir_url else jsfiles:
   333             w(u'<script type="text/javascript" src="%s"></script>\n' %
   375             w(u'<script type="text/javascript" src="%s"></script>\n' %
   334               xml_escape(jsfile))
   376               xml_escape(jsfile))
   335         # 5/ post inlined scripts (i.e. scripts depending on other JS files)
   377         # 5/ post inlined scripts (i.e. scripts depending on other JS files)
   336         if self.post_inlined_scripts:
   378         if self.post_inlined_scripts:
   337             w(self.xhtml_safe_script_opening)
   379             w(self.xhtml_safe_script_opening)