# HG changeset patch # User Laure Bourgois # Date 1235384675 -3600 # Node ID b28ef0f4494f180612473fa97f9181eb39766363 # Parent d7f85fd197dfacf2b23c8d587fa8fbe23250b6c4# Parent 19862a0e55a5a3b613d3dd3c6eaf780821899910 merge diff -r d7f85fd197df -r b28ef0f4494f web/data/cubicweb.widgets.js --- a/web/data/cubicweb.widgets.js Fri Feb 20 15:33:43 2009 +0100 +++ b/web/data/cubicweb.widgets.js Mon Feb 23 11:24:35 2009 +0100 @@ -181,14 +181,6 @@ } } -Widgets.TreeView = defclass("TreeView", null, { - __init__: function(wdgnode) { - jQuery(wdgnode).treeview({toggle: toggleTree, - prerendered: true - }); - } -}); - /* widget based on SIMILE's timeline widget * http://code.google.com/p/simile-widgets/ diff -r d7f85fd197df -r b28ef0f4494f web/views/tabs.py --- a/web/views/tabs.py Fri Feb 20 15:33:43 2009 +0100 +++ b/web/views/tabs.py Mon Feb 23 11:24:35 2009 +0100 @@ -33,15 +33,22 @@ });""" % {'event': 'load_%s' % vid, 'vid': vid, 'reloadable' : str(reloadable).lower()}) - def lazyview(self, vid, eid=None, reloadable=False, show_spinbox=True, w=None): + def lazyview(self, vid, rql=None, eid=None, rset=None, static=False, + reloadable=False, show_spinbox=True, w=None): """a lazy version of wview first version only support lazy viewing for an entity at a time """ + assert rql or eid or rset or static, \ + 'lazyview wants at least : rql, or an eid, or an rset -- or call it with static=True' w = w or self.w self.req.add_js('cubicweb.lazy.js') urlparams = {'vid' : vid, 'mode' : 'html'} - if eid: + if rql: + urlparams['rql'] = rql + elif eid: urlparams['rql'] = rql_for_eid(eid) + elif rset: + urlparams['rql'] = rset.printable_rql() w(u'
' % ( vid, html_escape(self.build_url('json', **urlparams)))) if show_spinbox: @@ -65,12 +72,12 @@ return str('%s_active_tab' % self.config.appid) def active_tab(self, tabs, default): - cookie = self.req.get_cookie() + cookies = self.req.get_cookie() cookiename = self.cookie_name - activetab = cookie.get(cookiename) + activetab = cookies.get(cookiename) if activetab is None: - cookie[cookiename] = default - self.req.set_cookie(cookie, cookiename) + cookies[cookiename] = default + self.req.set_cookie(cookies, cookiename) tab = default else: tab = activetab.value @@ -96,7 +103,7 @@ active_tab = self.active_tab(tabs, default) # build the html structure w = self.w - w(u'
') + w(u'
' % entity.eid) w(u'
    ') for tab in tabs: w(u'
  • ') @@ -110,15 +117,16 @@ w(u'
