Details
- Applies to
- moin-1.5.0rc1
- Purpose
- Establish the framework to make a dropdown menu for quicklinks
- Description
Speaking to some MoinMoin users they complained that the quicklinks are a bit confusing. Starting with their suggestion to split them from the sitelinks I went a bit further: With this patch it is even possible to make a dropdown menu (so that it is possible to add hundreds of personal pages without breaking the layout)! See the following picture of the modified rightsidebar theme: If you visit a page from your quicklinks, this page is visible in the dropdown menu. In any other case you see "Quick link:". If you don't have javascript enabled, the dropdown menu behaves like the "More action:" dropdown box sporting a label and a "Go" button.
- It would be even possible to make a dropdown menu for the Wiki navigation links (if this is sensible I don't want to comment on :)!)
I hope this patch improves the usability for MoinMoin (at least for themes which make use of it...)
Moving quicklinks to a dropdown makes them one move and one click less "quick".
How? Quicklinks is a very helpful feature, but the way a user accesses his quicklinks currently is one of the most unintuitive aspects of MoinMoin. Why are quicklinks stored in a non-hyperlinked textarea? How is a person supposed to know they have to copy and paste the quicklink from their user preferences page into the base moin's base url (same for subscribed page)? Isn't a hyperlinked dropdown menu so much easier? Why aren't they listed as hyperlinks with a (remove) link next to them in the user preferences? Anyway, this dropdown menu seem like a nice familiar way of providing quick access to your quicklinks (more familiarly called bookmarks), and is a good move toward making moinmoin more user-friendly.
Patch
- This patch establishes the general framework. It should not break existing themes...
1 diff -ur moin-1.5.0rc1.orig/MoinMoin/theme/__init__.py moin-1.5.0rc1/MoinMoin/theme/__init__.py
2 --- moin-1.5.0rc1.orig/MoinMoin/theme/__init__.py 2005-12-11 22:04:10.000000000 +0100
3 +++ moin-1.5.0rc1/MoinMoin/theme/__init__.py 2006-01-07 22:02:03.000000000 +0100
4 @@ -227,8 +227,10 @@
5 if request.user.valid:
6 userlinks.append("""\
7 <form action="" method="POST">
8 +<div>
9 <input type="hidden" name="action" value="userform">
10 <input type="submit" name="logout" value="%(logout)s">
11 +</div>
12 </form>
13 """ % { 'logout': _('Logout') })
14 else:
15 @@ -359,28 +361,14 @@
16 current = d['page_name']
17
18 # Process config navi_bar
19 - if request.cfg.navi_bar:
20 - for text in request.cfg.navi_bar:
21 - pagename, link = self.splitNavilink(text)
22 - if pagename == current:
23 - cls = 'wikilink current'
24 - else:
25 - cls = 'wikilink'
26 - items.append(item % (cls, link))
27 - found[pagename] = 1
28 + (items_found, pages_found) = self.config_navibar(d)
29 + items.extend([item % (i[2], i[0]) for i in items_found])
30 + found.update(pages_found)
31
32 # Add user links to wiki links, eliminating duplicates.
33 - userlinks = request.user.getQuickLinks()
34 - for text in userlinks:
35 - # Split text without localization, user knows what he wants
36 - pagename, link = self.splitNavilink(text, localize=0)
37 - if not pagename in found:
38 - if pagename == current:
39 - cls = 'userlink current'
40 - else:
41 - cls = 'userlink'
42 - items.append(item % (cls, link))
43 - found[pagename] = 1
44 + (items_found, pages_found) = self.user_navibar(d)
45 + items.extend([item % (i[2], i[0]) for i in items_found])
46 + found.update(pages_found)
47
48 # Add current page at end
49 if not current in found:
50 @@ -399,6 +387,57 @@
51 ''' % items
52 return html
53
54 + def config_navibar(self,d):
55 + """ Get the links from the configfile for the navibar
56 +
57 + @param d: parameter dictionary
58 + @rtype: unicode
59 + @return: list with navibar items from config, dictionary with found page
60 + """
61 + navi_bar = self.request.cfg.navi_bar
62 + found = {} # pages we found. prevent duplicates
63 + items = [] # navibar items
64 + current = d['page_name']
65 +
66 + # Process config navi_bar
67 + if navi_bar:
68 + for text in navi_bar:
69 + pagename, link = self.splitNavilink(text)
70 + if pagename == current:
71 + cls = 'wikilink current'
72 + else:
73 + cls = 'wikilink'
74 + items.append((link, pagename, cls))
75 + found[pagename] = 1
76 +
77 + return items, found
78 +
79 + def user_navibar(self,d):
80 + """ Get the quick links for the navibar
81 +
82 + @param d: parameter dictionary
83 + @rtype: unicode
84 + @return: list with navibar items, dictionary with found page
85 + """
86 + found = {} # pages we found. prevent duplicates
87 + items = [] # navibar items
88 + current = d['page_name']
89 +
90 + # Add user links to wiki links, eliminating duplicates.
91 + userlinks = self.request.user.getQuickLinks()
92 + for text in userlinks:
93 + # Split text without localization, user knows what he wants
94 + pagename, link = self.splitNavilink(text, localize=0)
95 + if not pagename in found:
96 + if pagename == current:
97 + cls = 'userlink current'
98 + else:
99 + cls = 'userlink'
100 + items.append((link, pagename, cls))
101 + found[pagename] = 1
102 +
103 + return (items, found)
104 +
105 def get_icon(self, icon):
106 """ Return icon data from self.icons
107
108 @@ -759,11 +798,11 @@
109 }
110 }
111
112 -function actionsMenuInit(title) {
113 - // Initialize action menu
114 +function menuInit(menu, title) {
115 + // Initialize a menu
116 for (i = 0; i < document.forms.length; i++) {
117 var form = document.forms[i];
118 - if (form.className == 'actionsmenu') {
119 + if (form.className == menu) {
120 // Check if this form needs update
121 var div = form.getElementsByTagName('div')[0];
122 var label = div.getElementsByTagName('label')[0];
123 @@ -778,11 +817,22 @@
124 item.appendChild(document.createTextNode(title));
125 item.value = 'show';
126 select.insertBefore(item, select.options[0]);
127 - select.selectedIndex = 0;
128 + // If there is no options with the selected attribute, we
129 + // don't want to select the newly added first item.
130 + // (We take a shortcut and do not loop over every item!)
131 + if (!select.options[select.selectedIndex].defaultSelected)
132 + select.selectedIndex = 0;
133 }
134 }
135 }
136 }
137 +
138 +function actionsMenuInit(title) {
139 + // Initialize action menu
140 + // This function is replaced by menuInit(), which can initialize
141 + // any menu. It remains here for backward compatibility.
142 + menuInit('actionsmenu', title);
143 +}
144 //-->
145 </script>
146 """ % {
- The following patch shows how you implement to above mentioned rightsidebar theme with dropdown menu.
1 diff -ur moin-1.5.0rc1.orig/MoinMoin/theme/rightsidebar.py moin-1.5.0rc1/MoinMoin/theme/rightsidebar.py
2 --- moin-1.5.0rc1.orig/MoinMoin/theme/rightsidebar.py 2005-12-12 20:14:38.000000000 +0100
3 +++ moin-1.5.0rc1/MoinMoin/theme/rightsidebar.py 2006-01-07 21:58:44.000000000 +0100
4 @@ -18,12 +18,52 @@
5 def wikipanel(self, d):
6 """ Create wiki panel """
7 _ = self.request.getText
8 - html = [
9 - u'<div class="sidepanel">',
10 - u'<h1>%s</h1>' % _("Wiki"),
11 - self.navibar(d),
12 - u'</div>',
13 - ]
14 + html = []
15 + navibar = self.config_navibar(d)[0]
16 + if navibar:
17 + html.extend([
18 + u'<div class="sidepanel">',
19 + u'<h1>%s</h1>' % _("Wiki"),
20 + u'<ul id="navibar">'])
21 + html.extend([
22 + u'<li class="%s">%s</li>' % (i[2], i[0]) for i in navibar])
23 + html.extend([
24 + u'</ul>',
25 + u'</div>',
26 + u''])
27 + navibar = self.user_navibar(d)[0]
28 + if navibar:
29 + html.extend([
30 + u'<div class="sidepanel">',
31 + u'<h1>%s</h1>' % _("Quick links"),
32 + u'<ul class="editbar">',
33 + u'<li>',
34 + u'<form class="quicklinksmenu" method="get" action="">',
35 + u'<div>',
36 + u' <label>%s:</label>' % _("Go To Page"),
37 + u' <select name="goto"',
38 + u' onchange="window.location=this.options[selectedIndex].value;">'])
39 + for i in navibar:
40 + if i[2] == 'userlink current':
41 + selected = u'selected="selected"'
42 + else:
43 + selected = u''
44 + html.extend([
45 + u' <option value="%s" %s>%s</option>' % (i[1], selected, i[1])])
46 + html.extend([
47 + u' </select>',
48 + u' <input type="submit" value="%s">' % _("Do"),
49 + u'</div>',
50 + u'<script type="text/javascript">',
51 + u'<!--// Init menu',
52 + u'menuInit(\'quicklinksmenu\', \'%s:\')' % _("Quick links"),
53 + u'-->',
54 + u'</script>',
55 + u'</form>',
56 + u'</li>',
57 + u'</ul>',
58 + u'</div',
59 + u''])
60 return u'\n'.join(html)
61
62 def pagepanel(self, d):
quicklinksmenu_rightsidebar.patch
Discussion
Very, very good idea. I was thinking the same thing because the current method of listing quicklinks (and subscribed pages in user preferences) in a textarea is VERY non-intuitive.. The quicklinks in current MoinMoin functionally work, but it seems silly to only list them as text in a non-hyperlinked textarea. I'm going to try to implement this. This should really be the standard interface. The "Subscribed" pages should be the same way. They should be displayed as hyperlinks in the User Preference with a (remove) tag, instead of listing the subscriptions in a non-hyperlinked text area. Thanks you! - RyanK
Plan
- Priority:
- Assigned to:
- Status: