1 """base classes to handle tabbed views |
1 """base classes to handle tabbed views |
2 |
2 |
3 :organization: Logilab |
3 :organization: Logilab |
4 :copyright: 2008-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved. |
4 :copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved. |
5 :contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr |
5 :contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr |
6 """ |
6 """ |
7 |
7 |
8 __docformat__ = "restructuredtext en" |
8 __docformat__ = "restructuredtext en" |
9 |
9 |
10 from logilab.common.decorators import monkeypatch |
10 from logilab.common.decorators import monkeypatch |
11 from logilab.mtconverter import html_escape |
11 from logilab.mtconverter import html_escape |
12 |
12 |
13 from cubicweb import NoSelectableObject, role |
13 from cubicweb import NoSelectableObject, role |
14 from cubicweb.common.view import EntityView |
14 from cubicweb.common.view import EntityView |
15 from cubicweb.common.selectors import has_related_entities |
15 from cubicweb.common.selectors import has_related_entities |
16 from cubicweb.common.utils import HTMLHead |
16 from cubicweb.common.utils import HTMLHead |
17 from cubicweb.common.uilib import rql_for_eid |
17 from cubicweb.common.uilib import rql_for_eid |
18 |
18 |
19 from cubicweb.web.views.basecontrollers import JSonController |
19 from cubicweb.web.views.basecontrollers import JSonController |
31 jQuery('#lazy-%(vid)s').bind('%(event)s', function(event) { |
31 jQuery('#lazy-%(vid)s').bind('%(event)s', function(event) { |
32 load_now('#lazy-%(vid)s', '#%(vid)s-hole', %(reloadable)s); |
32 load_now('#lazy-%(vid)s', '#%(vid)s-hole', %(reloadable)s); |
33 });""" % {'event': 'load_%s' % vid, 'vid': vid, |
33 });""" % {'event': 'load_%s' % vid, 'vid': vid, |
34 'reloadable' : str(reloadable).lower()}) |
34 'reloadable' : str(reloadable).lower()}) |
35 |
35 |
36 def lazyview(self, vid, eid=None, reloadable=False, show_spinbox=True, w=None): |
36 def lazyview(self, vid, rql=None, eid=None, rset=None, static=False, |
|
37 reloadable=False, show_spinbox=True, w=None): |
37 """a lazy version of wview |
38 """a lazy version of wview |
38 first version only support lazy viewing for an entity at a time |
39 first version only support lazy viewing for an entity at a time |
39 """ |
40 """ |
|
41 assert rql or eid or rset or static, \ |
|
42 'lazyview wants at least : rql, or an eid, or an rset -- or call it with static=True' |
40 w = w or self.w |
43 w = w or self.w |
41 self.req.add_js('cubicweb.lazy.js') |
44 self.req.add_js('cubicweb.lazy.js') |
42 urlparams = {'vid' : vid, 'mode' : 'html'} |
45 urlparams = {'vid' : vid, 'mode' : 'html'} |
43 if eid: |
46 if rql: |
|
47 urlparams['rql'] = rql |
|
48 elif eid: |
44 urlparams['rql'] = rql_for_eid(eid) |
49 urlparams['rql'] = rql_for_eid(eid) |
|
50 elif rset: |
|
51 urlparams['rql'] = rset.printable_rql() |
45 w(u'<div id="lazy-%s" cubicweb:loadurl="%s">' % ( |
52 w(u'<div id="lazy-%s" cubicweb:loadurl="%s">' % ( |
46 vid, html_escape(self.build_url('json', **urlparams)))) |
53 vid, html_escape(self.build_url('json', **urlparams)))) |
47 if show_spinbox: |
54 if show_spinbox: |
48 w(u'<img src="data/loading.gif" id="%s-hole" alt="%s"/>' |
55 w(u'<img src="data/loading.gif" id="%s-hole" alt="%s"/>' |
49 % (vid, self.req._('loading'))) |
56 % (vid, self.req._('loading'))) |
63 @property |
70 @property |
64 def cookie_name(self): |
71 def cookie_name(self): |
65 return str('%s_active_tab' % self.config.appid) |
72 return str('%s_active_tab' % self.config.appid) |
66 |
73 |
67 def active_tab(self, tabs, default): |
74 def active_tab(self, tabs, default): |
68 cookie = self.req.get_cookie() |
75 cookies = self.req.get_cookie() |
69 cookiename = self.cookie_name |
76 cookiename = self.cookie_name |
70 activetab = cookie.get(cookiename) |
77 activetab = cookies.get(cookiename) |
71 if activetab is None: |
78 if activetab is None: |
72 cookie[cookiename] = default |
79 cookies[cookiename] = default |
73 self.req.set_cookie(cookie, cookiename) |
80 self.req.set_cookie(cookies, cookiename) |
74 tab = default |
81 tab = default |
75 else: |
82 else: |
76 tab = activetab.value |
83 tab = activetab.value |
77 return tab in tabs and tab or default |
84 return tab in tabs and tab or default |
78 |
85 |
99 tabs = self.prune_tabs(tabs) |
106 tabs = self.prune_tabs(tabs) |
100 # select a tab |
107 # select a tab |
101 active_tab = self.active_tab(tabs, default) |
108 active_tab = self.active_tab(tabs, default) |
102 # build the html structure |
109 # build the html structure |
103 w = self.w |
110 w = self.w |
104 w(u'<div id="entity-tabs">') |
111 w(u'<div id="entity-tabs-%s">' % entity.eid) |
105 w(u'<ul>') |
112 w(u'<ul>') |
106 for tab in tabs: |
113 for tab in tabs: |
107 w(u'<li>') |
114 w(u'<li>') |
108 w(u'<a href="#as-%s">' % tab) |
115 w(u'<a href="#as-%s">' % tab) |
109 w(u'<span onclick="set_tab(\'%s\', \'%s\')">' % (tab, self.cookie_name)) |
116 w(u'<span onclick="set_tab(\'%s\', \'%s\')">' % (tab, self.cookie_name)) |
113 w(u'</li>') |
120 w(u'</li>') |
114 w(u'</ul>') |
121 w(u'</ul>') |
115 w(u'</div>') |
122 w(u'</div>') |
116 for tab in tabs: |
123 for tab in tabs: |
117 w(u'<div id="as-%s">' % tab) |
124 w(u'<div id="as-%s">' % tab) |
118 self.lazyview(tab, entity.eid) |
125 self.lazyview(tab, eid=entity.eid) |
119 w(u'</div>') |
126 w(u'</div>') |
120 # call the set_tab() JS function *after* each tab is generated |
127 # call the set_tab() JS function *after* each tab is generated |
121 # because the callback binding needs to be done before |
128 # because the callback binding needs to be done before |
122 self.req.html_headers.add_onload(u""" |
129 self.req.html_headers.add_onload(u""" |
123 jQuery('#entity-tabs > ul').tabs( { selected: %(tabindex)s }); |
130 jQuery('#entity-tabs-%(eeid)s > ul').tabs( { selected: %(tabindex)s }); |
124 set_tab('%(vid)s', '%(cookiename)s'); |
131 set_tab('%(vid)s', '%(cookiename)s'); |
125 """ % {'tabindex' : tabs.index(active_tab), |
132 """ % {'tabindex' : tabs.index(active_tab), |
126 'vid' : active_tab, |
133 'vid' : active_tab, |
|
134 'eeid' : entity.eid, |
127 'cookiename' : self.cookie_name}) |
135 'cookiename' : self.cookie_name}) |
128 |
136 |
129 |
137 |
130 class EntityRelatedTab(EntityView): |
138 class EntityRelatedTab(EntityView): |
131 """A view you should inherit from leftmost, |
139 """A view you should inherit from leftmost, |
141 rtype = 'screenshot' |
149 rtype = 'screenshot' |
142 target = 'object' |
150 target = 'object' |
143 vid = 'gallery' |
151 vid = 'gallery' |
144 __selectors__ = EntityRelationView.__selectors__ + (one_line_rset,) |
152 __selectors__ = EntityRelationView.__selectors__ + (one_line_rset,) |
145 |
153 |
146 |
|
147 This is the view we want to have in a tab, only if there is something to show. |
154 This is the view we want to have in a tab, only if there is something to show. |
148 Then, just define as below, and declare this being the tab content : |
155 Then, just define as below, and declare this being the tab content : |
149 |
156 |
150 class ProjectScreenshotTab(DataDependantTab, ProjectScreenshotsView): |
157 class ProjectScreenshotTab(EntityRelatedTab, ProjectScreenshotsView): |
151 id = 'screenshots_tab' |
158 id = 'screenshots_tab' |
152 """ |
159 """ |
153 __selectors__ = EntityView.__selectors__ + (has_related_entities,) |
160 __selectors__ = EntityView.__selectors__ + (has_related_entities,) |
154 vid = 'list' |
161 vid = 'list' |
155 |
162 |