web/views/treeview.py
branchstable
changeset 3320 0dc8b2d46a53
parent 3311 6934be37e948
child 3321 5baac9068823
equal deleted inserted replaced
3319:f959ded4d61e 3320:0dc8b2d46a53
     5 :contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
     5 :contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
     6 :license: GNU Lesser General Public License, v2.1 - http://www.gnu.org/licenses
     6 :license: GNU Lesser General Public License, v2.1 - http://www.gnu.org/licenses
     7 """
     7 """
     8 __docformat__ = "restructuredtext en"
     8 __docformat__ = "restructuredtext en"
     9 
     9 
       
    10 import simplejson as json
       
    11 
    10 from logilab.common.decorators import monkeypatch
    12 from logilab.common.decorators import monkeypatch
    11 from logilab.mtconverter import xml_escape
    13 from logilab.mtconverter import xml_escape
    12 
       
    13 from cubicweb.utils import make_uid
    14 from cubicweb.utils import make_uid
    14 from cubicweb.interfaces import ITree
    15 from cubicweb.interfaces import ITree
    15 from cubicweb.selectors import implements
    16 from cubicweb.selectors import implements
    16 from cubicweb.view import EntityView
    17 from cubicweb.view import EntityView
    17 
    18 
    19     return str('%s-treestate' % treeid)
    20     return str('%s-treestate' % treeid)
    20 
    21 
    21 class TreeView(EntityView):
    22 class TreeView(EntityView):
    22     id = 'treeview'
    23     id = 'treeview'
    23     itemvid = 'treeitemview'
    24     itemvid = 'treeitemview'
       
    25     subvid = 'oneline'
    24     css_classes = 'treeview widget'
    26     css_classes = 'treeview widget'
    25     title = _('tree view')
    27     title = _('tree view')
    26 
    28 
    27     def _init_params(self, subvid, treeid, initial_load, initial_thru_ajax):
    29     def _init_params(self, subvid, treeid, initial_load, initial_thru_ajax, morekwargs):
       
    30         form = self.req.form
    28         if subvid is None:
    31         if subvid is None:
    29             subvid = self.req.form.pop('treesubvid', 'oneline') # consume it
    32             subvid = form.pop('treesubvid', self.subvid) # consume it
    30         if treeid is None:
    33         if treeid is None:
    31             treeid = self.req.form.pop('treeid', None)
    34             treeid = form.pop('treeid', None)
    32             if treeid is None:
    35             if treeid is None:
    33                 self.warning('Tree state won\'t be properly restored after next reload')
    36                 treeid = 'throw_away' + make_uid('uid')
    34                 treeid = make_uid('throw away uid')
    37         if 'morekwargs' in self.req.form:
    35         toplevel_thru_ajax = self.req.form.pop('treeview_top', False) or initial_thru_ajax
    38             ajaxargs = json.loads(form.pop('morekwargs'))
    36         toplevel = toplevel_thru_ajax or (initial_load and not self.req.form.get('fname'))
    39             # got unicode & python keywords must be strings
       
    40             morekwargs.update(dict((str(k), v)
       
    41                                    for k, v in ajaxargs.iteritems()))
       
    42         toplevel_thru_ajax = form.pop('treeview_top', False) or initial_thru_ajax
       
    43         toplevel = toplevel_thru_ajax or (initial_load and not form.get('fname'))
    37         return subvid, treeid, toplevel_thru_ajax, toplevel
    44         return subvid, treeid, toplevel_thru_ajax, toplevel
    38 
    45 
    39     def call(self, subvid=None, treeid=None, initial_load=True, initial_thru_ajax=False):
    46     def _init_headers(self, treeid, toplevel_thru_ajax):
       
    47         self.req.add_css('jquery.treeview.css')
       
    48         self.req.add_js(('cubicweb.ajax.js', 'cubicweb.widgets.js', 'jquery.treeview.js'))
       
    49         self.req.html_headers.add_onload(u"""
       
    50 jQuery("#tree-%s").treeview({toggle: toggleTree, prerendered: true});""" % treeid,
       
    51                                          jsoncall=toplevel_thru_ajax)
       
    52 
       
    53     def call(self, subvid=None, treeid=None,
       
    54              initial_load=True, initial_thru_ajax=False, **morekwargs):
    40         subvid, treeid, toplevel_thru_ajax, toplevel = self._init_params(
    55         subvid, treeid, toplevel_thru_ajax, toplevel = self._init_params(
    41             subvid, treeid, initial_load, initial_thru_ajax)
    56             subvid, treeid, initial_load, initial_thru_ajax, morekwargs)
       
    57         print 'TREEVIEW', subvid, morekwargs
    42         ulid = ' '
    58         ulid = ' '
    43         if toplevel:
    59         if toplevel:
       
    60             self._init_headers(treeid, toplevel_thru_ajax)
    44             ulid = ' id="tree-%s"' % treeid
    61             ulid = ' id="tree-%s"' % treeid
    45         self.w(u'<ul%s class="%s">' % (ulid, self.css_classes))
    62         self.w(u'<ul%s class="%s">' % (ulid, self.css_classes))
    46         for rowidx in xrange(len(self.rset)):
    63         for rowidx in xrange(len(self.rset)):
    47             self.wview(self.itemvid, self.rset, row=rowidx, col=0,
    64             self.wview(self.itemvid, self.rset, row=rowidx, col=0,
    48                        vid=subvid, parentvid=self.id, treeid=treeid)
    65                        vid=subvid, parentvid=self.id, treeid=treeid, **morekwargs)
    49         self.w(u'</ul>')
    66         self.w(u'</ul>')
    50         if toplevel:
    67 
    51             self.req.add_css('jquery.treeview.css')
    68     def cell_call(self, *args, **allargs):
    52             self.req.add_js(('cubicweb.ajax.js', 'cubicweb.widgets.js', 'jquery.treeview.js'))
    69         """ does not makes much sense until you have to invoke
    53             self.req.html_headers.add_onload(u"""
    70         somentity.view('treeview') """
    54 jQuery("#tree-%s").treeview({toggle: toggleTree, prerendered: true});""" % treeid,
    71         allargs.pop('row')
    55                                              jsoncall=toplevel_thru_ajax)
    72         allargs.pop('col')
       
    73         self.call(*args, **allargs)
    56 
    74 
    57 class FileTreeView(TreeView):
    75 class FileTreeView(TreeView):
    58     """specific version of the treeview to display file trees
    76     """specific version of the treeview to display file trees
    59     """
    77     """
    60     id = 'filetree'
    78     id = 'filetree'
    61     css_classes = 'treeview widget filetree'
    79     css_classes = 'treeview widget filetree'
    62     title = _('file tree view')
    80     title = _('file tree view')
    63 
    81 
    64     def call(self, subvid=None, treeid=None, initial_load=True):
    82     def call(self, subvid=None, treeid=None, initial_load=True, **kwargs):
    65         super(FileTreeView, self).call(treeid=treeid, subvid='filetree-oneline', initial_load=initial_load)
    83         super(FileTreeView, self).call(treeid=treeid, subvid='filetree-oneline',
       
    84                                        initial_load=initial_load, **kwargs)
    66 
    85 
    67 class FileItemInnerView(EntityView):
    86 class FileItemInnerView(EntityView):
    68     """inner view used by the TreeItemView instead of oneline view
    87     """inner view used by the TreeItemView instead of oneline view
    69 
    88 
    70     This view adds an enclosing <span> with some specific CSS classes
    89     This view adds an enclosing <span> with some specific CSS classes
   109         treestate = cookies.get(treecookiename(treeid))
   128         treestate = cookies.get(treecookiename(treeid))
   110         if treestate:
   129         if treestate:
   111             return str(eeid) in treestate.value.split(';')
   130             return str(eeid) in treestate.value.split(';')
   112         return self.default_branch_state_is_open
   131         return self.default_branch_state_is_open
   113 
   132 
   114     def cell_call(self, row, col, treeid, vid='oneline', parentvid='treeview',
   133     def cell_call(self, row, col, treeid, vid='oneline', parentvid='treeview', **morekwargs):
   115                   **kwargs):
       
   116         w = self.w
   134         w = self.w
   117         entity = self.entity(row, col)
   135         entity = self.entity(row, col)
   118         liclasses = []
   136         liclasses = []
   119         is_last = row == len(self.rset) - 1
   137         is_last = row == len(self.rset) - 1
   120         is_open = self.open_state(entity.eid, treeid)
   138         is_open = self.open_state(entity.eid, treeid)
   124                 liclasses.append('last')
   142                 liclasses.append('last')
   125             w(u'<li class="%s">' % u' '.join(liclasses))
   143             w(u'<li class="%s">' % u' '.join(liclasses))
   126         else:
   144         else:
   127             rql = entity.children_rql() % {'x': entity.eid}
   145             rql = entity.children_rql() % {'x': entity.eid}
   128             url = xml_escape(self.build_url('json', rql=rql, vid=parentvid,
   146             url = xml_escape(self.build_url('json', rql=rql, vid=parentvid,
   129                                              pageid=self.req.pageid,
   147                                             pageid=self.req.pageid,
   130                                              treeid=treeid,
   148                                             treeid=treeid,
   131                                              fname='view',
   149                                             fname='view',
   132                                              treesubvid=vid))
   150                                             treesubvid=vid,
       
   151                                             morekwargs=json.dumps(morekwargs)))
   133             divclasses = ['hitarea']
   152             divclasses = ['hitarea']
   134             if is_open:
   153             if is_open:
   135                 liclasses.append('collapsable')
   154                 liclasses.append('collapsable')
   136                 divclasses.append('collapsable-hitarea')
   155                 divclasses.append('collapsable-hitarea')
   137             else:
   156             else:
   146                     divclasses.append('lastExpandable-hitarea')
   165                     divclasses.append('lastExpandable-hitarea')
   147             if is_open:
   166             if is_open:
   148                 w(u'<li class="%s">' % u' '.join(liclasses))
   167                 w(u'<li class="%s">' % u' '.join(liclasses))
   149             else:
   168             else:
   150                 w(u'<li cubicweb:loadurl="%s" class="%s">' % (url, u' '.join(liclasses)))
   169                 w(u'<li cubicweb:loadurl="%s" class="%s">' % (url, u' '.join(liclasses)))
   151             divtail = """ onclick="asyncRemoteExec('node_clicked', '%s', '%s')" """ %\
   170             if treeid.startswith('throw_away'):
   152                 (treeid, entity.eid)
   171                 divtail = ''
       
   172             else:
       
   173                 divtail = """ onclick="asyncRemoteExec('node_clicked', '%s', '%s')" """ %\
       
   174                     (treeid, entity.eid)
   153             w(u'<div class="%s"%s></div>' % (u' '.join(divclasses), divtail))
   175             w(u'<div class="%s"%s></div>' % (u' '.join(divclasses), divtail))
   154 
   176 
   155             # add empty <ul> because jquery's treeview plugin checks for
   177             # add empty <ul> because jquery's treeview plugin checks for
   156             # sublists presence
   178             # sublists presence
   157             if not is_open:
   179             if not is_open:
   158                 w(u'<ul class="placeholder"><li>place holder</li></ul>')
   180                 w(u'<ul class="placeholder"><li>place holder</li></ul>')
   159         # the local node info
   181         # the local node info
   160         self.wview(vid, self.rset, row=row, col=col, **kwargs)
   182         self.wview(vid, self.rset, row=row, col=col, **morekwargs)
   161         if is_open and not is_leaf: #  => rql is defined
   183         if is_open and not is_leaf: #  => rql is defined
   162             self.wview(parentvid, self.req.execute(rql), treeid=treeid, initial_load=False)
   184             self.wview(parentvid, self.req.execute(rql), treeid=treeid, initial_load=False, **morekwargs)
   163         w(u'</li>')
   185         w(u'</li>')
   164 
   186