# HG changeset patch # User sylvain.thenault@logilab.fr # Date 1233332732 -3600 # Node ID 9cafff0e0620e780b256e172e7c7e1f5f1418aa0 # Parent 781cd9fccbaa2726e8b890068e21412815639b22# Parent 73aab1d2a27aca47ef7255cfa39fca5db2dbc22a merge diff -r 781cd9fccbaa -r 9cafff0e0620 common/view.py --- a/common/view.py Fri Jan 30 17:25:11 2009 +0100 +++ b/common/view.py Fri Jan 30 17:25:32 2009 +0100 @@ -53,12 +53,11 @@ cubicweb:vid CDATA #IMPLIED cubicweb:rql CDATA #IMPLIED cubicweb:actualrql CDATA #IMPLIED - cubicweb:rooteid CDATA #IMPLIED + cubicweb:rooteid CDATA #IMPLIED cubicweb:dataurl CDATA #IMPLIED - cubicweb:size CDATA #IMPLIED + cubicweb:size CDATA #IMPLIED cubicweb:tlunit CDATA #IMPLIED cubicweb:loadurl CDATA #IMPLIED - cubicweb:lazyloadurl CDATA #IMPLIED cubicweb:uselabel CDATA #IMPLIED cubicweb:facetargs CDATA #IMPLIED cubicweb:facetName CDATA #IMPLIED @@ -74,7 +73,7 @@ A view is instantiated to render a [part of a] result set. View subclasses may be parametred using the following class attributes: - + * `templatable` indicates if the view may be embeded in a main template or if it has to be rendered standalone (i.e. XML for instance) @@ -88,14 +87,14 @@ time to a write function to use. """ __registry__ = 'views' - + templatable = True need_navigation = True # content_type = 'application/xhtml+xml' # text/xhtml' binary = False add_to_breadcrumbs = True category = 'view' - + def __init__(self, req, rset): super(View, self).__init__(req, rset) self.w = None @@ -105,7 +104,7 @@ if self.req.xhtml_browser(): return 'application/xhtml+xml' return 'text/html' - + def set_stream(self, w=None): if self.w is not None: return @@ -121,14 +120,14 @@ return stream # main view interface ##################################################### - + def dispatch(self, w=None, **context): """called to render a view object for a result set. This method is a dispatched to an actual method selected according to optional row and col parameters, which are locating a particular row or cell in the result set: - + * if row [and col] are specified, `cell_call` is called * if none of them is supplied, the view is considered to apply on the whole result set (which may be None in this case), `call` is @@ -150,7 +149,7 @@ # should default .call() method add a
around each # rset item add_div_section = True - + def call(self, **kwargs): """the view is called for an entire result set, by default loop other rows of the result set and call the same view on the @@ -172,10 +171,10 @@ def cell_call(self, row, col, **kwargs): """the view is called for a particular result set cell""" raise NotImplementedError, self - + def linkable(self): """return True if the view may be linked in a menu - + by default views without title are not meant to be displayed """ if not getattr(self, 'title', None): @@ -184,7 +183,7 @@ def is_primary(self): return self.id == 'primary' - + def url(self): """return the url associated with this view. Should not be necessary for non linkable views, but a default implementation @@ -200,7 +199,7 @@ self.req.set_content_type(self.content_type) # view utilities ########################################################## - + def view(self, __vid, rset, __fallback_vid=None, **kwargs): """shortcut to self.vreg.render method avoiding to pass self.req""" try: @@ -210,7 +209,7 @@ raise view = self.vreg.select_view(__fallback_vid, self.req, rset, **kwargs) return view.dispatch(**kwargs) - + def wview(self, __vid, rset, __fallback_vid=None, **kwargs): """shortcut to self.view method automatically passing self.w as argument """ @@ -237,7 +236,7 @@ label = label or self.req._(action.title) return u'%s' % (html_escape(action.url()), label) return u'' - + def html_headers(self): """return a list of html headers (eg something to be inserted between and of the returned page @@ -245,7 +244,7 @@ by default return a meta tag to disable robot indexation of the page """ return [NOINDEX] - + def page_title(self): """returns a title according to the result set - used for the title in the HTML header @@ -295,7 +294,7 @@ """ return the url of the entity creation form for a given entity type""" return self.req.build_url('add/%s'%etype, **kwargs) - + # concrete views base classes ################################################# class EntityView(View): @@ -304,7 +303,7 @@ __registerer__ = accepts_registerer __selectors__ = (accept,) category = 'entityview' - + def field(self, label, value, row=True, show_label=True, w=None, tr=True): """ read-only field """ if w is None: @@ -319,7 +318,7 @@ if row: w(u'
') - + class StartupView(View): """base class for views which doesn't need a particular result set to be displayed (so they can always be displayed !) @@ -328,7 +327,7 @@ __selectors__ = (match_user_group, none_rset) require_groups = () category = 'startupview' - + def url(self): """return the url associated with this view. We can omit rql here""" return self.build_url('view', vid=self.id) @@ -348,9 +347,9 @@ """ __registerer__ = accepts_registerer __selectors__ = (chainfirst(none_rset, accept),) - + default_rql = None - + def __init__(self, req, rset): super(EntityStartupView, self).__init__(req, rset) if rset is None: @@ -360,7 +359,7 @@ def startup_rql(self): """return some rql to be executedif the result set is None""" return self.default_rql - + def call(self, **kwargs): """override call to execute rql returned by the .startup_rql method if necessary @@ -379,14 +378,14 @@ return self.build_url(vid=self.id) return super(EntityStartupView, self).url() - + class AnyRsetView(View): """base class for views applying on any non empty result sets""" __registerer__ = priority_registerer __selectors__ = (nonempty_rset,) - + category = 'anyrsetview' - + def columns_labels(self, tr=True): if tr: translate = display_name @@ -403,7 +402,7 @@ label = translate(self.req, attr) labels.append(label) return labels - + class EmptyRsetView(View): """base class for views applying on any empty result sets""" @@ -422,7 +421,7 @@ __selectors__ = (match_user_group,) require_groups = () - + def template(self, oid, **kwargs): """shortcut to self.registry.render method on the templates registry""" w = kwargs.pop('w', self.w) diff -r 781cd9fccbaa -r 9cafff0e0620 skeleton/__pkginfo__.py.tmpl --- a/skeleton/__pkginfo__.py.tmpl Fri Jan 30 17:25:11 2009 +0100 +++ b/skeleton/__pkginfo__.py.tmpl Fri Jan 30 17:25:32 2009 +0100 @@ -1,6 +1,7 @@ # pylint: disable-msg=W0622 """%(distname)s application packaging information""" +modname = %(cubename)s distname = '%(distname)s' numversion = (0, 1, 0) diff -r 781cd9fccbaa -r 9cafff0e0620 toolsutils.py --- a/toolsutils.py Fri Jan 30 17:25:11 2009 +0100 +++ b/toolsutils.py Fri Jan 30 17:25:32 2009 +0100 @@ -273,7 +273,7 @@ }), ("host", {'short': 'H', 'type' : 'string', 'metavar': '', - 'default': 'all-in-one', + 'default': None, 'help': 'specify the name server\'s host name. Will be detected by \ broadcast if not provided.', }), diff -r 781cd9fccbaa -r 9cafff0e0620 web/data/cubicweb.ajax.js --- a/web/data/cubicweb.ajax.js Fri Jan 30 17:25:11 2009 +0100 +++ b/web/data/cubicweb.ajax.js Fri Jan 30 17:25:32 2009 +0100 @@ -9,6 +9,23 @@ var JSON_BASE_URL = baseuri() + 'json?'; +function postAjaxLoad(node) { + // find sortable tables if there are some + if (typeof(Sortable) != 'undefined') { + Sortable.sortTables(node); + } + // find textareas and wrap them if there are some + if (typeof(FCKeditor) != 'undefined') { + buildWysiwygEditors(node); + } + if (typeof initFacetBoxEvents != 'undefined') { + initFacetBoxEvents(node); + } + if (typeof buildWidgets != 'undefined') { + buildWidgets(node); + } +} + // cubicweb loadxhtml plugin to make jquery handle xhtml response jQuery.fn.loadxhtml = function(url, data, reqtype, mode) { var ajax = null; @@ -40,28 +57,12 @@ } else if (mode == 'append') { jQuery(node).append(domnode); } - // find sortable tables if there are some - if (typeof(Sortable) != 'undefined') { - Sortable.sortTables(node); - } - // find textareas and wrap them if there are some - if (typeof(FCKeditor) != 'undefined') { - buildWysiwygEditors(node); - } - - if (typeof initFacetBoxEvents != 'undefined') { - initFacetBoxEvents(node); - } - - if (typeof buildWidgets != 'undefined') { - buildWidgets(node); - } - + postAjaxLoad(node); while (jQuery.isFunction(callback)) { callback = callback.apply(this, [domnode]); } }); -} +}; diff -r 781cd9fccbaa -r 9cafff0e0620 web/data/cubicweb.lazy.js --- a/web/data/cubicweb.lazy.js Fri Jan 30 17:25:11 2009 +0100 +++ b/web/data/cubicweb.lazy.js Fri Jan 30 17:25:32 2009 +0100 @@ -1,22 +1,14 @@ function load_now(eltsel, holesel) { - var lazydiv = jQuery(eltsel); - var hole = lazydiv.children(holesel); - if (hole.length == 0) /* the hole is already filled */ - return; - var vid_eid = lazydiv.attr('cubicweb:lazyloadurl'); - /* XXX see what could be done with jquery.loadxhtml(...) */ - var later = async_rawremote_exec('lazily', vid_eid); - later.addCallback(function(req) { - var div = lazydiv[0]; - div.appendChild(getDomFromResponse(req)); - div.removeChild(hole[0]); - }); - later.addErrback(function(err) { - log(err); - }); + var lazydiv = jQuery(eltsel); + var hole = lazydiv.children(holesel); + if (hole.length == 0) { + /* the hole is already filled */ + return; + } + lazydiv.loadxhtml(lazydiv.attr('cubicweb:loadurl')); } function trigger_load(divid) { - jQuery('#lazy-' + divid).trigger('load_' + divid); -} \ No newline at end of file + jQuery('#lazy-' + divid).trigger('load_' + divid); +} diff -r 781cd9fccbaa -r 9cafff0e0620 web/data/cubicweb.tabs.js --- a/web/data/cubicweb.tabs.js Fri Jan 30 17:25:11 2009 +0100 +++ b/web/data/cubicweb.tabs.js Fri Jan 30 17:25:32 2009 +0100 @@ -1,7 +1,7 @@ function set_tab(tabname) { - // set appropriate cookie - // XXX see if we can no just do it with jQuery - async_remote_exec('remember_active_tab', tabname); - // trigger show + tabname event - trigger_load(tabname); + // set appropriate cookie + // XXX see if we can no just do it with jQuery + async_remote_exec('remember_active_tab', tabname); + // trigger show + tabname event + trigger_load(tabname); } diff -r 781cd9fccbaa -r 9cafff0e0620 web/views/owl.py --- a/web/views/owl.py Fri Jan 30 17:25:11 2009 +0100 +++ b/web/views/owl.py Fri Jan 30 17:25:32 2009 +0100 @@ -30,6 +30,7 @@ id = 'owl' title = _('owl') templatable =False + content_type = 'application/xml' # 'text/xml' def call(self): skipmeta = int(self.req.form.get('skipmeta', True)) @@ -176,11 +177,10 @@ title = _('owlabox') templatable =False accepts = ('Any',) + content_type = 'application/xml' # 'text/xml' def call(self): - rql = ('Any X') - rset = self.req.execute(rql) skipmeta = int(self.req.form.get('skipmeta', True)) self.w(u''' ' % (vid, vid, eid)) + urlparams = {'vid' : vid, 'mode' : 'html'} + if eid: + urlparams['rql'] = rql_for_eid(eid) + # w(u'
' % (vid, vid, eid)) + w(u'
' % ( + vid, html_escape(self.build_url('json', **urlparams)))) if show_spinbox: w(u'%s' % (vid, self.req._('loading'))) w(u'
') - self.req.html_headers.prepend_post_inline_script(u""" -jQuery(document).ready(function () { - $('#lazy-%(vid)s').bind('%(event)s', function(event) { + self.req.html_headers.add_onload(u""" + jQuery('#lazy-%(vid)s').bind('%(event)s', function(event) { load_now('#lazy-%(vid)s', '#%(vid)s-hole'); - });});""" % {'event' : 'load_%s' % vid, - 'vid' : vid}) + });""" % {'event': 'load_%s' % vid, 'vid': vid}) def forceview(self, vid): """trigger an event that will force immediate loading of the view on dom readyness """ self.req.add_js('.lazy.js') - self.req.html_headers.add_post_inline_script(u""" -jQuery(document).ready(function() { - trigger_load('%(vid)s');}) -""" % {'vid' : vid}) + self.req.html_headers.add_onload("trigger_load('%s');" % vid) + class TabsMixin(LazyViewMixin): @@ -89,13 +87,6 @@ tabs = self.prune_tabs(tabs) # select a tab active_tab = self.active_tab(tabs, default) - self.req.html_headers.add_post_inline_script(u""" - jQuery(document).ready(function() { - jQuery('#entity-tabs > ul').tabs( { selected: %(tabindex)s }); - set_tab('%(vid)s'); - }); - """ % {'tabindex' : tabs.index(active_tab), - 'vid' : active_tab}) # build the html structure w = self.w w(u'
') @@ -114,24 +105,29 @@ w(u'
' % tab) self.lazyview(tab, entity.eid) w(u'
') + # call the set_tab() JS function *after* each tab is generated + # because the callback binding needs to be done before + self.req.html_headers.add_onload(u""" + jQuery('#entity-tabs > ul').tabs( { selected: %(tabindex)s }); + set_tab('%(vid)s'); + """ % {'tabindex' : tabs.index(active_tab), + 'vid' : active_tab}) -from cubicweb.web.views.basecontrollers import JSonController - +@monkeypatch(JSonController) def js_remember_active_tab(self, tabname): cookie = self.req.get_cookie() cookiename = '%s_active_tab' % self.config.appid cookie[cookiename] = tabname self.req.set_cookie(cookie, cookiename) +@monkeypatch(JSonController) def js_lazily(self, vid_eid): vid, eid = vid_eid.split('-') rset = eid and self.req.eid_rset(eid) or None view = self.vreg.select_view(vid, self.req, rset) return self._set_content_type(view, view.dispatch()) -JSonController.js_remember_active_tab = js_remember_active_tab -JSonController.js_lazily = js_lazily class EntityRelatedTab(EntityView): """A view you should inherit from leftmost, @@ -141,7 +137,7 @@ Example : class ProjectScreenshotsView(EntityRelationView): - "display project's screenshots" + '''display project's screenshots''' id = title = _('projectscreenshots') accepts = ('Project',) rtype = 'screenshot' @@ -160,7 +156,7 @@ vid = 'list' def cell_call(self, row, col): - rset = self.rset.get_entity(row, col).related(self.rtype, role(self)) + rset = self.entity(row, col).related(self.rtype, role(self)) self.w(u'
') self.wview(self.vid, rset, 'noresult') self.w(u'
')