Aleksander Machniak
2014-08-08 66233b76c83b8e31bc1ff301352393299130a18c
Added folder searching in Folder Manager
12 files modified
168 ■■■■■ changed files
CHANGELOG 1 ●●●● patch | view | raw | blame | history
program/js/app.js 4 ●●● patch | view | raw | blame | history
program/js/treelist.js 3 ●●●● patch | view | raw | blame | history
program/localization/en_US/labels.inc 24 ●●●●● patch | view | raw | blame | history
skins/classic/common.css 19 ●●●●● patch | view | raw | blame | history
skins/classic/functions.js 35 ●●●●● patch | view | raw | blame | history
skins/classic/settings.css 10 ●●●●● patch | view | raw | blame | history
skins/classic/templates/folders.html 12 ●●●●● patch | view | raw | blame | history
skins/larry/settings.css 13 ●●●●● patch | view | raw | blame | history
skins/larry/styles.css 1 ●●●● patch | view | raw | blame | history
skins/larry/templates/folders.html 14 ●●●●● patch | view | raw | blame | history
skins/larry/ui.js 32 ●●●●● patch | view | raw | blame | history
CHANGELOG
@@ -1,6 +1,7 @@
CHANGELOG Roundcube Webmail
===========================
- Added folder searching in Folder Manager
- Added config option 'imap_log_session' to enable Roundcube <-> IMAP session ID logging
- Added config option 'log_session_id' to control the lengh of the session identifer in logs
- Implemented 'storage_connected' API hook after successful IMAP login (#1490025)
program/js/app.js
@@ -5743,13 +5743,15 @@
        selectable: true,
        id_prefix: 'rcmli',
        id_encode: this.html_identifier_encode,
        id_decode: this.html_identifier_decode
        id_decode: this.html_identifier_decode,
        searchbox: '#foldersearch'
    });
    this.subscription_list
      .addEventListener('select', function(node) { ref.subscription_select(node.id); })
      .addEventListener('collapse', function(node) { ref.folder_collapsed(node) })
      .addEventListener('expand', function(node) { ref.folder_collapsed(node) })
      .addEventListener('search', function(p) { if (p.query) ref.subscription_select(); })
      .draggable({cancel: 'li.mailbox.root'})
      .droppable({
        // @todo: find better way, accept callback is executed for every folder
program/js/treelist.js
@@ -525,7 +525,8 @@
            .attr('id', li.attr('id') + '--xsR')
            .attr('class', li.attr('class'))
            .addClass('searchresult__')
            .append(li.children().first().clone(true, true))
            // append all elements like links and inputs, but not sub-trees
            .append(li.children(':not(div.treetoggle,ul)').clone(true, true))
            .appendTo(container);
            hits.push(node.id);
        }
program/localization/en_US/labels.inc
@@ -528,14 +528,14 @@
$labels['replyalldefault'] = 'reply to all';
$labels['replyalllist'] = 'reply to mailing list only (if found)';
$labels['folder']  = 'Folder';
$labels['folders']  = 'Folders';
$labels['foldername']  = 'Folder name';
$labels['subscribed']  = 'Subscribed';
$labels['folder'] = 'Folder';
$labels['folders'] = 'Folders';
$labels['foldername'] = 'Folder name';
$labels['subscribed'] = 'Subscribed';
$labels['messagecount'] = 'Messages';
$labels['create']  = 'Create';
$labels['createfolder']  = 'Create new folder';
$labels['managefolders']  = 'Manage folders';
$labels['create'] = 'Create';
$labels['createfolder'] = 'Create new folder';
$labels['managefolders'] = 'Manage folders';
$labels['specialfolders'] = 'Special Folders';
$labels['properties'] = 'Properties';
$labels['folderproperties'] = 'Folder properties';
@@ -545,9 +545,10 @@
$labels['getfoldersize'] = 'Click to get folder size';
$labels['changesubscription'] = 'Click to change subscription';
$labels['foldertype'] = 'Folder Type';
$labels['personalfolder']  = 'Private Folder';
$labels['otherfolder']  = 'Other User\'s Folder';
$labels['sharedfolder']  = 'Public Folder';
$labels['personalfolder'] = 'Private Folder';
$labels['otherfolder'] = 'Other User\'s Folder';
$labels['sharedfolder'] = 'Public Folder';
$labels['findfolders'] = 'Find folders';
$labels['sortby'] = 'Sort by';
$labels['sortasc']  = 'Sort ascending';
@@ -597,6 +598,8 @@
$labels['arialabelcontactsearchform'] = 'Contacts search form';
$labels['arialabelmailquicksearchbox'] = 'Email search input';
$labels['arialabelquicksearchbox'] = 'Search input';
$labels['arialabelfoldersearchfilter'] = 'Folder listing filter';
$labels['arialabelfoldersearchform'] = 'Folder search form';
$labels['arialabelfolderlist'] = 'Email folder selection';
$labels['arialabelmessagelist'] = 'Email Messages Listing';
$labels['arialabelmailpreviewframe'] = 'Message preview';
@@ -625,6 +628,7 @@
$labels['arialabelpreferencesform'] = 'Preferences form';
$labels['arialabelidentityeditfrom'] = 'Identity edit form';
$labels['arialabelresonseeditfrom'] = 'Response edit form';
$labels['arialabelsearchterms'] = 'Search terms';
$labels['helplistnavigation'] = 'List keyboard navigation';
$labels['helplistkeyboardnavigation'] = "Arrows up/down: Move row focus/selection.
skins/classic/common.css
@@ -1010,6 +1010,25 @@
  width: 97%;
}
.listsearchbox
{
  border-bottom: solid 1px #ddd;
  padding: 2px 4px 1px;
  display: none;
  background-color: #f2f2f2;
}
.listsearchbox a.iconbutton.reset
{
  background: url(images/icons/reset.gif) no-repeat 0 0;
  width: 13px;
  height: 13px;
  text-indent: 50000px;
  position: absolute;
  top: 3px;
  left: 165px;
  overflow: hidden;
}
/***** roundcube webmail pre-defined classes *****/
skins/classic/functions.js
@@ -636,6 +636,36 @@
    var label = rcmail.gettext(p.status ? 'replylist' : 'replyall');
    $('a.button.replyAll').attr('title', label);
  }
},
folder_search_init: function(container)
{
  // animation to unfold list search box
  $('.boxtitle a.search', container).click(function(e) {
    var title = $('.boxtitle', container),
      box = $('.listsearchbox', container),
      dir = box.is(':visible') ? -1 : 1;
    box.slideToggle({
      duration: 160,
      progress: function(animation, progress) {
        if (dir < 0) progress = 1 - progress;
          $('.boxlistcontent', container).css('top', (title.outerHeight() + 24 * progress) + 'px');
      },
      complete: function() {
        box.toggleClass('expanded');
        if (box.is(':visible')) {
          box.find('input[type=text]').focus();
        }
        else {
          $('a.reset', box).click();
        }
        // TODO: save state in cookie
      }
    });
    return false;
  });
}
};
@@ -1012,5 +1042,10 @@
      rcmail.addEventListener('afterupload-photo', function(){ rcmail_ui.show_popup('uploadform', false); })
        .gui_object('dragmenu', 'dragmenu');
    }
    else if (rcmail.env.task == 'settings') {
      if (rcmail.env.action == 'folders') {
        rcmail_ui.folder_search_init($('#folder-manager'));
      }
    }
  });
}
skins/classic/settings.css
@@ -11,6 +11,16 @@
  background-color: #FFFFA6;
}
#folderlist-title a.iconbutton.search {
  background: url(images/icons/glass.png) no-repeat 0 0;
  cursor: pointer;
  position: absolute;
  right: 4px;
  top: 2px;
  width: 16px;
  text-indent: 50000px;
}
#identities-table,
#sections-table
{
skins/classic/templates/folders.html
@@ -19,7 +19,17 @@
<div id="mainscreen">
<div id="folder-manager">
<div id="folderlist-title" class="boxtitle"><span class="rightalign"><roundcube:label name="subscribed" /></span><roundcube:label name="folders" /></div>
<div id="folderlist-title" class="boxtitle">
    <roundcube:label name="folders" />
    <a href="#folders" class="iconbutton search" title="<roundcube:label name='findfolders' />" tabindex="0"><roundcube:label name='findfolders' /></a>
</div>
<div class="listsearchbox">
    <div class="searchbox" role="search">
        <input type="text" name="q" id="foldersearch" placeholder="<roundcube:label name='findfolders' />" />
        <a class="iconbutton searchicon"></a>
        <roundcube:button command="reset-foldersearch" id="folderlistsearch-reset" class="iconbutton reset" title="resetsearch" width="13" height="13" />
    </div>
</div>
<div id="folderlist-content" class="boxlistcontent">
    <roundcube:object name="foldersubscription" form="subscriptionform" id="subscription-table"
        summary="Folder subscription table" class="treelist folderlist" />
skins/larry/settings.css
@@ -211,6 +211,19 @@
    background-position: 4px -550px;
}
#folderslist .boxtitle a.iconbutton.search {
    background-position: -2px -317px;
    cursor: pointer;
    position: absolute;
    right: 8px;
    top: 8px;
    width: 16px;
}
#folderslist .listsearchbox + .scroller {
    top: 34px;
}
#folderslist,
#identitieslist {
    position: absolute;
