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.

modified_rightsidebar.png

I hope this patch improves the usability for MoinMoin (at least for themes which make use of it...)

Patch

   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  """ % {
quicklinksmenu.patch

   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


MoinMoin: MoinMoinPatch/QuicklinksMenu (last edited 2007-10-29 19:11:01 by localhost)