227 """ |
227 """ |
228 js_unload_code = u'''if (typeof(pageDataUnloaded) == 'undefined') { |
228 js_unload_code = u'''if (typeof(pageDataUnloaded) == 'undefined') { |
229 jQuery(window).unload(unloadPageData); |
229 jQuery(window).unload(unloadPageData); |
230 pageDataUnloaded = true; |
230 pageDataUnloaded = true; |
231 }''' |
231 }''' |
232 # Making <script> tag content work properly with all possible |
232 script_opening = u'<script type="text/javascript">\n' |
233 # content-types (xml/html) and all possible browsers is very |
233 script_closing = u'\n</script>' |
234 # tricky, see http://www.hixie.ch/advocacy/xhtml for an in-depth discussion |
|
235 xhtml_safe_script_opening = u'<script type="text/javascript"><!--//--><![CDATA[//><!--\n' |
|
236 xhtml_safe_script_closing = u'\n//--><!]]></script>' |
|
237 |
234 |
238 def __init__(self, req): |
235 def __init__(self, req): |
239 super(HTMLHead, self).__init__() |
236 super(HTMLHead, self).__init__() |
240 self.jsvars = [] |
237 self.jsvars = [] |
241 self.jsfiles = [] |
238 self.jsfiles = [] |
342 resources declaration |
339 resources declaration |
343 """ |
340 """ |
344 w = self.write |
341 w = self.write |
345 # 1/ variable declaration if any |
342 # 1/ variable declaration if any |
346 if self.jsvars: |
343 if self.jsvars: |
347 w(self.xhtml_safe_script_opening) |
344 w(self.script_opening) |
348 for var, value, override in self.jsvars: |
345 for var, value, override in self.jsvars: |
349 vardecl = u'%s = %s;' % (var, json.dumps(value)) |
346 vardecl = u'%s = %s;' % (var, json.dumps(value)) |
350 if not override: |
347 if not override: |
351 vardecl = (u'if (typeof %s == "undefined") {%s}' % |
348 vardecl = (u'if (typeof %s == "undefined") {%s}' % |
352 (var, vardecl)) |
349 (var, vardecl)) |
353 w(vardecl + u'\n') |
350 w(vardecl + u'\n') |
354 w(self.xhtml_safe_script_closing) |
351 w(self.script_closing) |
355 # 2/ css files |
352 # 2/ css files |
356 ie_cssfiles = ((x, (y, z)) for x, y, z in self.ie_cssfiles) |
353 ie_cssfiles = ((x, (y, z)) for x, y, z in self.ie_cssfiles) |
357 if self.datadir_url and self._cw.vreg.config['concat-resources']: |
354 if self.datadir_url and self._cw.vreg.config['concat-resources']: |
358 cssfiles = self.group_urls(self.cssfiles) |
355 cssfiles = self.group_urls(self.cssfiles) |
359 ie_cssfiles = self.group_urls(ie_cssfiles) |
356 ie_cssfiles = self.group_urls(ie_cssfiles) |
420 # stream for <head> |
417 # stream for <head> |
421 self.head = req.html_headers |
418 self.head = req.html_headers |
422 # main stream |
419 # main stream |
423 self.body = UStringIO() |
420 self.body = UStringIO() |
424 self.doctype = u'' |
421 self.doctype = u'' |
425 # xmldecl and html opening tag |
422 self._htmlattrs = [('lang', req.lang)] |
426 self.xmldecl = u'<?xml version="1.0" encoding="%s"?>\n' % req.encoding |
|
427 self._namespaces = [('xmlns', 'http://www.w3.org/1999/xhtml'), |
|
428 ('xmlns:cubicweb','http://www.logilab.org/2008/cubicweb')] |
|
429 self._htmlattrs = [('xml:lang', req.lang), |
|
430 ('lang', req.lang)] |
|
431 # keep main_stream's reference on req for easier text/html demoting |
423 # keep main_stream's reference on req for easier text/html demoting |
432 req.main_stream = self |
424 req.main_stream = self |
433 |
425 |
|
426 @deprecated('[3.17] there are no namespaces in html, xhtml is not served any longer') |
434 def add_namespace(self, prefix, uri): |
427 def add_namespace(self, prefix, uri): |
435 self._namespaces.append( (prefix, uri) ) |
428 pass |
436 |
429 |
|
430 @deprecated('[3.17] there are no namespaces in html, xhtml is not served any longer') |
437 def set_namespaces(self, namespaces): |
431 def set_namespaces(self, namespaces): |
438 self._namespaces = namespaces |
432 pass |
439 |
433 |
440 def add_htmlattr(self, attrname, attrvalue): |
434 def add_htmlattr(self, attrname, attrvalue): |
441 self._htmlattrs.append( (attrname, attrvalue) ) |
435 self._htmlattrs.append( (attrname, attrvalue) ) |
442 |
436 |
443 def set_htmlattrs(self, attrs): |
437 def set_htmlattrs(self, attrs): |
444 self._htmlattrs = attrs |
438 self._htmlattrs = attrs |
445 |
439 |
446 def set_doctype(self, doctype, reset_xmldecl=True): |
440 def set_doctype(self, doctype, reset_xmldecl=None): |
447 self.doctype = doctype |
441 self.doctype = doctype |
448 if reset_xmldecl: |
442 if reset_xmldecl is not None: |
449 self.xmldecl = u'' |
443 warn('[3.17] xhtml is no more supported', |
|
444 DeprecationWarning, stacklevel=2) |
450 |
445 |
451 def write(self, data): |
446 def write(self, data): |
452 """StringIO interface: this method will be assigned to self.w |
447 """StringIO interface: this method will be assigned to self.w |
453 """ |
448 """ |
454 self.body.write(data) |
449 self.body.write(data) |
455 |
450 |
456 @property |
451 @property |
457 def htmltag(self): |
452 def htmltag(self): |
458 attrs = ' '.join('%s="%s"' % (attr, xml_escape(value)) |
453 attrs = ' '.join('%s="%s"' % (attr, xml_escape(value)) |
459 for attr, value in (self._namespaces + self._htmlattrs)) |
454 for attr, value in self._htmlattrs) |
460 if attrs: |
455 if attrs: |
461 return '<html %s>' % attrs |
456 return '<html %s>' % attrs |
462 return '<html>' |
457 return '<html>' |
463 |
458 |
464 def getvalue(self): |
459 def getvalue(self): |
465 """writes HTML headers, closes </head> tag and writes HTML body""" |
460 """writes HTML headers, closes </head> tag and writes HTML body""" |
466 return u'%s\n%s\n%s\n%s\n%s\n</html>' % (self.xmldecl, self.doctype, |
461 return u'%s\n%s\n%s\n%s\n</html>' % (self.doctype, |
467 self.htmltag, |
462 self.htmltag, |
468 self.head.getvalue(), |
463 self.head.getvalue(), |
469 self.body.getvalue()) |
464 self.body.getvalue()) |
470 |
465 |
471 try: |
466 try: |
472 # may not be there if cubicweb-web not installed |
467 # may not be there if cubicweb-web not installed |
473 if sys.version_info < (2, 6): |
468 if sys.version_info < (2, 6): |
474 import simplejson as json |
469 import simplejson as json |