# HG changeset patch # User sylvain.thenault@logilab.fr # Date 1234813901 -3600 # Node ID 5e5b296a657ee4da85002d7fbe2cb146c8ba9178 # Parent 8e64f12be69c9b7faada1e2aeaad48c24874ca2f# Parent 616191014b8b2998f3d73afe4946c0ca21319c92 merge diff -r 8e64f12be69c -r 5e5b296a657e common/utils.py --- a/common/utils.py Mon Feb 16 20:51:24 2009 +0100 +++ b/common/utils.py Mon Feb 16 20:51:41 2009 +0100 @@ -177,7 +177,7 @@ self.post_inlined_scripts.append(self.js_unload_code) self.pagedata_unload = True - def getvalue(self): + def getvalue(self, skiphead=False): """reimplement getvalue to provide a consistent (and somewhat browser optimzed cf. http://stevesouders.com/cuzillion) order in external resources declaration @@ -209,7 +209,10 @@ w(u'\n') - return u'\n%s\n' % super(HTMLHead, self).getvalue() + header = super(HTMLHead, self).getvalue() + if skiphead: + return header + return u'\n%s\n' % header class HTMLStream(object): diff -r 8e64f12be69c -r 5e5b296a657e web/data/cubicweb.ajax.js --- a/web/data/cubicweb.ajax.js Mon Feb 16 20:51:24 2009 +0100 +++ b/web/data/cubicweb.ajax.js Mon Feb 16 20:51:41 2009 +0100 @@ -9,7 +9,18 @@ var JSON_BASE_URL = baseuri() + 'json?'; -function postAjaxLoad(node) { +/* + * inspect dom response, search for a
node and + * put its content into the real document's head. + * This enables dynamic css and js loading and is used by replacePageChunk + */ +function loadAjaxHtmlHead(node) { + jQuery(node).find('div.ajaxHtmlHead').appendTo(jQuery('head')); +} + +function postAjaxLoad(node, req) { + // addStylesheets(evalJSON(req.getResponseHeader('X-Cubicweb-Stylesheets') || '[]')); + loadAjaxHtmlHead(node); // find sortable tables if there are some if (typeof(Sortable) != 'undefined') { Sortable.sortTables(node); @@ -28,23 +39,18 @@ // cubicweb loadxhtml plugin to make jquery handle xhtml response jQuery.fn.loadxhtml = function(url, data, reqtype, mode) { - var ajax = null; - if (reqtype == 'post') { - ajax = jQuery.post; - } else { - ajax = jQuery.get; - } if (this.size() > 1) { log('loadxhtml was called with more than one element'); } + var node = this.get(0); // only consider the first element mode = mode || 'replace'; var callback = null; if (data && data.callback) { callback = data.callback; delete data.callback; } - var node = this.get(0); // only consider the first element - ajax(url, data, function(response) { + var deferred = loadJSON(url, data, reqtype); + deferred.addCallback(function(response, req) { var domnode = getDomFromResponse(response); if (mode == 'swap') { var origId = node.id; @@ -57,7 +63,7 @@ } else if (mode == 'append') { jQuery(node).append(domnode); } - postAjaxLoad(node); + postAjaxLoad(node, req); while (jQuery.isFunction(callback)) { callback = callback.apply(this, [domnode]); } diff -r 8e64f12be69c -r 5e5b296a657e web/views/basecontrollers.py --- a/web/views/basecontrollers.py Mon Feb 16 20:51:24 2009 +0100 +++ b/web/views/basecontrollers.py Mon Feb 16 20:51:41 2009 +0100 @@ -211,14 +211,14 @@ self.req.set_content_type(content_type) return xmlize(data) return data - + def html_exec(self, rset=None): - """html mode: execute query and return the view as HTML""" + # XXX try to use the page-content template req = self.req rql = req.form.get('rql') if rset is None and rql: rset = self._exec(rql) - + vid = req.form.get('vid') or vid_from_rset(req, rset, self.schema) try: view = self.vreg.select_view(vid, req, rset) @@ -239,6 +239,10 @@ if divid == 'pageContent': stream.write(u'
') view.dispatch() + extresources = req.html_headers.getvalue(skiphead=True) + stream.write(u'
\n') # XXX use a widget ? + stream.write(extresources) + stream.write(u'
\n') if req.form.get('paginate') and divid == 'pageContent': stream.write(u'
') source = stream.getvalue() diff -r 8e64f12be69c -r 5e5b296a657e web/views/basetemplates.py --- a/web/views/basetemplates.py Mon Feb 16 20:51:24 2009 +0100 +++ b/web/views/basetemplates.py Mon Feb 16 20:51:41 2009 +0100 @@ -19,9 +19,8 @@ # main templates ############################################################## +class LogInOutTemplate(MainTemplate): -class LogInOutTemplate(MainTemplate): - def call(self): self.set_request_content_type() w = self.w @@ -43,7 +42,7 @@ w(u'\n'.join(additional_headers) + u'\n') self.template('htmlheader', rset=self.rset) w(u'%s\n' % html_escape(page_title)) - + class LogInTemplate(LogInOutTemplate): id = 'login' @@ -51,7 +50,7 @@ def content(self, w): self.template('logform', rset=self.rset, id='loginBox', klass='') - + class LoggedOutTemplate(LogInOutTemplate): id = 'loggedout' @@ -66,10 +65,10 @@ html_escape(indexurl), self.req._('go back to the index page'))) - + class TheMainTemplate(MainTemplate): """default main template : - + - call header / footer templates - build result set - guess and call an appropriate view through the view manager @@ -112,7 +111,7 @@ vid = vid_from_rset(req, rset, self.schema) view = self.vreg.select_view(vid, req, rset) return view, rset - + def call(self): view, rset = self._select_view_and_rset() req = self.req @@ -123,8 +122,7 @@ req.update_breadcrumbs() view.set_http_cache_headers() req.validate_cache() - with_templates = not view.binary and view.templatable and \ - not req.form.has_key('__notemplate') + with_templates = self.with_templates(view) if not with_templates: view.set_request_content_type() self.set_stream(templatable=False) @@ -132,17 +130,14 @@ self.set_request_content_type() content_type = self.content_type self.template_header(content_type, view) - if view.binary: - # have to replace our unicode stream using view's binary stream - view.dispatch() - assert self._stream, 'duh, template used as a sub-view ?? (%s)' % self._stream - self._stream = view._stream - else: - view.dispatch(w=self.w) + self.template('page-content', view=view, rset=rset) if with_templates: self.template_footer(view) - + def with_templates(self, view): + return (not view.binary and view.templatable and + not self.req.form.has_key('__notemplate')) + def process_rql(self, rql): """execute rql if specified""" if rql: @@ -159,17 +154,7 @@ additional_headers = additional_headers or view.html_headers() self.template_html_header(content_type, page_title, additional_headers) self.template_body_header(view) - # display entity type restriction component - etypefilter = self.vreg.select_component('etypenavigation', - self.req, self.rset) - if etypefilter and etypefilter.propval('visible'): - etypefilter.dispatch(w=self.w) - self.nav_html = UStringIO() - self.pagination(self.req, self.rset, self.nav_html.write, - not (view and view.need_navigation)) - self.w(_(self.nav_html.getvalue())) - self.w(u'
\n') - + def template_html_header(self, content_type, page_title, additional_headers=()): w = self.whead lang = self.req.lang @@ -196,15 +181,8 @@ if msgcomp: msgcomp.dispatch(w=self.w) self.content_header(view) - w(u'
\n') - vtitle = self.req.form.get('vtitle') - if vtitle: - w(u'

