1 from logilab.mtconverter import html_escape |
1 from logilab.mtconverter import html_escape |
2 |
|
3 from cubicweb.interfaces import ITree |
2 from cubicweb.interfaces import ITree |
4 from cubicweb.common.selectors import implement_interface, yes |
3 from cubicweb.common.selectors import implement_interface, yes |
5 from cubicweb.common.view import EntityView |
4 from cubicweb.common.view import EntityView |
6 |
|
7 from cubicweb.web.views.baseviews import OneLineView |
|
8 |
5 |
9 class TreeView(EntityView): |
6 class TreeView(EntityView): |
10 id = 'treeview' |
7 id = 'treeview' |
11 accepts = ('Any',) |
8 accepts = ('Any',) |
12 itemvid = 'treeitemview' |
9 itemvid = 'treeitemview' |
13 css_classes = 'treeview widget' |
10 css_classes = 'treeview widget' |
14 title = _('tree view') |
11 title = _('tree view') |
15 |
12 |
16 def call(self, subvid=None): |
13 def call(self, subvid=None, treeid=None): |
17 if subvid is None and 'subvid' in self.req.form: |
14 if subvid is None and 'subvid' in self.req.form: |
18 subvid = self.req.form.pop('subvid') # consume it |
15 subvid = self.req.form.pop('subvid') # consume it |
19 if subvid is None: |
16 if subvid is None: |
20 subvid = 'oneline' |
17 subvid = 'oneline' |
21 self.req.add_css('jquery.treeview.css') |
18 self.req.add_css('jquery.treeview.css') |
22 self.req.add_js(('cubicweb.ajax.js', 'jquery.treeview.js', 'cubicweb.widgets.js')) |
19 self.req.add_js(('cubicweb.ajax.js', 'jquery.treeview.js')) |
23 # XXX noautoload is a quick hack to avoid treeview to be rebuilt |
20 # XXX find a way, an id is MANDATORY |
24 # after a json query and avoid double toggling bugs. |
21 treeid = 'TREE' #treeid or self.rset.rows[0][0] |
25 # Need to find a way to do that cleanly. |
22 self.req.html_headers.add_onload(u""" |
26 if 'noautoload' in self.req.form: |
23 $("#tree-%s").treeview({toggle: toggleTree, |
27 self.w(u'<ul class="%s" cubicweb:wdgtype="TreeView">' % self.css_classes) |
24 prerendered: true});""" % treeid) |
28 else: |
25 self.w(u'<ul id="tree-%s" class="%s">' % (treeid, self.css_classes)) |
29 self.w(u'<ul class="%s" cubicweb:loadtype="auto" cubicweb:wdgtype="TreeView">' |
|
30 % self.css_classes) |
|
31 for rowidx in xrange(len(self.rset)): |
26 for rowidx in xrange(len(self.rset)): |
32 self.wview(self.itemvid, self.rset, row=rowidx, col=0, |
27 self.wview(self.itemvid, self.rset, row=rowidx, col=0, |
33 vid=subvid, parentvid=self.id) |
28 vid=subvid, parentvid=self.id) |
34 self.w(u'</ul>') |
29 self.w(u'</ul>') |
35 |
|
36 |
30 |
37 class FileTreeView(TreeView): |
31 class FileTreeView(TreeView): |
38 """specific version of the treeview to display file trees |
32 """specific version of the treeview to display file trees |
39 """ |
33 """ |
40 id = 'filetree' |
34 id = 'filetree' |
41 css_classes = 'treeview widget filetree' |
35 css_classes = 'treeview widget filetree' |
42 title = _('file tree view') |
36 title = _('file tree view') |
43 |
37 |
44 def call(self, subvid=None): |
38 def call(self, subvid=None): |
45 super(FileTreeView, self).call(subvid='filetree-oneline') |
39 super(FileTreeView, self).call(subvid='filetree-oneline') |
46 |
|
47 |
|
48 |
40 |
49 class FileItemInnerView(EntityView): |
41 class FileItemInnerView(EntityView): |
50 """inner view used by the TreeItemView instead of oneline view |
42 """inner view used by the TreeItemView instead of oneline view |
51 |
43 |
52 This view adds an enclosing <span> with some specific CSS classes |
44 This view adds an enclosing <span> with some specific CSS classes |
55 id = 'filetree-oneline' |
47 id = 'filetree-oneline' |
56 |
48 |
57 def cell_call(self, row, col): |
49 def cell_call(self, row, col): |
58 entity = self.entity(row, col) |
50 entity = self.entity(row, col) |
59 if ITree.is_implemented_by(entity.__class__) and not entity.is_leaf(): |
51 if ITree.is_implemented_by(entity.__class__) and not entity.is_leaf(): |
60 self.w(u'<div class="folder">%s</div>' % entity.view('oneline')) |
52 self.w(u'<div class="folder">%s</div>\n' % entity.view('oneline')) |
61 else: |
53 else: |
62 # XXX define specific CSS classes according to mime types |
54 # XXX define specific CSS classes according to mime types |
63 self.w(u'<div class="file">%s</div>' % entity.view('oneline')) |
55 self.w(u'<div class="file">%s</div>\n' % entity.view('oneline')) |
64 |
56 |
65 |
57 |
66 class DefaultTreeViewItemView(EntityView): |
58 class DefaultTreeViewItemView(EntityView): |
67 """default treeitem view for entities which don't implement ITree |
59 """default treeitem view for entities which don't implement ITree |
68 """ |
60 """ |
69 id = 'treeitemview' |
61 id = 'treeitemview' |
70 accepts = ('Any',) |
62 accepts = ('Any',) |
71 |
63 |
72 def cell_call(self, row, col, vid='oneline', parentvid='treeview'): |
64 def cell_call(self, row, col, vid='oneline', parentvid='treeview'): |
73 entity = self.entity(row, col) |
65 entity = self.entity(row, col) |
74 itemview = self.view(vid, self.rset, row=row, col=col) |
66 itemview = self.view(vid, self.rset, row=row, col=col) |
75 if row == len(self.rset) - 1: |
67 if row == len(self.rset) - 1: |
76 self.w(u'<li class="last">%s</li>' % itemview) |
68 self.w(u'<li class="last">%s</li>' % itemview) |
78 self.w(u'<li>%s</li>' % itemview) |
70 self.w(u'<li>%s</li>' % itemview) |
79 |
71 |
80 |
72 |
81 class TreeViewItemView(EntityView): |
73 class TreeViewItemView(EntityView): |
82 """specific treeitem view for entities which implement ITree |
74 """specific treeitem view for entities which implement ITree |
83 |
75 |
84 (each item should be exandable if it's not a tree leaf) |
76 (each item should be exandable if it's not a tree leaf) |
85 """ |
77 """ |
86 id = 'treeitemview' |
78 id = 'treeitemview' |
87 # XXX append yes to make sure we get an higher score than |
79 # XXX append yes to make sure we get an higher score than |
88 # the default treeitem view |
80 # the default treeitem view |
89 __selectors__ = (implement_interface, yes) |
81 __selectors__ = (implement_interface, yes) |
90 accepts_interfaces = (ITree,) |
82 accepts_interfaces = (ITree,) |
91 |
83 opening = 'man_a/a1'.split('/') |
|
84 |
92 def cell_call(self, row, col, vid='oneline', parentvid='treeview'): |
85 def cell_call(self, row, col, vid='oneline', parentvid='treeview'): |
|
86 w = self.w |
93 entity = self.entity(row, col) |
87 entity = self.entity(row, col) |
94 cssclasses = [] |
88 liclasses = [] |
95 is_leaf = False |
89 is_leaf = False |
|
90 is_open = entity.name in self.opening |
96 if row == len(self.rset) - 1: |
91 if row == len(self.rset) - 1: |
97 is_leaf = True |
92 is_leaf = True |
98 if not hasattr(entity, 'is_leaf') or entity.is_leaf(): |
93 if not hasattr(entity, 'is_leaf') or entity.is_leaf(): |
99 if is_leaf : cssclasses.append('last') |
94 if is_leaf : liclasses.append('last') |
100 self.w(u'<li class="%s">' % u' '.join(cssclasses)) |
95 w(u'<li class="%s">' % u' '.join(liclasses)) |
101 else: |
96 else: |
102 rql = entity.children_rql() % {'x': entity.eid} |
97 rql = entity.children_rql() % {'x': entity.eid} |
103 url = html_escape(self.build_url('json', rql=rql, vid=parentvid, |
98 url = html_escape(self.build_url('json', rql=rql, vid=parentvid, |
104 pageid=self.req.pageid, |
99 pageid=self.req.pageid, |
105 subvid=vid, |
100 subvid=vid, |
106 noautoload=True)) |
101 noautoload=True)) |
107 cssclasses.append('expandable') |
102 if is_open: |
108 divclasses = ['hitarea expandable-hitarea'] |
103 liclasses.append('collapsable') |
109 if is_leaf : |
104 else: |
110 cssclasses.append('lastExpandable') |
105 liclasses.append('expandable') |
111 divclasses.append('lastExpandable-hitarea') |
106 divclasses = ['hitarea'] |
112 self.w(u'<li cubicweb:loadurl="%s" class="%s">' % (url, u' '.join(cssclasses))) |
107 if is_open: |
113 self.w(u'<div class="%s"> </div>' % u' '.join(divclasses)) |
108 divclasses.append('collapsable-hitarea') |
114 |
109 else: |
|
110 divclasses.append('expandable-hitarea') |
|
111 if is_leaf: |
|
112 liclasses.append('lastExpandable') |
|
113 if not is_open: |
|
114 divclasses.append('lastExpandable-hitarea') |
|
115 if is_open: |
|
116 w(u'<li class="%s">' % u' '.join(liclasses)) |
|
117 else: |
|
118 w(u'<li cubicweb:loadurl="%s" class="%s">' % (url, u' '.join(liclasses))) |
|
119 w(u'<div class="%s"> </div>' % u' '.join(divclasses)) |
|
120 |
115 # add empty <ul> because jquery's treeview plugin checks for |
121 # add empty <ul> because jquery's treeview plugin checks for |
116 # sublists presence |
122 # sublists presence |
117 self.w(u'<ul class="placeholder"><li>place holder</li></ul>') |
123 if not is_open: |
|
124 w(u'<ul class="placeholder"><li>place holder</li></ul>') |
|
125 # the local node info |
118 self.wview(vid, self.rset, row=row, col=col) |
126 self.wview(vid, self.rset, row=row, col=col) |
119 self.w(u'</li>') |
127 if is_open: # recurse if needed |
120 |
128 self.wview(parentvid, self.req.execute(rql)) |
|
129 w(u'</li>') |