skins/larry/styles.css
@@ -1959,6 +1959,7 @@
    position: relative;
    padding: 4px;
    background: #c7e3ef;
    display: none;
}
.listsearchbox input {
skins/larry/templates/folders.html
@@ -17,7 +17,19 @@
<div id="settings-right" role="main">
<div id="folderslist" class="uibox listbox">
<h2 id="folderslist-header" class="boxtitle"><span style="float:right"><roundcube:label name="subscribed" /></span><roundcube:label name="folders" /></h2>
<h2 id="folderslist-header" class="boxtitle">
    <roundcube:label name="folders" />
    <a href="#folders" class="iconbutton search" title="<roundcube:label name='findfolders' />" tabindex="0"><roundcube:label name='findfolders' /></a>
</h2>
<div class="listsearchbox">
    <div class="searchbox" role="search" aria-labelledby="aria-label-foldersearchform">
        <h3 id="aria-label-foldersearchform" class="voice"><roundcube:label name="arialabelfoldersearchform" /></h3>
        <label for="foldersearch" class="voice"><roundcube:label name="arialabelsearchterms" /></label>
        <input type="text" name="q" id="foldersearch" placeholder="<roundcube:label name='findfolders' />" />
        <a class="iconbutton searchicon"></a>
        <roundcube:button command="reset-foldersearch" id="folderlistsearch-reset" class="iconbutton reset" title="resetsearch" label="resetsearch" />
    </div>
</div>
<div id="folderslist-content" class="scroller withfooter">
    <roundcube:object name="foldersubscription" form="subscriptionform" id="subscription-table" class="treelist listing folderlist" />
</div>
skins/larry/ui.js
@@ -47,6 +47,7 @@
  this.update_quota = update_quota;
  this.get_pref = get_pref;
  this.save_pref = save_pref;
  this.folder_search_init = folder_search_init;
  // set minimal mode on small screens (don't wait for document.ready)
@@ -255,6 +256,8 @@
          orientation:'v', relative:true, start:266, min:180, size:12 }).init();
        rcmail.addEventListener('setquota', update_quota);
        folder_search_init($('#folderslist'));
      }
      else if (rcmail.env.action == 'identities') {
        new rcube_splitter({ id:'identviewsplitter', p1:'#identitieslist', p2:'#identity-details',
@@ -531,6 +534,35 @@
    }
  }
  function folder_search_init(container)
  {
    // animation to unfold list search box
    $('.boxtitle a.search', container).click(function(e) {
      var title = $('.boxtitle', container),
        box = $('.listsearchbox', container),
        dir = box.is(':visible') ? -1 : 1;
      box.slideToggle({
        duration: 160,
        progress: function(animation, progress) {
          if (dir < 0) progress = 1 - progress;
            $('.scroller', container).css('top', (title.outerHeight() + 34 * progress) + 'px');
        },
        complete: function() {
          box.toggleClass('expanded');
          if (box.is(':visible')) {
            box.find('input[type=text]').focus();
          }
          else {
            $('a.reset', box).click();
          }
          // TODO: save state in localStorage
        }
      });
      return false;
    });
  }
  function enable_command(p)
  {