%s

\n' % html_escape(vtitle)) - + def template_footer(self, view=None): - self.w(u'
\n') # close id=contentmain - self.w(_(self.nav_html.getvalue())) - self.w(u'
\n') # closes id=pageContent self.content_footer(view) self.w(u'\n') self.nav_column(view, 'right') @@ -224,18 +202,55 @@ def content_header(self, view=None): """by default, display informal messages in content header""" self.template('contentheader', rset=self.rset, view=view) - + def content_footer(self, view=None): self.template('contentfooter', rset=self.rset, view=view) +class PageContentTemplate(TheMainTemplate): + id = 'page-content' + + def call(self, view=None, rset=None): + self.req.set_header('x-cubicweb-css', 'a.css;b.css') + if view is None: + view, rset = self._select_view_and_rset() + with_templates = self.with_templates(view) + w = self.w + if with_templates: + w(u'
\n') + vtitle = self.req.form.get('vtitle') + if vtitle: + w(u'

%s

\n' % html_escape(vtitle)) + # display entity type restriction component + etypefilter = self.vreg.select_component('etypenavigation', + self.req, self.rset) + if etypefilter and etypefilter.propval('visible'): + etypefilter.dispatch(w=w) + self.nav_html = UStringIO() + self.pagination(self.req, self.rset, self.nav_html.write, + not (view and view.need_navigation)) + w(_(self.nav_html.getvalue())) + w(u'
\n') + if view.binary: + # have to replace our unicode stream using view's binary stream + view.dispatch() + assert self._stream, 'duh, template used as a sub-view ?? (%s)' % self._stream + self._stream = view._stream + else: + view.dispatch(w=w) + if with_templates: + w(u'
\n') # close id=contentmain + w(_(self.nav_html.getvalue())) + w(u'
\n') # closes id=pageContent + + class ErrorTemplate(TheMainTemplate): """fallback template if an internal error occured during displaying the main template. This template may be called for authentication error, which means that req.cnx and req.user may not be set. """ id = 'error' - + def call(self): """display an unexpected error""" self.set_request_content_type() @@ -245,7 +260,7 @@ [NOINDEX, NOFOLLOW]) view.dispatch(w=self.w) self.template_footer(view) - + def template_header(self, content_type, view=None, page_title='', additional_headers=()): w = self.whead lang = self.req.lang @@ -264,7 +279,7 @@ class SimpleMainTemplate(TheMainTemplate): id = 'main-no-top' - + def template_header(self, content_type, view=None, page_title='', additional_headers=()): page_title = page_title or view.page_title() additional_headers = additional_headers or view.html_headers() @@ -295,7 +310,7 @@ vtitle = self.req.form.get('vtitle') if vtitle: w(u'

%s

' % html_escape(vtitle)) - + def topleft_header(self): self.w(u'\n') self.w(u'