') for tab in tabs: w(u'
' % tab) - self.lazyview(tab, entity.eid) + self.lazyview(tab, eid=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 }); + jQuery('#entity-tabs-%(eeid)s > ul').tabs( { selected: %(tabindex)s }); set_tab('%(vid)s', '%(cookiename)s'); """ % {'tabindex' : tabs.index(active_tab), 'vid' : active_tab, + 'eeid' : entity.eid, 'cookiename' : self.cookie_name}) @@ -138,11 +146,10 @@ vid = 'gallery' __selectors__ = EntityRelationView.__selectors__ + (one_line_rset,) - This is the view we want to have in a tab, only if there is something to show. Then, just define as below, and declare this being the tab content : - class ProjectScreenshotTab(DataDependantTab, ProjectScreenshotsView): + class ProjectScreenshotTab(EntityRelatedTab, ProjectScreenshotsView): id = 'screenshots_tab' """ __selectors__ = EntityView.__selectors__ + (has_related_entities,) diff -r d7f85fd197df -r b28ef0f4494f web/views/treeview.py --- a/web/views/treeview.py Fri Feb 20 15:33:43 2009 +0100 +++ b/web/views/treeview.py Mon Feb 23 11:24:35 2009 +0100 @@ -1,38 +1,32 @@ from logilab.mtconverter import html_escape - from cubicweb.interfaces import ITree from cubicweb.common.selectors import implement_interface, yes from cubicweb.common.view import EntityView -from cubicweb.web.views.baseviews import OneLineView - class TreeView(EntityView): id = 'treeview' accepts = ('Any',) itemvid = 'treeitemview' css_classes = 'treeview widget' title = _('tree view') - - def call(self, subvid=None): + + def call(self, subvid=None, treeid=None): if subvid is None and 'subvid' in self.req.form: subvid = self.req.form.pop('subvid') # consume it if subvid is None: subvid = 'oneline' self.req.add_css('jquery.treeview.css') - self.req.add_js(('cubicweb.ajax.js', 'jquery.treeview.js', 'cubicweb.widgets.js')) - # XXX noautoload is a quick hack to avoid treeview to be rebuilt - # after a json query and avoid double toggling bugs. - # Need to find a way to do that cleanly. - if 'noautoload' in self.req.form: - self.w(u'
    ' % self.css_classes) - else: - self.w(u'
      ' - % self.css_classes) + self.req.add_js(('cubicweb.ajax.js', 'jquery.treeview.js')) + # XXX find a way, an id is MANDATORY + treeid = 'TREE' #treeid or self.rset.rows[0][0] + self.req.html_headers.add_onload(u""" + $("#tree-%s").treeview({toggle: toggleTree, + prerendered: true});""" % treeid) + self.w(u'
        ' % (treeid, self.css_classes)) for rowidx in xrange(len(self.rset)): self.wview(self.itemvid, self.rset, row=rowidx, col=0, vid=subvid, parentvid=self.id) self.w(u'
      ') - class FileTreeView(TreeView): """specific version of the treeview to display file trees @@ -44,8 +38,6 @@ def call(self, subvid=None): super(FileTreeView, self).call(subvid='filetree-oneline') - - class FileItemInnerView(EntityView): """inner view used by the TreeItemView instead of oneline view @@ -57,10 +49,10 @@ def cell_call(self, row, col): entity = self.entity(row, col) if ITree.is_implemented_by(entity.__class__) and not entity.is_leaf(): - self.w(u'
      %s
      ' % entity.view('oneline')) + self.w(u'
      %s
      \n' % entity.view('oneline')) else: # XXX define specific CSS classes according to mime types - self.w(u'
      %s
      ' % entity.view('oneline')) + self.w(u'
      %s
      \n' % entity.view('oneline')) class DefaultTreeViewItemView(EntityView): @@ -68,7 +60,7 @@ """ id = 'treeitemview' accepts = ('Any',) - + def cell_call(self, row, col, vid='oneline', parentvid='treeview'): entity = self.entity(row, col) itemview = self.view(vid, self.rset, row=row, col=col) @@ -78,9 +70,14 @@ self.w(u'
    • %s
    • ' % itemview) -class TreeViewItemView(EntityView): +class TreeStateMixin(object): + + def open_state(self): + raise NotImplementedError + +class TreeViewItemView(EntityView, TreeStateMixin): """specific treeitem view for entities which implement ITree - + (each item should be exandable if it's not a tree leaf) """ id = 'treeitemview' @@ -88,33 +85,80 @@ # the default treeitem view __selectors__ = (implement_interface, yes) accepts_interfaces = (ITree,) - + + def open_state(self): + """implements TreeState mixin""" + return () + def cell_call(self, row, col, vid='oneline', parentvid='treeview'): + w = self.w entity = self.entity(row, col) - cssclasses = [] + liclasses = [] is_leaf = False + is_open = str(entity.eid) in self.open_state() if row == len(self.rset) - 1: is_leaf = True if not hasattr(entity, 'is_leaf') or entity.is_leaf(): - if is_leaf : cssclasses.append('last') - self.w(u'
    • ' % u' '.join(cssclasses)) + if is_leaf : liclasses.append('last') + w(u'
    • ' % u' '.join(liclasses)) else: rql = entity.children_rql() % {'x': entity.eid} url = html_escape(self.build_url('json', rql=rql, vid=parentvid, pageid=self.req.pageid, subvid=vid, noautoload=True)) - cssclasses.append('expandable') - divclasses = ['hitarea expandable-hitarea'] - if is_leaf : - cssclasses.append('lastExpandable') - divclasses.append('lastExpandable-hitarea') - self.w(u'
    • ' % (url, u' '.join(cssclasses))) - self.w(u'
      ' % u' '.join(divclasses)) - + if is_open: + liclasses.append('collapsable') + else: + liclasses.append('expandable') + divclasses = ['hitarea'] + if is_open: + divclasses.append('collapsable-hitarea') + else: + divclasses.append('expandable-hitarea') + if is_leaf: + liclasses.append('lastExpandable') + if not is_open: + divclasses.append('lastExpandable-hitarea') + if is_open: + w(u'
    • ' % u' '.join(liclasses)) + else: + w(u'
    • ' % (url, u' '.join(liclasses))) + if is_leaf: + divtail = '' + else: + divtail = ''' onclick="async_remote_exec('node_clicked', %s)"''' % entity.eid + w(u'
      ' % (u' '.join(divclasses), divtail)) + # add empty
        because jquery's treeview plugin checks for # sublists presence - self.w(u'
        • place holder
        ') + if not is_open: + w(u'
        • place holder
        ') + # the local node info self.wview(vid, self.rset, row=row, col=col) - self.w(u'') + if is_open: # recurse if needed + self.wview(parentvid, self.req.execute(rql)) + w(u'') + +from logilab.common.decorators import monkeypatch +from cubicweb.web.views.basecontrollers import JSonController +@monkeypatch(JSonController) +def js_node_clicked(self, eid): + """add/remove eid in treestate cookie + XXX this deals with one tree per page + also check the treeid issue above + """ + cookies = self.req.get_cookie() + treestate = cookies.get('treestate') + if treestate is None: + cookies['treestate'] = str(eid) + self.req.set_cookie(cookies, 'treestate') + else: + marked = set(treestate.value.split(';')) + if eid in marked: + marked.remove(eid) + else: + marked.add(eid) + cookies['treestate'] = ';'.join(str(x) for x in marked) + self.req.set_cookie(cookies, 'treestate')