Thomas Bruederli
2014-06-05 99cdca46b7bcc46fe6affd9e9f9f60a546b2e5b8
Merge branch 'dev-accessibility'

Conflicts:
program/include/rcmail_output_html.php
program/js/app.js
program/js/treelist.js
program/lib/Roundcube/html.php
skins/larry/styles.css
skins/larry/templates/compose.html
49 files modified
2923 ■■■■■ changed files
plugins/legacy_browser/skins/larry/ie7hacks.css 1 ●●●● patch | view | raw | blame | history
plugins/managesieve/skins/larry/managesieve.css 8 ●●●●● patch | view | raw | blame | history
plugins/zipdownload/zipdownload.js 25 ●●●● patch | view | raw | blame | history
plugins/zipdownload/zipdownload.php 8 ●●●● patch | view | raw | blame | history
program/include/rcmail.php 9 ●●●●● patch | view | raw | blame | history
program/include/rcmail_output_html.php 33 ●●●●● patch | view | raw | blame | history
program/js/app.js 597 ●●●● patch | view | raw | blame | history
program/js/common.js 24 ●●●●● patch | view | raw | blame | history
program/js/list.js 171 ●●●● patch | view | raw | blame | history
program/js/treelist.js 114 ●●●●● patch | view | raw | blame | history
program/lib/Roundcube/html.php 21 ●●●● patch | view | raw | blame | history
program/localization/en_US/labels.inc 57 ●●●●● patch | view | raw | blame | history
program/steps/addressbook/edit.inc 3 ●●●●● patch | view | raw | blame | history
program/steps/addressbook/func.inc 14 ●●●●● patch | view | raw | blame | history
program/steps/addressbook/show.inc 1 ●●●● patch | view | raw | blame | history
program/steps/mail/compose.inc 5 ●●●●● patch | view | raw | blame | history
program/steps/mail/func.inc 31 ●●●●● patch | view | raw | blame | history
program/steps/mail/list_contacts.inc 2 ●●● patch | view | raw | blame | history
program/steps/mail/search_contacts.inc 2 ●●● patch | view | raw | blame | history
program/steps/mail/show.inc 7 ●●●● patch | view | raw | blame | history
program/steps/settings/edit_folder.inc 3 ●●●● patch | view | raw | blame | history
program/steps/settings/func.inc 2 ●●● patch | view | raw | blame | history
program/steps/settings/responses.inc 2 ●●● patch | view | raw | blame | history
skins/classic/addressbook.css 5 ●●●●● patch | view | raw | blame | history
skins/classic/common.css 5 ●●●● patch | view | raw | blame | history
skins/classic/mail.css 169 ●●●● patch | view | raw | blame | history
skins/larry/addressbook.css 51 ●●●● patch | view | raw | blame | history
skins/larry/includes/footer.html 1 ●●●● patch | view | raw | blame | history
skins/larry/includes/header.html 18 ●●●●● patch | view | raw | blame | history
skins/larry/includes/mailtoolbar.html 58 ●●●● patch | view | raw | blame | history
skins/larry/includes/settingstabs.html 8 ●●●●● patch | view | raw | blame | history
skins/larry/mail.css 208 ●●●●● patch | view | raw | blame | history
skins/larry/settings.css 101 ●●●● patch | view | raw | blame | history
skins/larry/styles.css 206 ●●●● patch | view | raw | blame | history
skins/larry/templates/addressbook.html 120 ●●●●● patch | view | raw | blame | history
skins/larry/templates/compose.html 126 ●●●● patch | view | raw | blame | history
skins/larry/templates/contactedit.html 5 ●●●●● patch | view | raw | blame | history
skins/larry/templates/folders.html 25 ●●●●● patch | view | raw | blame | history
skins/larry/templates/identities.html 12 ●●●●● patch | view | raw | blame | history
skins/larry/templates/importcontacts.html 2 ●●● patch | view | raw | blame | history
skins/larry/templates/login.html 10 ●●●●● patch | view | raw | blame | history
skins/larry/templates/mail.html 148 ●●●●● patch | view | raw | blame | history
skins/larry/templates/message.html 46 ●●●●● patch | view | raw | blame | history
skins/larry/templates/messageerror.html 14 ●●●●● patch | view | raw | blame | history
skins/larry/templates/messagepart.html 14 ●●●●● patch | view | raw | blame | history
skins/larry/templates/messagepreview.html 68 ●●●● patch | view | raw | blame | history
skins/larry/templates/responses.html 12 ●●●●● patch | view | raw | blame | history
skins/larry/templates/settings.html 11 ●●●●● patch | view | raw | blame | history
skins/larry/ui.js 340 ●●●●● patch | view | raw | blame | history
plugins/legacy_browser/skins/larry/ie7hacks.css
@@ -37,6 +37,7 @@
a.iconbutton,
a.deletebutton,
.boxpagenav a.icon,
a.button span.icon,
.pagenav a.button span.inner,
.boxfooter .listbutton .inner,
.attachmentslist li a.delete,
plugins/managesieve/skins/larry/managesieve.css
@@ -417,11 +417,13 @@
/* vacation form */
#settings-sections span.vacation a {
  background: url(images/vacation_icons.png) no-repeat 7px 1px;
#settings-sections .vacation a {
  background-image: url(images/vacation_icons.png);
    background-repeat: no-repeat;
    background-position: 7px 1px;
}
#settings-sections span.vacation.selected a {
#settings-sections .vacation.selected a {
  background-position: 7px -23px;
}
plugins/zipdownload/zipdownload.js
@@ -43,21 +43,10 @@
            link.html('').append(span);
        }
        span.addClass('folder-selector-link').text(rcmail.gettext('zipdownload.download'));
        span.text(rcmail.gettext('zipdownload.download'));
        rcmail.env.download_link = link;
    });
    // hide menu on click out of menu element
    var fn = function(e) {
        var menu = $('#zipdownload-menu');
        if (e.target != menu.get(0))
            menu.hide();
    };
    $(document.body).on('mouseup', fn);
    $('iframe').contents().on('mouseup', fn)
        .load(function(e) { try { $(this).contents().on('mouseup', fn); } catch(e) {}; });
});
  });
function rcmail_zipdownload(mode)
@@ -100,14 +89,10 @@
}
// display download options menu
function rcmail_zipdownload_menu()
function rcmail_zipdownload_menu(e)
{
    // fix menu style and display menu
    var z_index = rcmail.env.download_link.parents('.popupmenu').css('z-index'),
        menu = $('#zipdownload-menu').css({'max-height': 'none', 'z-index': z_index + 1}).show();
    // position menu on the screen
    rcmail.element_position(menu, rcmail.env.download_link);
    // show (sub)menu for download selection
    rcmail.command('menu-open', 'zipdownload-menu', e && e.target ? e.target : rcmail.env.download_link, e);
    // abort default download action
    return false;
plugins/zipdownload/zipdownload.php
@@ -96,7 +96,10 @@
        $rcmail  = rcmail::get_instance();
        $menu    = array();
        $ul_attr = $rcmail->config->get('skin') == 'classic' ? null : array('class' => 'toolbarmenu');
        $ul_attr = array('role' => 'menu', 'aria-labelledby' => 'aria-label-zipdownloadmenu');
        if ($rcmail->config->get('skin') != 'classic') {
            $ul_attr['class'] = 'toolbarmenu';
        }
        foreach (array('eml', 'mbox', 'maildir') as $type) {
            $menu[] = html::tag('li', null, $rcmail->output->button(array(
@@ -106,7 +109,8 @@
            )));
        }
        $rcmail->output->add_footer(html::div(array('id' => 'zipdownload-menu', 'class' => 'popupmenu'),
        $rcmail->output->add_footer(html::div(array('id' => 'zipdownload-menu', 'class' => 'popupmenu', 'aria-hidden' => 'true'),
            html::tag('h2', array('class' => 'voice', 'id' => 'aria-label-zipdownloadmenu'), "Message Download Options Menu") .
            html::tag('ul', $ul_attr, implode('', $menu))));
    }
program/include/rcmail.php
@@ -1077,14 +1077,17 @@
        }
        else {
            foreach ($table_data as $row_data) {
                $class = !empty($row_data['class']) ? $row_data['class'] : '';
                $class = !empty($row_data['class']) ? $row_data['class'] : null;
                if (!empty($attrib['rowclass']))
                    $class = trim($class . ' ' . $attrib['rowclass']);
                $rowid = 'rcmrow' . rcube_utils::html_identifier($row_data[$id_col]);
                $table->add_row(array('id' => $rowid, 'class' => $class));
                // format each col
                foreach ($a_show_cols as $col) {
                    $table->add($col, $this->Q(is_array($row_data[$col]) ? $row_data[$col][0] : $row_data[$col]));
                    $val = is_array($row_data[$col]) ? $row_data[$col][0] : $row_data[$col];
                    $table->add($col, empty($attrib['ishtml']) ? $this->Q($val) : $val);
                }
            }
        }
@@ -1490,7 +1493,7 @@
            $html_name = $this->Q($foldername) . ($unread ? html::span('unreadcount', sprintf($attrib['unreadwrap'], $unread)) : '');
            $link_attrib = $folder['virtual'] ? array() : array(
                'href' => $this->url(array('_mbox' => $folder['id'])),
                'onclick' => sprintf("return %s.command('list','%s',this)", rcmail_output::JS_OBJECT_NAME, $js_name),
                'onclick' => sprintf("return %s.command('list','%s',this,event)", rcmail_output::JS_OBJECT_NAME, $js_name),
                'rel' => $folder['id'],
                'title' => $title,
            );
program/include/rcmail_output_html.php
@@ -893,6 +893,14 @@
            return '';
        }
        // localize title and summary attributes
        if ($command != 'button' && !empty($attrib['title']) && $this->app->text_exists($attrib['title'])) {
            $attrib['title'] = $this->app->gettext($attrib['title']);
        }
        if ($command != 'button' && !empty($attrib['summary']) && $this->app->text_exists($attrib['summary'])) {
            $attrib['summary'] = $this->app->gettext($attrib['summary']);
        }
        // execute command
        switch ($command) {
            // return a button
@@ -1165,6 +1173,17 @@
            $attrib['alt'] = html::quote($this->app->gettext($attrib['alt'], $attrib['domain']));
        }
        // set accessibility attributes
        if (!$attrib['role']) {
            $attrib['role'] = 'button';
        }
        if (!empty($attrib['class']) && !empty($attrib['classact']) || !empty($attrib['imagepas']) && !empty($attrib['imageact'])) {
            if (array_key_exists('tabindex', $attrib))
                $attrib['data-tabindex'] = $attrib['tabindex'];
            $attrib['tabindex'] = '-1';  // disable button by default
            $attrib['aria-disabled'] = 'true';
        }
        // set title to alt attribute for IE browsers
        if ($this->browser->ie && !$attrib['title'] && $attrib['alt']) {
            $attrib['title'] = $attrib['alt'];
@@ -1353,6 +1372,20 @@
            $is_empty = true;
        }
        // set default page title
        if (empty($this->pagetitle)) {
            $this->pagetitle = 'Roundcube Mail';
        }
        // declare page language
        if (!empty($_SESSION['language'])) {
            $lang = substr($_SESSION['language'], 0, 2);
            $output = preg_replace('/<html/', '<html lang="' . html::quote($lang) . '"', $output, 1);
            if (!headers_sent()) {
                header('Content-Language: ' . $lang);
            }
        }
        // replace specialchars in content
        $page_title  = html::quote($this->pagetitle);
        $page_header = '';
program/js/app.js
@@ -46,6 +46,7 @@
  this.messages = {};
  this.group2expand = {};
  this.http_request_jobs = {};
  this.menu_stack = new Array();
  // webmail client settings
  this.dblclick_time = 500;
@@ -197,7 +198,10 @@
    // enable general commands
    this.enable_command('close', 'logout', 'mail', 'addressbook', 'settings', 'save-pref',
      'compose', 'undo', 'about', 'switch-task', 'menu-open', 'menu-save', true);
      'compose', 'undo', 'about', 'switch-task', 'menu-open', 'menu-close', 'menu-save', true);
    // set active task button
    this.set_button(this.task, 'sel');
    if (this.env.permaurl)
      this.enable_command('permaurl', 'extwin', true);
@@ -232,8 +236,7 @@
            return ref.command('sort', $(this).attr('rel'), this);
          });
          document.onmouseup = function(e){ return ref.doc_mouse_up(e); };
          this.gui_objects.messagelist.parentNode.onmousedown = function(e){ return ref.click_on_list(e); };
          this.gui_objects.messagelist.parentNode.onclick = function(e){ return ref.click_on_list(e || window.event); };
          this.enable_command('toggle_status', 'toggle_flag', 'sort', true);
          this.enable_command('set-listmode', this.env.threads && !this.is_multifolder_listing());
@@ -276,7 +279,7 @@
          this.env.address_group_stack = [];
          this.env.compose_commands = ['send-attachment', 'remove-attachment', 'send', 'cancel',
            'toggle-editor', 'list-adresses', 'pushgroup', 'search', 'reset-search', 'extwin',
            'insert-response', 'save-response'];
            'insert-response', 'save-response', 'menu-open', 'menu-close'];
          if (this.env.drafts_mailbox)
            this.env.compose_commands.push('savedraft')
@@ -302,10 +305,12 @@
            $('a.insertresponse', this.gui_objects.responseslist)
              .attr('unselectable', 'on')
              .mousedown(function(e){ return rcube_event.cancel(e); })
              .mouseup(function(e){
                ref.command('insert-response', $(this).attr('rel'));
                $(document.body).trigger('mouseup');  // hides the menu
                return rcube_event.cancel(e);
              .bind('mouseup keypress', function(e){
                if (e.type == 'mouseup' || rcube_event.get_keycode(e) == 13) {
                  ref.command('insert-response', $(this).attr('rel'));
                  $(document.body).trigger('mouseup');  // hides the menu
                  return rcube_event.cancel(e);
                }
              });
            // avoid textarea loosing focus when hitting the save-response button/link
@@ -313,8 +318,6 @@
              $('#'+this.buttons['save-response'][i].id).mousedown(function(e){ return rcube_event.cancel(e); })
            }
          }
          document.onmouseup = function(e){ return ref.doc_mouse_up(e); };
          // init message compose form
          this.init_messageform();
@@ -339,11 +342,21 @@
        // init address book widget
        if (this.gui_objects.contactslist) {
          this.contact_list = new rcube_list_widget(this.gui_objects.contactslist,
            { multiselect:true, draggable:false, keyboard:false });
            { multiselect:true, draggable:false, keyboard:true });
          this.contact_list
            .addEventListener('initrow', function(o) { ref.triggerEvent('insertrow', { cid:o.uid, row:o }); })
            .addEventListener('select', function(o) { ref.compose_recipient_select(o); })
            .addEventListener('dblclick', function(o) { ref.compose_add_recipient('to'); })
            .addEventListener('keypress', function(o) {
              if (o.key_pressed == o.ENTER_KEY) {
                if (!ref.compose_add_recipient('to')) {
                  // execute link action on <enter> if not a recipient entry
                  if (o.last_selected && String(o.last_selected).charAt(0) == 'G') {
                    $(o.rows[o.last_selected].obj).find('a').first().click();
                  }
                }
              }
            })
            .init();
        }
@@ -394,7 +407,6 @@
            this.contact_list.highlight_row(this.env.cid);
          this.gui_objects.contactslist.parentNode.onmousedown = function(e){ return ref.click_on_list(e); };
          document.onmouseup = function(e){ return ref.doc_mouse_up(e); };
          $(this.gui_objects.qsearchbox).focusin(function() { ref.contact_list.blur(); });
@@ -449,9 +461,14 @@
        if (this.gui_objects.identitieslist) {
          this.identity_list = new rcube_list_widget(this.gui_objects.identitieslist,
            {multiselect:false, draggable:false, keyboard:false});
            {multiselect:false, draggable:false, keyboard:true});
          this.identity_list
            .addEventListener('select', function(o) { ref.identity_select(o); })
            .addEventListener('keypress', function(o) {
              if (o.key_pressed == o.ENTER_KEY) {
                ref.identity_select(o);
              }
            })
            .init()
            .focus();
@@ -459,9 +476,10 @@
            this.identity_list.highlight_row(this.env.iid);
        }
        else if (this.gui_objects.sectionslist) {
          this.sections_list = new rcube_list_widget(this.gui_objects.sectionslist, {multiselect:false, draggable:false, keyboard:false});
          this.sections_list = new rcube_list_widget(this.gui_objects.sectionslist, {multiselect:false, draggable:false, keyboard:true});
          this.sections_list
            .addEventListener('select', function(o) { ref.section_select(o); })
            .addEventListener('keypress', function(o) { if (o.key_pressed == o.ENTER_KEY) ref.section_select(o); })
            .init()
            .focus();
        }
@@ -469,7 +487,7 @@
          this.init_subscription_list();
        }
        else if (this.gui_objects.responseslist) {
          this.responses_list = new rcube_list_widget(this.gui_objects.responseslist, {multiselect:false, draggable:false, keyboard:false});
          this.responses_list = new rcube_list_widget(this.gui_objects.responseslist, {multiselect:false, draggable:false, keyboard:true});
          this.responses_list
            .addEventListener('select', function(list) {
              var win, id = list.get_single_selection();
@@ -559,6 +577,18 @@
        .get(0).addEventListener('drop', function(e){ return ref.file_dropped(e); }, false);
    }
    // catch document (and iframe) mouse clicks
    var body_mouseup = function(e){ return ref.doc_mouse_up(e); };
    $(document.body)
      .bind('mouseup', body_mouseup)
      .bind('keydown', function(e){ return ref.doc_keypress(e); });
    $('iframe').load(function(e) {
        try { $(this.contentDocument || this.contentWindow).on('mouseup', body_mouseup);  }
        catch (e) {/* catch possible "Permission denied" error in IE */ }
      })
      .contents().on('mouseup', body_mouseup);
    // trigger init event hook
    this.triggerEvent('init', { task:this.task, action:this.env.action });
@@ -591,7 +621,7 @@
  {
    var ret, uid, cid, url, flag, aborted = false;
    if (obj && obj.blur)
    if (obj && obj.blur && !(event || rcube_event.is_keyboard(event)))
      obj.blur();
    // do nothing if interface is locked by other command (with exception for searching reset)
@@ -634,8 +664,8 @@
    }
    // trigger plugin hooks
    this.triggerEvent('actionbefore', {props:props, action:command});
    ret = this.triggerEvent('before'+command, props);
    this.triggerEvent('actionbefore', {props:props, action:command, originalEvent:event});
    ret = this.triggerEvent('before'+command, props || event);
    if (ret !== undefined) {
      // abort if one of the handlers returned false
      if (ret === false)
@@ -707,9 +737,15 @@
          var mimetype = this.env.attachments[props.id];
          this.enable_command('open-attachment', mimetype && this.env.mimetypes && $.inArray(mimetype, this.env.mimetypes) >= 0);
        }
        this.show_menu(props, props.show || undefined, event);
        break;
      case 'menu-close':
        this.hide_menu(props, event);
        break;
      case 'menu-save':
        this.triggerEvent(command, {props:props});
        this.triggerEvent(command, {props:props, originalEvent:event});
        return false;
      case 'open':
@@ -887,14 +923,14 @@
      case 'move':
      case 'moveto': // deprecated
        if (this.task == 'mail')
          this.move_messages(props, obj);
          this.move_messages(props, event);
        else if (this.task == 'addressbook')
          this.move_contacts(props);
        break;
      case 'copy':
        if (this.task == 'mail')
          this.copy_messages(props, obj);
          this.copy_messages(props, event);
        else if (this.task == 'addressbook')
          this.copy_contacts(props);
        break;
@@ -1450,7 +1486,8 @@
    if (menu && modkey == SHIFT_KEY && this.commands['copy']) {
      var pos = rcube_event.get_mouse_pos(e);
      this.env.drag_target = target;
      $(menu).css({top: (pos.y-10)+'px', left: (pos.x-10)+'px'}).show();
      this.show_menu(this.gui_objects.dragmenu.id, true, e);
      $(menu).css({top: (pos.y-10)+'px', left: (pos.x-10)+'px'});
      return true;
    }
@@ -1566,17 +1603,22 @@
    }
  };
  // global mouse-click handler to cleanup some UI elements
  this.doc_mouse_up = function(e)
  {
    var list, id;
    var list, id, target = rcube_event.get_target(e);
    // ignore event if jquery UI dialog is open
    if ($(rcube_event.get_target(e)).closest('.ui-dialog, .ui-widget-overlay').length)
    if ($(target).closest('.ui-dialog, .ui-widget-overlay').length)
      return;
    list = this.message_list || this.contact_list;
    if (list && !rcube_mouse_is_over(e, list.list.parentNode))
      list.blur();
    // remove focus from list widgets
    if (window.rcube_list_widget && rcube_list_widget._instances.length) {
      $.each(rcube_list_widget._instances, function(i,list){
        if (list && !rcube_mouse_is_over(e, list.list.parentNode))
          list.blur();
      });
    }
    // reset 'pressed' buttons
    if (this.buttons_sel) {
@@ -1585,7 +1627,77 @@
          this.button_out(this.buttons_sel[id], id);
      this.buttons_sel = {};
    }
    // reset popup menus; delayed to have updated menu_stack data
    window.setTimeout(function(e){
      var obj, skip, config, id, i, parents = $(target).parents();
      for (i = ref.menu_stack.length - 1; i >= 0; i--) {
        id = ref.menu_stack[i];
        obj = $('#' + id);
        if (obj.is(':visible')
          && target != obj.data('opener')
          && target != obj.get(0)  // check if scroll bar was clicked (#1489832)
          && !parents.is(obj.data('opener'))
          && id != skip
          && (obj.attr('data-editable') != 'true' || !$(target).parents('#' + id).length)
          && (obj.attr('data-sticky') != 'true' || !rcube_mouse_is_over(e, obj.get(0)))
        ) {
          ref.hide_menu(id, e);
        }
        skip = obj.data('parent');
      }
    }, 10);
  };
  // global keypress event handler
  this.doc_keypress = function(e)
  {
    // Helper method to move focus to the next/prev active menu item
    var focus_menu_item = function(dir) {
      var obj, item, mod = dir < 0 ? 'prevAll' : 'nextAll', limit = dir < 0 ? 'last' : 'first';
      if (ref.focused_menu && (obj = $('#'+ref.focused_menu))) {
        item = obj.find(':focus').closest('li')[mod](':has(:not([aria-disabled=true]))').find('a,input')[limit]();
        if (!item.length)
          item = obj.find(':focus').closest('ul')[mod](':has(:not([aria-disabled=true]))').find('a,input')[limit]();
        return item.focus().length;
      }
      return 0;
    };
    var target = e.target || {},
      keyCode = rcube_event.get_keycode(e);
    if (e.keyCode != 27 && (!this.menu_keyboard_active || target.nodeName == 'TEXTAREA' || target.nodeName == 'SELECT')) {
      return true;
    }
    switch (keyCode) {
      case 38:
      case 40:
      case 63232: // "up", in safari keypress
      case 63233: // "down", in safari keypress
        focus_menu_item(mod = keyCode == 38 || keyCode == 63232 ? -1 : 1);
        break;
      case 9:   // tab
        if (this.focused_menu) {
          var mod = rcube_event.get_modifier(e);
          if (!focus_menu_item(mod == SHIFT_KEY ? -1 : 1)) {
            this.hide_menu(this.focused_menu, e);
          }
        }
        return rcube_event.cancel(e);
      case 27:  // esc
        if (this.menu_stack.length)
          this.hide_menu(this.menu_stack[this.menu_stack.length-1], e);
        break;
    }
    return true;
  }
  this.click_on_list = function(e)
  {
@@ -1593,9 +1705,9 @@
      this.gui_objects.qsearchbox.blur();
    if (this.message_list)
      this.message_list.focus();
      this.message_list.focus(e);
    else if (this.contact_list)
      this.contact_list.focus();
      this.contact_list.focus(e);
    return true;
  };
@@ -1880,7 +1992,7 @@
      flags: flags.extra_flags
    });
    var c, n, col, html, css_class,
    var c, n, col, html, css_class, label, status_class = '', status_label = '',
      tree = '', expando = '',
      list = this.message_list,
      rows = list.rows,
@@ -1897,17 +2009,26 @@
    css_class = 'msgicon';
    if (this.env.status_col === null) {
      css_class += ' status';
      if (flags.deleted)
        css_class += ' deleted';
      else if (!flags.seen)
        css_class += ' unread';
      else if (flags.unread_children > 0)
        css_class += ' unreadchildren';
      if (flags.deleted) {
        status_class += ' deleted';
        status_label += this.get_label('deleted') + ' ';
      }
      else if (!flags.seen) {
        status_class += ' unread';
        status_label += this.get_label('unread') + ' ';
      }
      else if (flags.unread_children > 0) {
        status_class += ' unreadchildren';
      }
    }
    if (flags.answered)
      css_class += ' replied';
    if (flags.forwarded)
      css_class += ' forwarded';
    if (flags.answered) {
      status_class += ' replied';
      status_label += this.get_label('replied') + ' ';
    }
    if (flags.forwarded) {
      status_class += ' forwarded';
      status_label += this.get_label('replied') + ' ';
    }
    // update selection
    if (message.selected && !list.in_selection(uid))
@@ -1944,15 +2065,17 @@
        row_class += ' unroot';
    }
    tree += '<span id="msgicn'+row.id+'" class="'+css_class+'">&nbsp;</span>';
    tree += '<span id="msgicn'+row.id+'" class="'+css_class+status_class+'" title="'+status_label+'"></span>';
    row.className = row_class;
    // build subject link
    if (cols.subject) {
      var action = flags.mbox == this.env.drafts_mailbox ? 'compose' : 'show';
      var uid_param = flags.mbox == this.env.drafts_mailbox ? '_draft_uid' : '_uid';
      cols.subject = '<a href="./?_task=mail&_action='+action+'&_mbox='+urlencode(flags.mbox)+'&'+uid_param+'='+urlencode(uid)+'"'+
        ' onclick="return rcube_event.cancel(event)" onmouseover="rcube_webmail.long_subject_title(this,'+(message.depth+1)+')"><span>'+cols.subject+'</span></a>';
      var action  = flags.mbox == this.env.drafts_mailbox ? 'compose' : 'show',
        uid_param = flags.mbox == this.env.drafts_mailbox ? '_draft_uid' : '_uid',
        query = { _mbox: flags.mbox };
      query[uid_param] = uid;
      cols.subject = '<a href="' + this.url(action, query) + '" onclick="return rcube_event.keyboard_only(event)"' +
        ' onmouseover="rcube_webmail.long_subject_title(this,'+(message.depth+1)+')" tabindex="-1"><span>'+cols.subject+'</span></a>';
    }
    // add each submitted col
@@ -1966,28 +2089,36 @@
      if (c == 'flag') {
        css_class = (flags.flagged ? 'flagged' : 'unflagged');
        html = '<span id="flagicn'+row.id+'" class="'+css_class+'">&nbsp;</span>';
        label = this.get_label(css_class);
        html = '<span id="flagicn'+row.id+'" class="'+css_class+'" title="'+label+'"></span>';
      }
      else if (c == 'attachment') {
        label = this.get_label('withattachment');
        if (flags.attachmentClass)
          html = '<span class="'+flags.attachmentClass+'">&nbsp;</span>';
          html = '<span class="'+flags.attachmentClass+'" title="'+label+'"></span>';
        else if (/application\/|multipart\/(m|signed)/.test(flags.ctype))
          html = '<span class="attachment">&nbsp;</span>';
          html = '<span class="attachment" title="'+label+'"></span>';
        else if (/multipart\/report/.test(flags.ctype))
          html = '<span class="report">&nbsp;</span>';
        else
          html = '<span class="report"></span>';
          else
          html = '&nbsp;';
      }
      else if (c == 'status') {
        if (flags.deleted)
        label = '';
        if (flags.deleted) {
          css_class = 'deleted';
        else if (!flags.seen)
          label = this.get_label('deleted');
        }
        else if (!flags.seen) {
          css_class = 'unread';
        else if (flags.unread_children > 0)
          label = this.get_label('unread');
        }
        else if (flags.unread_children > 0) {
          css_class = 'unreadchildren';
        }
        else
          css_class = 'msgicon';
        html = '<span id="statusicn'+row.id+'" class="'+css_class+'">&nbsp;</span>';
        html = '<span id="statusicn'+row.id+'" class="'+css_class+status_class+'" title="'+label+'"></span>';
      }
      else if (c == 'threads')
        html = expando;
@@ -1997,8 +2128,10 @@
        html = tree + cols[c];
      }
      else if (c == 'priority') {
        if (flags.prio > 0 && flags.prio < 6)
          html = '<span class="prio'+flags.prio+'">&nbsp;</span>';
        if (flags.prio > 0 && flags.prio < 6) {
          label = this.get_label('priority') + ' ' + flags.prio;
          html = '<span class="prio'+flags.prio+'" title="'+label+'"></span>';
        }
        else
          html = '&nbsp;';
      }
@@ -2308,7 +2441,6 @@
  this.clear_message_list = function()
  {
    this.env.messages = {};
    this.last_selected = 0;
    this.show_contentframe(false);
    if (this.message_list)
@@ -2327,6 +2459,7 @@
      url._page = page;
    this.http_request('list', url, lock);
    this.update_state({ _mbox: mbox, _page: (page && page > 1 ? page : null) });
  };
  // removes messages that doesn't exists from list selection array
@@ -2600,7 +2733,7 @@
  // set message icon
  this.set_message_icon = function(uid)
  {
    var css_class,
    var css_class, label = '',
      row = this.message_list.rows[uid];
    if (!row)
@@ -2608,38 +2741,55 @@
    if (row.icon) {
      css_class = 'msgicon';
      if (row.deleted)
      if (row.deleted) {
        css_class += ' deleted';
      else if (row.unread)
        label += this.get_label('deleted') + ' ';
      }
      else if (row.unread) {
        css_class += ' unread';
        label += this.get_label('unread') + ' ';
      }
      else if (row.unread_children)
        css_class += ' unreadchildren';
      if (row.msgicon == row.icon) {
        if (row.replied)
        if (row.replied) {
          css_class += ' replied';
        if (row.forwarded)
          label += this.get_label('replied') + ' ';
        }
        if (row.forwarded) {
          css_class += ' forwarded';
          label += this.get_label('forwarded') + ' ';
        }
        css_class += ' status';
      }
      row.icon.className = css_class;
      $(row.icon).attr('class', css_class).attr('title', label);
    }
    if (row.msgicon && row.msgicon != row.icon) {
      label = '';
      css_class = 'msgicon';
      if (!row.unread && row.unread_children)
      if (!row.unread && row.unread_children) {
        css_class += ' unreadchildren';
      if (row.replied)
      }
      if (row.replied) {
        css_class += ' replied';
      if (row.forwarded)
        label += this.get_label('replied') + ' ';
      }
      if (row.forwarded) {
        css_class += ' forwarded';
        label += this.get_label('forwarded') + ' ';
      }
      row.msgicon.className = css_class;
      $(row.msgicon).attr('class', css_class).attr('title', label);
    }
    if (row.flagicon) {
      css_class = (row.flagged ? 'flagged' : 'unflagged');
      row.flagicon.className = css_class;
      label = this.get_label(css_class);
      $(row.flagicon).attr('class', css_class)
        .attr('aria-label', label)
        .attr('title', label);
    }
  };
@@ -2693,12 +2843,12 @@
  };
  // copy selected messages to the specified mailbox
  this.copy_messages = function(mbox, obj)
  this.copy_messages = function(mbox, event)
  {
    if (mbox && typeof mbox === 'object')
      mbox = mbox.id;
    else if (!mbox)
      return this.folder_selector(obj, function(folder) { ref.command('copy', folder); });
      return this.folder_selector(event, function(folder) { ref.command('copy', folder); });
    // exit if current or no mailbox specified
    if (!mbox || mbox == this.env.mailbox)
@@ -2715,12 +2865,12 @@
  };
  // move selected messages to the specified mailbox
  this.move_messages = function(mbox, obj)
  this.move_messages = function(mbox, event)
  {
    if (mbox && typeof mbox === 'object')
      mbox = mbox.id;
    else if (!mbox)
      return this.folder_selector(obj, function(folder) { ref.command('move', folder); });
      return this.folder_selector(event, function(folder) { ref.command('move', folder); });
    // exit if current or no mailbox specified
    if (!mbox || (mbox == this.env.mailbox && !this.is_multifolder_listing()))
@@ -3286,7 +3436,7 @@
    this.env.recipients_delimiter = this.env.recipients_separator + ' ';
    obj.keydown(function(e) { return ref.ksearch_keydown(e, this, props); })
      .attr('autocomplete', 'off');
      .attr({ 'autocomplete': 'off', 'aria-autocomplete': 'list', 'aria-expanded': 'false', 'role': 'combobox' });
  };
  this.submit_messageform = function(draft)
@@ -3357,6 +3507,8 @@
      input.val(oldval + recipients.join(delim + ' ') + delim + ' ');
      this.triggerEvent('add-recipient', { field:field, recipients:recipients });
    }
    return recipients.length;
  };
  // checks the input fields before sending a message
@@ -3507,15 +3659,18 @@
      $('<a>').addClass('insertresponse active')
        .attr('href', '#')
        .attr('rel', key)
        .attr('tabindex', '0')
        .html(this.quote_html(response.name))
        .appendTo(li)
        .mousedown(function(e){
          return rcube_event.cancel(e);
        })
        .mouseup(function(e){
          ref.command('insert-response', key);
          $(document.body).trigger('mouseup');  // hides the menu
          return rcube_event.cancel(e);
        .bind('mouseup keypress', function(e){
          if (e.type == 'mouseup' || rcube_event.get_keycode(e) == 13) {
            ref.command('insert-response', $(this).attr('rel'));
            $(document.body).trigger('mouseup');  // hides the menu
            return rcube_event.cancel(e);
          }
        });
    }
  };
@@ -3787,7 +3942,7 @@
      // cleanup
      rx = new RegExp(rx_delim + '\\s*' + rx_delim, 'g');
      input_val = input_val.replace(rx, delim);
      input_val = String(input_val).replace(rx, delim);
      rx = new RegExp('^[\\s' + rx_delim + ']+');
      input_val = input_val.replace(rx, '');
@@ -4155,7 +4310,7 @@
          return;
        var dir = key == 38 ? 1 : 0,
          highlight = document.getElementById('rcmksearchSelected');
          highlight = document.getElementById('rcmkSearchItem' + this.ksearch_selected);
        if (!highlight)
          highlight = this.ksearch_pane.__ul.firstChild;
@@ -4204,14 +4359,14 @@
  this.ksearch_select = function(node)
  {
    var current = $('#rcmksearchSelected');
    if (current[0] && node) {
      current.removeAttr('id').removeClass('selected');
    if (this.ksearch_pane && node) {
      this.ksearch_pane.find('li.selected').removeClass('selected').removeAttr('aria-selected');
    }
    if (node) {
      $(node).attr('id', 'rcmksearchSelected').addClass('selected');
      $(node).addClass('selected').attr('aria-selected', 'true');
      this.ksearch_selected = node._rcm_id;
      $(this.ksearch_input).attr('aria-activedescendant', 'rcmkSearchItem' + this.ksearch_selected);
    }
  };
@@ -4340,16 +4495,20 @@
      return;
    // display search results
    var i, len, ul, li, text, type, init,
    var i, id, len, ul, text, type, init,
      value = this.ksearch_value,
      maxlen = this.env.autocomplete_max ? this.env.autocomplete_max : 15;
    // create results pane if not present
    if (!this.ksearch_pane) {
      ul = $('<ul>');
      this.ksearch_pane = $('<div>').attr('id', 'rcmKSearchpane')
      this.ksearch_pane = $('<div>').attr('id', 'rcmKSearchpane').attr('role', 'listbox')
        .css({ position:'absolute', 'z-index':30000 }).append(ul).appendTo(document.body);
      this.ksearch_pane.__ul = ul[0];
      // register (delegate) event handlers
      ul.on('mouseover', 'li', function(e){ ref.ksearch_select(e.target); })
        .on('onmouseup', 'li', function(e){ ref.ksearch_click(e.target); })
    }
    ul = this.ksearch_pane.__ul;
@@ -4374,23 +4533,29 @@
      for (i=0; i < len && maxlen > 0; i++) {
        text = typeof results[i] === 'object' ? results[i].name : results[i];
        type = typeof results[i] === 'object' ? results[i].type : '';
        li = document.createElement('LI');
        li.innerHTML = text.replace(new RegExp('('+RegExp.escape(value)+')', 'ig'), '##$1%%').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/##([^%]+)%%/g, '<b>$1</b>');
        li.onmouseover = function(){ ref.ksearch_select(this); };
        li.onmouseup = function(){ ref.ksearch_click(this) };
        li._rcm_id = this.env.contacts.length + i;
        if (type) li.className = type;
        ul.appendChild(li);
        id = i + this.env.contacts.length;
        $('<li>').attr('id', 'rcmkSearchItem' + id)
          .attr('role', 'option')
          .html(this.quote_html(text.replace(new RegExp('('+RegExp.escape(value)+')', 'ig'), '##$1%%')).replace(/##([^%]+)%%/g, '<b>$1</b>'))
          .addClass(type || '')
          .appendTo(ul)
          .get(0)._rcm_id = id;
        maxlen -= 1;
      }
    }
    if (ul.childNodes.length) {
      // set the right aria-* attributes to the input field
      $(this.ksearch_input)
        .attr('aria-haspopup', 'true')
        .attr('aria-expanded', 'true')
        .attr('aria-owns', 'rcmKSearchpane');
      this.ksearch_pane.show();
      // select the first
      if (!this.env.contacts.length) {
        $('li:first', ul).attr('id', 'rcmksearchSelected').addClass('selected');
        this.ksearch_selected = 0;
        this.ksearch_select($('li:first', ul).get(0));
      }
    }
@@ -4426,6 +4591,12 @@
    if (this.ksearch_pane)
      this.ksearch_pane.hide();
    $(this.ksearch_input)
      .attr('aria-haspopup', 'false')
      .attr('aria-expanded', 'false')
      .removeAttr('aria-activedescendant')
      .removeAttr('aria-owns');
    this.ksearch_destroy();
  };
@@ -4631,6 +4802,7 @@
      // add link to pop back to parent group
      if (this.env.address_group_stack.length > 1) {
        $('<a href="#list">...</a>')
          .attr('title', this.gettext('uponelevel'))
          .addClass('poplink')
          .appendTo(boxtitle)
          .click(function(e){ return ref.command('popgroup','',this); });
@@ -5174,6 +5346,7 @@
      if (appendcontainer.length && appendcontainer.get(0).nodeName == 'FIELDSET') {
        var input, colprop = this.env.coltypes[col],
          input_id = 'ff_' + col + (colprop.count || 0),
          row = $('<div>').addClass('row'),
          cell = $('<div>').addClass('contactfieldcontent data'),
          label = $('<div>').addClass('contactfieldlabel label');
@@ -5181,14 +5354,14 @@
        if (colprop.subtypes_select)
          label.html(colprop.subtypes_select);
        else
          label.html(colprop.label);
          label.html('<label for="' + input_id + '">' + colprop.label + '</label>');
        var name_suffix = colprop.limit != 1 ? '[]' : '';
        if (colprop.type == 'text' || colprop.type == 'date') {
          input = $('<input>')
            .addClass('ff_'+col)
            .attr({type: 'text', name: '_'+col+name_suffix, size: colprop.size})
            .attr({type: 'text', name: '_'+col+name_suffix, size: colprop.size, id: input_id})
            .appendTo(cell);
          this.init_edit_field(col, input);
@@ -5199,7 +5372,7 @@
        else if (colprop.type == 'textarea') {
          input = $('<textarea>')
            .addClass('ff_'+col)
            .attr({ name: '_'+col+name_suffix, cols:colprop.size, rows:colprop.rows })
            .attr({ name: '_'+col+name_suffix, cols:colprop.size, rows:colprop.rows, id: input_id })
            .appendTo(cell);
          this.init_edit_field(col, input);
@@ -5235,7 +5408,7 @@
        else if (colprop.type == 'select') {
          input = $('<select>')
            .addClass('ff_'+col)
            .attr('name', '_'+col+name_suffix)
            .attr({ 'name': '_'+col+name_suffix, id: input_id })
            .appendTo(cell);
          var options = input.attr('options');
@@ -5542,7 +5715,7 @@
    this.last_sub_rx = RegExp('['+delim+']?[^'+delim+']+$');
    this.subscription_list = new rcube_list_widget(this.gui_objects.subscriptionlist,
      {multiselect:false, draggable:true, keyboard:false, toggleselect:true});
      {multiselect:false, draggable:true, keyboard:true, toggleselect:true});
    this.subscription_list
      .addEventListener('select', function(o){ ref.subscription_select(o); })
      .addEventListener('dragstart', function(o){ ref.drag_active = true; })
@@ -5551,7 +5724,8 @@
        row.obj.onmouseover = function() { ref.focus_subscription(row.id); };
        row.obj.onmouseout = function() { ref.unfocus_subscription(row.id); };
      })
      .init();
      .init()
      .focus();
    $('#mailboxroot')
      .mouseover(function(){ ref.focus_subscription(this.id); })
@@ -5976,15 +6150,12 @@
        init_button(cmd, this.buttons[cmd][i]);
      }
    }
    // set active task button
    this.set_button(this.task, 'sel');
  };
  // set button to a specific state
  this.set_button = function(command, state)
  {
    var n, button, obj, a_buttons = this.buttons[command],
    var n, button, obj, $obj, a_buttons = this.buttons[command],
      len = a_buttons ? a_buttons.length : 0;
    for (n=0; n<len; n++) {
@@ -6019,7 +6190,14 @@
        obj.disabled = state == 'pas';
      }
      else if (button.type == 'uibutton') {
        button.status = state;
        $(obj).button('option', 'disabled', state == 'pas');
      }
      else {
        $obj = $(obj);
        $obj
          .attr('tabindex', state == 'pas' || state == 'sel' ? '-1' : ($obj.attr('data-tabindex') || '0'))
          .attr('aria-disabled', state == 'pas' || state == 'sel' ? 'true' : 'false');
      }
    }
  };
@@ -6144,7 +6322,8 @@
      this.messages[key].labels = [{'id': id, 'msg': msg}];
    }
    else {
      obj.click(function() { return ref.hide_message(obj); });
      obj.click(function() { return ref.hide_message(obj); })
        .attr('role', 'alert');
    }
    this.triggerEvent('message', { message:msg, type:type, timeout:timeout, object:obj });
@@ -6274,10 +6453,8 @@
      this.treelist.select(name);
    }
    else if (this.gui_objects.folderlist) {
      $('li.selected', this.gui_objects.folderlist)
        .removeClass('selected').addClass('unfocused');
      $(this.get_folder_li(name, prefix, encode))
        .removeClass('unfocused').addClass('selected');
      $('li.selected', this.gui_objects.folderlist).removeClass('selected');
      $(this.get_folder_li(name, prefix, encode)).addClass('selected');
      // trigger event hook
      this.triggerEvent('selectfolder', { folder:name, prefix:prefix });
@@ -6327,7 +6504,7 @@
        tr = document.createElement('tr');
        for (c=0, len=repl.length; c < len; c++) {
          cell = document.createElement('td');
          cell = document.createElement('th');
          cell.innerHTML = repl[c].html || '';
          if (repl[c].id) cell.id = repl[c].id;
          if (repl[c].className) cell.className = repl[c].className;
@@ -6511,17 +6688,15 @@
  };
  // create folder selector popup, position and display it
  this.folder_selector = function(obj, callback)
  this.folder_selector = function(event, callback)
  {
    var container = this.folder_selector_element;
    if (!container) {
      var rows = [],
        delim = this.env.delimiter,
        ul = $('<ul class="toolbarmenu iconized">'),
        li = document.createElement('li'),
        link = document.createElement('a'),
        span = document.createElement('span');
        ul = $('<ul class="toolbarmenu">'),
        link = document.createElement('a');
      container = $('<div id="folder-selector" class="popupmenu"></div>');
      link.href = '#';
@@ -6529,33 +6704,30 @@
      // loop over sorted folders list
      $.each(this.env.mailboxes_list, function() {
        var tmp, n = 0, s = 0,
        var n = 0, s = 0,
          folder = ref.env.mailboxes[this],
          id = folder.id,
          a = link.cloneNode(false), row = li.cloneNode(false);
          a = $(link.cloneNode(false)),
          row = $('<li>');
        if (folder.virtual)
          a.className += ' virtual';
        else {
          a.className += ' active';
          a.onclick = function() { container.hide().data('callback')(folder.id); };
        }
          a.addClass('virtual').attr('aria-disabled', 'true').attr('tabindex', '-1');
        else
          a.addClass('active').data('id', folder.id);
        if (folder['class'])
          a.className += ' ' + folder['class'];
          a.addClass(folder['class']);
        // calculate/set indentation level
        while ((s = id.indexOf(delim, s)) >= 0) {
          n++; s++;
        }
        a.style.paddingLeft =  n ? (n * 16) + 'px' : 0;
        a.css('padding-left', n ? (n * 16) + 'px' : 0);
        // add folder name element
        tmp = span.cloneNode(false);
        $(tmp).text(folder.name);
        a.appendChild(tmp);
        a.append($('<span>').text(folder.name));
        row.appendChild(a);
        row.append(a);
        rows.push(row);
      });
@@ -6567,22 +6739,156 @@
      // set max-height if the list is long
      if (rows.length > 10)
        container.css('max-height', $('li', container)[0].offsetHeight * 10 + 9)
        container.css('max-height', $('li', container)[0].offsetHeight * 10 + 9);
      // hide selector on click out of selector element
      var fn = function(e) { if (e.target != container.get(0)) container.hide(); };
      $(document.body).on('mouseup', fn);
      $('iframe').contents().on('mouseup', fn)
        .load(function(e) { try { $(this).contents().on('mouseup', fn); } catch(e) {}; });
      // register delegate event handler for folder item clicks
      container.on('click', 'a.active', function(e){
        container.data('callback')($(this).data('id'));
        return false;
      });
      this.folder_selector_element = container;
    }
    // position menu on the screen
    this.element_position(container, obj);
    container.data('callback', callback);
    container.show().data('callback', callback);
    // position menu on the screen
    this.show_menu('folder-selector', true, event);
  };
  /***********************************************/
  /*********    popup menu functions     *********/
  /***********************************************/
  // Show/hide a specific popup menu
  this.show_menu = function(prop, show, event)
  {
    var name = typeof prop == 'object' ? prop.menu : prop,
      obj = $('#'+name),
      ref = event && event.target ? $(event.target) : $(obj.attr('rel') || '#'+name+'link'),
      keyboard = rcube_event.is_keyboard(event),
      align = obj.attr('data-align') || '',
      stack = false;
    // find "real" button element
    if (ref.get(0).tagName != 'A' && ref.closest('a').length)
      ref = ref.closest('a');
    if (typeof prop == 'string')
      prop = { menu:name };
    // let plugins or skins provide the menu element
    if (!obj.length) {
      obj = this.triggerEvent('menu-get', { name:name, props:prop, originalEvent:event });
    }
    if (!obj || !obj.length) {
      // just delegate the action to subscribers
      return this.triggerEvent(show === false ? 'menu-close' : 'menu-open', { name:name, props:prop, originalEvent:event });
    }
    // move element to top for proper absolute positioning
    obj.appendTo(document.body);
    if (typeof show == 'undefined')
      show = obj.is(':visible') ? false : true;
    if (show && ref.length) {
      var win = $(window),
        pos = ref.offset(),
        above = align.indexOf('bottom') >= 0;
      stack = ref.attr('role') == 'menuitem' || ref.closest('[role=menuitem]').length > 0;
      ref.offsetWidth = ref.outerWidth();
      ref.offsetHeight = ref.outerHeight();
      if (!above && pos.top + ref.offsetHeight + obj.height() > win.height()) {
        above = true;
      }
      if (align.indexOf('right') >= 0) {
        pos.left = pos.left + ref.outerWidth() - obj.width();
      }
      else if (stack) {
        pos.left = pos.left + ref.offsetWidth - 5;
        pos.top -= ref.offsetHeight;
      }
      if (pos.left + obj.width() > win.width()) {
        pos.left = win.width() - obj.width() - 12;
      }
      pos.top = Math.max(0, pos.top + (above ? -obj.height() : ref.offsetHeight));
      obj.css({ left:pos.left+'px', top:pos.top+'px' });
    }
    // add menu to stack
    if (show) {
      // truncate stack down to the one containing the ref link
      for (var i = this.menu_stack.length - 1; stack && i >= 0; i--) {
        if (!$(ref).parents('#'+this.menu_stack[i]).length)
          this.hide_menu(this.menu_stack[i]);
      }
      if (stack && this.menu_stack.length) {
        obj.data('parent', $.last(this.menu_stack));
        obj.css('z-index', ($('#'+$.last(this.menu_stack)).css('z-index') || 0) + 1);
      }
      else if (!stack && this.menu_stack.length) {
        this.hide_menu(this.menu_stack[0], event);
      }
      obj.show().attr('aria-hidden', 'false').data('opener', ref.attr('aria-expanded', 'true').get(0));
      this.triggerEvent('menu-open', { name:name, obj:obj, props:prop, originalEvent:event });
      this.menu_stack.push(name);
      this.menu_keyboard_active = show && keyboard;
      if (this.menu_keyboard_active) {
        this.focused_menu = name;
        obj.find('a,input:not(:disabled)').not('[aria-disabled=true]').first().focus();
      }
    }
    else {  // close menu
      this.hide_menu(name, event);
    }
    return show;
  };
  // hide the given popup menu (and it's childs)
  this.hide_menu = function(name, event)
  {
    if (!this.menu_stack.length) {
      // delegate to subscribers
      this.triggerEvent('menu-close', { name:name, props:{ menu:name }, originalEvent:event });
      return;
    }
    var obj, keyboard = rcube_event.is_keyboard(event);
    for (var j=this.menu_stack.length-1; j >= 0; j--) {
      obj = $('#' + this.menu_stack[j]).hide().attr('aria-hidden', 'true').data('parent', false);
      this.triggerEvent('menu-close', { name:this.menu_stack[j], obj:obj, props:{ menu:this.menu_stack[j] }, originalEvent:event });
      if (this.menu_stack[j] == name) {
        j = -1;  // stop loop
        if (obj.data('opener')) {
          $(obj.data('opener')).attr('aria-expanded', 'false');
          if (keyboard)
            obj.data('opener').focus();
        }
      }
      this.menu_stack.pop();
    }
    // focus previous menu in stack
    if (this.menu_stack.length && keyboard) {
      this.menu_keyboard_active = true;
      this.focused_menu = $.last(this.menu_stack);
      if (!obj || !obj.data('opener'))
        $('#'+this.focused_menu).find('a,input:not(:disabled)').not('[aria-disabled=true]').first().focus();
    }
    else {
      this.focused_menu = null;
      this.menu_keyboard_active = false;
    }
  }
  // position a menu element on the screen in relation to other object
  this.element_position = function(element, obj)
@@ -6751,6 +7057,13 @@
    // reset keep-alive interval
    this.start_keepalive();
  };
  // update browser location to remember current view
  this.update_state = function(query)
  {
    if (window.history.replaceState)
      window.history.replaceState({}, document.title, rcmail.url('', query));
  };
  // send a http request to the server
@@ -6938,6 +7251,8 @@
          if ((response.action == 'list' || response.action == 'search') && this.message_list) {
            this.enable_command('set-listmode', this.env.threads && !is_multifolder);
            if (this.message_list.rowcount > 0)
              this.message_list.focus();
            this.msglist_select(this.message_list);
            this.triggerEvent('listupdate', { folder:this.env.mailbox, rowcount:this.message_list.rowcount });
          }
@@ -6949,10 +7264,18 @@
            this.enable_command('search-create', this.env.source == '');
            this.enable_command('search-delete', this.env.search_id);
            this.update_group_commands();
            if (this.contact_list.rowcount > 0)
              this.contact_list.focus();
            this.triggerEvent('listupdate', { folder:this.env.source, rowcount:this.contact_list.rowcount });
          }
        }
        break;
      case 'list-contacts':
      case 'search-contacts':
        if (this.contact_list && this.contact_list.rowcount > 0)
          this.contact_list.focus();
        break;
    }
    if (response.unlock)
program/js/common.js
@@ -281,6 +281,25 @@
  return false;
},
/**
 * Determine whether the given event was trigered from keyboard
 */
is_keyboard: function(e)
{
  return e && (
      (e.mozInputSource && e.mozInputSource == e.MOZ_SOURCE_KEYBOARD) ||
      (!e.pageX && (e.pageY || 0) <= 0 && !e.clientX && (e.clientY || 0) <= 0)
    );
},
/**
 * Accept event if triggered from keyboard action (e.g. <Enter>)
 */
keyboard_only: function(e)
{
  return rcube_event.is_keyboard(e) ? true : rcube_event.cancel(e);
},
touchevent: function(e)
{
  return { pageX:e.pageX, pageY:e.pageY, offsetX:e.pageX - e.target.offsetLeft, offsetY:e.pageY - e.target.offsetTop, target:e.target, istouch:true };
@@ -593,6 +612,11 @@
  };
}
// array utility function
jQuery.last = function(arr) {
  return arr && arr.length ? arr[arr.length-1] : undefined;
}
// jQuery plugin to emulate HTML5 placeholder attributes on input elements
jQuery.fn.placeholder = function(text) {
  return this.each(function() {
program/js/list.js
@@ -51,7 +51,7 @@
  this.rowcount = 0;
  this.colcount = 0;
  this.subject_col = -1;
  this.subject_col = 0;
  this.modkey = 0;
  this.multiselect = false;
  this.multiexpand = false;
@@ -60,6 +60,7 @@
  this.column_movable = false;
  this.keyboard = false;
  this.toggleselect = false;
  this.aria_listbox = false;
  this.drag_active = false;
  this.col_drag_active = false;
@@ -75,6 +76,9 @@
  if (p && typeof p === 'object')
    for (var n in p)
      this[n] = p[n];
  // register this instance
  rcube_list_widget._instances.push(this);
};
@@ -94,11 +98,17 @@
    this.tbody = this.list;
  }
  if ($(this.list).attr('role') == 'listbox') {
    this.aria_listbox = true;
    if (this.multiselect)
      $(this.list).attr('aria-multiselectable', 'true');
  }
  if (this.tbody) {
    this.rows = {};
    this.rowcount = 0;
    var r, len, rows = this.tbody.childNodes;
    var r, len, rows = this.tbody.childNodes, me = this;
    for (r=0, len=rows.length; r<len; r++) {
      this.rowcount += this.init_row(rows[r]) ? 1 : 0;
@@ -108,8 +118,13 @@
    this.frame = this.list.parentNode;
    // set body events
    if (this.keyboard)
    if (this.keyboard) {
      rcube_event.add_listener({event:'keydown', object:this, method:'key_press'});
      // allow the table element to receive focus.
      $(this.list).attr('tabindex', '0')
        .on('focus', function(e){ me.focus(e); });
    }
  }
  return this;
@@ -154,6 +169,15 @@
      }, false);
    }
    // label the list row with the subject col as descriptive label
    if (this.aria_listbox) {
      var lbl_id = 'l:' + row.id;
      $(row)
        .attr('role', 'option')
        .attr('aria-labelledby', lbl_id)
        .find(this.col_tagname()).eq(this.subject_col).attr('id', lbl_id);
    }
    if (document.all)
      row.onselectstart = function() { return false; };
@@ -175,7 +199,7 @@
    if (this.fixed_header) {  // copy (modified) fixed header back to the actual table
      $(this.list.tHead).replaceWith($(this.fixed_header).find('thead').clone());
      $(this.list.tHead).find('tr td').attr('style', '');  // remove fixed widths
      $(this.list.tHead).find('th,td').attr('style', '').find('a').attr('tabindex', '-1');  // remove fixed widths
    }
    else if (!bw.touch && this.list.className.indexOf('fixedheader') >= 0) {
      this.init_fixed_header();
@@ -202,6 +226,7 @@
  if (!this.fixed_header) {
    this.fixed_header = $('<table>')
      .attr('class', this.list.className + ' fixedcopy')
      .attr('role', 'presentation')
      .css({ position:'fixed' })
      .append(clone)
      .append('<tbody></tbody>');
@@ -219,6 +244,12 @@
  else {
    $(this.fixed_header).find('thead').replaceWith(clone);
  }
  // avoid scrolling header links being focused
  $(this.list.tHead).find('a.sortcol').attr('tabindex', '-1');
  // set tabindex to fixed header sort links
  clone.find('a.sortcol').attr('tabindex', '0');
  this.thead = clone.get(0);
  this.resize();
@@ -262,6 +293,7 @@
  this.rows = {};
  this.rowcount = 0;
  this.last_selected = 0;
  if (sel)
    this.clear_selection();
@@ -370,39 +402,66 @@
 */
focus: function(e)
{
  var n, id;
  if (this.focused)
    return;
  this.focused = true;
  for (n in this.selection) {
    id = this.selection[n];
    if (this.rows[id] && this.rows[id].obj) {
      $(this.rows[id].obj).addClass('selected').removeClass('unfocused');
    }
  if (e)
    rcube_event.cancel(e);
  var focus_elem = null;
  if (this.last_selected && this.rows[this.last_selected]) {
    focus_elem = $(this.rows[this.last_selected].obj).find(this.col_tagname()).eq(this.subject_col).attr('tabindex', '0');
  }
  // Un-focus already focused elements (#1487123, #1487316, #1488600, #1488620)
  // It looks that window.focus() does the job for all browsers, but not Firefox (#1489058)
  $('iframe,:focus:not(body)').blur();
  window.focus();
  if (focus_elem && focus_elem.length) {
    // We now fix this by explicitly assigning focus to a dedicated link element
    this.focus_noscroll(focus_elem);
  }
  else {
    // It looks that window.focus() does the job for all browsers, but not Firefox (#1489058)
    $('iframe,:focus:not(body)').blur();
    window.focus();
  }
  if (e || (e = window.event))
    rcube_event.cancel(e);
  $(this.list).addClass('focus').removeAttr('tabindex');
  // set internal focus pointer to first row
  if (!this.last_selected)
    this.select_first(CONTROL_KEY);
},
/**
 * remove focus from the list
 */
blur: function()
blur: function(e)
{
  var n, id;
  this.focused = false;
  for (n in this.selection) {
    id = this.selection[n];
    if (this.rows[id] && this.rows[id].obj) {
      $(this.rows[id].obj).removeClass('selected focused').addClass('unfocused');
    }
  // avoid the table getting focus right again
  var me = this;
  setTimeout(function(){
    $(me.list).removeClass('focus').attr('tabindex', '0');
  }, 20);
  if (this.last_selected && this.rows[this.last_selected]) {
    $(this.rows[this.last_selected].obj)
      .find(this.col_tagname()).eq(this.subject_col).removeAttr('tabindex');
  }
},
/**
 * Focus the given element without scrolling the list container
 */
focus_noscroll: function(elem)
{
  var y = this.frame.scrollTop || this.frame.scrollY;
  elem.focus();
  this.frame.scrollTop = y;
},
@@ -522,6 +581,8 @@
  }
  this.rows[id].clicked = now;
  this.focus();
  return false;
},
@@ -794,9 +855,9 @@
get_first_row: function()
{
  if (this.rowcount) {
    var i, len, uid, rows = this.tbody.childNodes;
    var i, uid, rows = this.tbody.childNodes;
    for (i=0, len=rows.length-1; i<len; i++)
    for (i=0; i<rows.length; i++)
      if (rows[i].id && (uid = this.get_row_uid(rows[i])))
        return uid;
  }
@@ -839,9 +900,10 @@
 */
select_row: function(id, mod_key, with_mouse)
{
  var select_before = this.selection.join(',');
  var select_before = this.selection.join(','),
    in_selection_before = this.in_selection(id);
  if (!this.multiselect)
  if (!this.multiselect && with_mouse)
    mod_key = 0;
  if (!this.shift_start)
@@ -877,20 +939,26 @@
    this.multi_selecting = true;
  }
  // trigger event if selection changed
  if (this.selection.join(',') != select_before)
    this.triggerEvent('select');
  if (this.last_selected != 0 && this.rows[this.last_selected])
    $(this.rows[this.last_selected].obj).removeClass('focused');
  if (this.last_selected != 0 && this.rows[this.last_selected]) {
    $(this.rows[this.last_selected].obj).removeClass('focused')
      .find(this.col_tagname()).eq(this.subject_col).removeAttr('tabindex');
  }
  // unselect if toggleselect is active and the same row was clicked again
  if (this.toggleselect && this.last_selected == id) {
  if (this.toggleselect && in_selection_before) {
    this.clear_selection();
    id = null;
  }
  else
  // trigger event if selection changed
  else if (this.selection.join(',') != select_before) {
    this.triggerEvent('select');
  }
  if (this.rows[id]) {
    $(this.rows[id].obj).addClass('focused');
    // set cursor focus to link inside selected row
    if (this.focused)
      this.focus_noscroll($(this.rows[id].obj).find(this.col_tagname()).eq(this.subject_col).attr('tabindex', '0'));
  }
  if (!this.selection.length)
    this.shift_start = null;
@@ -1038,7 +1106,7 @@
      this.highlight_row(n, true, true);
    }
    else {
      $(this.rows[n].obj).removeClass('selected').removeClass('unfocused');
      $(this.rows[n].obj).removeClass('selected').removeAttr('aria-selected');
    }
  }
@@ -1095,14 +1163,16 @@
  else {
    for (n in this.selection)
      if (this.rows[this.selection[n]]) {
        $(this.rows[this.selection[n]].obj).removeClass('selected').removeClass('unfocused');
        $(this.rows[this.selection[n]].obj).removeClass('selected').removeAttr('aria-selected');
      }
    this.selection = [];
  }
  if (num_select && !this.selection.length && !no_event)
  if (num_select && !this.selection.length && !no_event) {
    this.triggerEvent('select');
    this.last_selected = 0;
  }
},
@@ -1156,13 +1226,13 @@
    if (this.selection.length > 1 || !this.in_selection(id)) {
      this.clear_selection(null, true);
      this.selection[0] = id;
      $(this.rows[id].obj).addClass('selected');
      $(this.rows[id].obj).addClass('selected').attr('aria-selected', 'true');
    }
  }
  else {
    if (!this.in_selection(id)) { // select row
      this.selection.push(id);
      $(this.rows[id].obj).addClass('selected');
      $(this.rows[id].obj).addClass('selected').attr('aria-selected', 'true');
      if (!norecur && !this.rows[id].expanded)
        this.highlight_children(id, true);
    }
@@ -1172,7 +1242,7 @@
        a_post = this.selection.slice(p+1, this.selection.length);
      this.selection = a_pre.concat(a_post);
      $(this.rows[id].obj).removeClass('selected').removeClass('unfocused');
      $(this.rows[id].obj).removeClass('selected').removeAttr('aria-selected');
      if (!norecur && !this.rows[id].expanded)
        this.highlight_children(id, false);
    }
@@ -1252,6 +1322,14 @@
      return rcube_event.cancel(e);
    case 9: // Tab
      this.blur();
      break;
    case 13: // Enter
      if (!this.selection.length)
        this.select_row(this.last_selected, mod_key, false);
    default:
      this.key_pressed = keyCode;
      this.modkey = mod_key;
@@ -1311,8 +1389,16 @@
  }
  if (new_row) {
    // simulate ctr-key if no rows are selected
    if (!mod_key && !this.selection.length)
      mod_key = CONTROL_KEY;
    this.select_row(new_row.uid, mod_key, false);
    this.scrollto(new_row.uid);
  }
  else if (!new_row && !selected_row) {
    // select the first row if none selected yet
    this.select_first(CONTROL_KEY);
  }
  return false;
@@ -1708,3 +1794,6 @@
rcube_list_widget.prototype.addEventListener = rcube_event_engine.prototype.addEventListener;
rcube_list_widget.prototype.removeEventListener = rcube_event_engine.prototype.removeEventListener;
rcube_list_widget.prototype.triggerEvent = rcube_event_engine.prototype.triggerEvent;
// static
rcube_list_widget._instances = [];
program/js/treelist.js
@@ -55,6 +55,7 @@
    drag_active = false,
    search_active = false,
    last_search = '',
    has_focus = false,
    box_coords = {},
    item_coords = [],
    autoexpand_timer,
@@ -151,6 +152,19 @@
    })
  }
  container.on('focusin', function(e){
      // TODO: only accept focus on virtual nodes from keyboard events
      has_focus = true;
    })
    .on('focusout', function(e){
      has_focus = false;
    });
  container.attr('role', 'tree');
  $(document.body)
    .bind('keydown', keypress);
  /////// private methods
@@ -201,13 +215,13 @@
  function select(id)
  {
    if (selection) {
      id2dom(selection).removeClass('selected');
      id2dom(selection).removeClass('selected').removeAttr('aria-selected');
      selection = null;
    }
    var li = id2dom(id);
    if (li.length) {
      li.addClass('selected');
      li.addClass('selected').attr('aria-selected', 'true');
      selection = id;
      // TODO: expand all parent nodes if collapsed
      scroll_to_node(li);
@@ -262,6 +276,7 @@
    // insert as child of an existing node
    if (parent_node) {
      node.level = parent_node.level + 1;
      if (!parent_node.children)
        parent_node.children = [];
@@ -296,6 +311,7 @@
    }
    // insert at top level
    else {
      node.level = 0;
      data.push(node);
      li = render_node(node, container);
    }
@@ -392,7 +408,7 @@
   */
  function update_data()
  {
    data = walk_list(container);
    data = walk_list(container, 0);
  }
  /**
@@ -401,6 +417,7 @@
  function update_dom(node)
  {
    var li = id2dom(node.id);
    li.attr('aria-expanded', node.collapsed ? 'false' : 'true');
    li.children('ul').first()[(node.collapsed ? 'hide' : 'show')]();
    li.children('div.treetoggle').removeClass('collapsed expanded').addClass(node.collapsed ? 'collapsed' : 'expanded');
    me.triggerEvent('toggle', node);
@@ -507,6 +524,7 @@
    // render child nodes
    for (var i=0; i < data.length; i++) {
      data[i].level = 0;
      render_node(data[i], container);
    }
@@ -523,6 +541,7 @@
    var li = $('<li>')
      .attr('id', p.id_prefix + (p.id_encode ? p.id_encode(node.id) : node.id))
      .attr('role', 'treeitem')
      .addClass((node.classes || []).join(' '))
      .data('id', node.id);
@@ -546,12 +565,14 @@
    // add child list and toggle icon
    if (node.children && node.children.length) {
      li.attr('aria-expanded', node.collapsed ? 'false' : 'true');
      $('<div class="treetoggle '+(node.collapsed ? 'collapsed' : 'expanded') + '">&nbsp;</div>').appendTo(li);
      var ul = $('<ul>').appendTo(li).attr('class', node.childlistclass);
      var ul = $('<ul>').appendTo(li).attr('class', node.childlistclass).attr('role', 'group');
      if (node.collapsed)
        ul.hide();
      for (var i=0; i < node.children.length; i++) {
        node.children[i].level = node.level + 1;
        render_node(node.children[i], ul);
      }
    }
@@ -563,7 +584,7 @@
   * Recursively walk the DOM tree and build an internal data structure
   * representing the skeleton of this tree list.
   */
  function walk_list(ul)
  function walk_list(ul, level)
  {
    var result = [];
    ul.children('li').each(function(i,e){
@@ -572,9 +593,10 @@
        id: dom2id(li),
        classes: String(li.attr('class')).split(' '),
        virtual: li.hasClass('virtual'),
        level: level,
        html: li.children().first().get(0).outerHTML,
        text: li.children().first().text(),
        children: walk_list(sublist)
        children: walk_list(sublist, level+1)
      }
      if (sublist.length) {
@@ -592,15 +614,29 @@
        if (!li.children('div.treetoggle').length)
          $('<div class="treetoggle '+(node.collapsed ? 'collapsed' : 'expanded') + '">&nbsp;</div>').appendTo(li);
        li.attr('aria-expanded', node.collapsed ? 'false' : 'true');
      }
      if (li.hasClass('selected')) {
        li.attr('aria-selected', 'true');
        selection = node.id;
      }
      li.data('id', node.id);
      // declare list item as treeitem
      li.attr('role', 'treeitem').attr('aria-level', node.level+1);
      // allow virtual nodes to receive focus
      if (node.virtual) {
        li.children('a:first').attr('tabindex', '0');
      }
      result.push(node);
      indexbyid[node.id] = node;
    })
    });
    ul.attr('role', level == 0 ? 'tree' : 'group');
    return result;
  }
@@ -683,6 +719,70 @@
    return undefined;
  }
  /**
   * Handler for keyboard events on treelist
   */
  function keypress(e)
  {
    var target = e.target || {},
      keyCode = rcube_event.get_keycode(e);
    if (!has_focus || target.nodeName == 'INPUT' || target.nodeName == 'TEXTAREA' || target.nodeName == 'SELECT')
      return true;
    switch (keyCode) {
      case 38:
      case 40:
      case 63232: // 'up', in safari keypress
      case 63233: // 'down', in safari keypress
        var li = container.find(':focus').closest('li');
        if (li.length) {
          focus_next(li, (mod = keyCode == 38 || keyCode == 63232 ? -1 : 1));
        }
        break;
      case 37: // Left arrow key
      case 39: // Right arrow key
        var id, node, li = container.find(':focus').closest('li');
        if (li.length) {
          id = dom2id(li);
          node = indexbyid[id];
          if (node && node.children.length)
            toggle(id, rcube_event.get_modifier(e) == SHIFT_KEY);  // toggle subtree
        }
        return false;
    }
    return true;
  }
  function focus_next(li, dir, from_child)
  {
    var mod = dir < 0 ? 'prev' : 'next',
      next = li[mod](), limit, parent;
    if (dir > 0 && !from_child && li.children('ul[role=group]:visible').length) {
      li.children('ul').children('li:first').children('a:first').focus();
    }
    else if (dir < 0 && !from_child && next.children('ul[role=group]:visible').length) {
      next.children('ul').children('li:last').children('a:last').focus();
    }
    else if (next.length && next.children('a:first')) {
      next.children('a:first').focus();
    }
    else {
      parent = li.parent().closest('li[role=treeitem]');
      if (parent.length)
        if (dir < 0) {
          parent.children('a:first').focus();
        }
        else {
          focus_next(parent, dir, true);
        }
    }
>>>>>>> dev-accessibility
  }
  ///// drag & drop support
program/lib/Roundcube/html.php
@@ -32,7 +32,7 @@
    public static $doctype = 'xhtml';
    public static $lc_tags = true;
    public static $common_attrib = array('id','class','style','title','align','unselectable');
    public static $common_attrib = array('id','class','style','title','align','unselectable','tabindex','role');
    public static $containers = array('iframe','div','span','p','h1','h2','h3','ul','form','textarea','table','thead','tbody','tr','th','td','style','script');
@@ -285,7 +285,9 @@
            // ignore not allowed attributes, except data-*
            if (!empty($allowed)) {
                if (!isset($allowed_f[$key]) && @substr_compare($key, 'data-', 0, 5) !== 0) {
                $is_data_attr = @substr_compare($key, 'data-', 0, 5) === 0;
                $is_aria_attr = @substr_compare($key, 'aria-', 0, 5) === 0;
                if (!$is_aria_attr && !isset($allowed_f[$key]) && (!$is_data_attr || !isset($allowed_f['data-*']))) {
                    continue;
                }
            }
@@ -835,7 +837,7 @@
        if (!empty($this->header)) {
            $rowcontent = '';
            foreach ($this->header as $c => $col) {
                $rowcontent .= self::tag($this->_col_tagname(), $col->attrib, $col->content);
                $rowcontent .= self::tag($this->_head_tagname(), $col->attrib, $col->content);
            }
            $thead = $this->tagname == 'table' ? self::tag('thead', null, self::tag('tr', null, $rowcontent, parent::$common_attrib)) :
                self::tag($this->_row_tagname(), array('class' => 'thead'), $rowcontent, parent::$common_attrib);
@@ -888,7 +890,16 @@
    private function _row_tagname()
    {
        static $row_tagnames = array('table' => 'tr', 'ul' => 'li', '*' => 'div');
        return $row_tagnames[$this->tagname] ? $row_tagnames[$this->tagname] : $row_tagnames['*'];
        return $row_tagnames[$this->tagname] ?: $row_tagnames['*'];
    }
    /**
     * Getter for the corresponding tag name for table row elements
     */
    private function _head_tagname()
    {
        static $head_tagnames = array('table' => 'th', '*' => 'span');
        return $head_tagnames[$this->tagname] ?: $head_tagnames['*'];
    }
    /**
@@ -897,7 +908,7 @@
    private function _col_tagname()
    {
        static $col_tagnames = array('table' => 'td', '*' => 'span');
        return $col_tagnames[$this->tagname] ? $col_tagnames[$this->tagname] : $col_tagnames['*'];
        return $col_tagnames[$this->tagname] ?: $col_tagnames['*'];
    }
}
program/localization/en_US/labels.inc
@@ -157,16 +157,24 @@
$labels['back']             = 'Back';
$labels['options']          = 'Options';
$labels['first'] = 'First';
$labels['last'] = 'Last';
$labels['previous'] = 'Previous';
$labels['next'] = 'Next';
$labels['select'] = 'Select';
$labels['all'] = 'All';
$labels['none'] = 'None';
$labels['currpage'] = 'Current page';
$labels['isread'] = 'Read';
$labels['unread'] = 'Unread';
$labels['flagged'] = 'Flagged';
$labels['unflagged'] = 'Not Flagged';
$labels['unanswered'] = 'Unanswered';
$labels['withattachment'] = 'With attachment';
$labels['deleted'] = 'Deleted';
$labels['undeleted'] = 'Not deleted';
$labels['replied'] = 'Replied';
$labels['forwarded'] = 'Forwarded';
$labels['invert'] = 'Invert';
$labels['filter'] = 'Filter';
$labels['list'] = 'List';
@@ -259,6 +267,7 @@
$labels['uploadprogress'] = '$percent ($current from $total)';
$labels['close']  = 'Close';
$labels['messageoptions']  = 'Message options...';
$labels['togglecomposeoptions'] = 'Toggle composition options';
$labels['low']     = 'Low';
$labels['lowest']  = 'Lowest';
@@ -348,7 +357,9 @@
$labels['editcontact'] = 'Edit contact';
$labels['contacts'] = 'Contacts';
$labels['contactproperties'] = 'Contact properties';
$labels['contactnameandorg'] = 'Name and Organization';
$labels['personalinfo'] = 'Personal information';
$labels['contactphoto'] = 'Contact photo';
$labels['edit']   = 'Edit';
$labels['cancel'] = 'Cancel';
@@ -372,6 +383,7 @@
$labels['grouprename']    = 'Rename group';
$labels['groupdelete']    = 'Delete group';
$labels['groupremoveselected'] = 'Remove selected contacts from group';
$labels['uponelevel']     = 'Up one level';
$labels['previouspage']   = 'Show previous page';
$labels['firstpage']      = 'Show first page';
@@ -468,6 +480,7 @@
$labels['2047folding'] = 'Full RFC 2047 (other)';
$labels['force7bit'] = 'Use MIME encoding for 8-bit characters';
$labels['advancedoptions'] = 'Advanced options';
$labels['toggleadvancedoptions'] = 'Toggle advanced options';
$labels['focusonnewmessage'] = 'Focus browser window on new message';
$labels['checkallfolders'] = 'Check all folders for new messages';
$labels['displaynext'] = 'After message delete/move display the next message';
@@ -569,4 +582,48 @@
$labels['korean'] = 'Korean';
$labels['chinese'] = 'Chinese';
// accessibility (voice-only) headings and descriptions
$labels['arialabeltopnav'] = 'Window control';
$labels['arialabeltasknav'] = 'Application tasks';
$labels['arialabeltoolbar'] = 'Application toolbar';
$labels['arialabelmessagessearchfilter'] = 'Email listing filter';
$labels['arialabelmailsearchform'] = 'Email message search form';
$labels['arialabelcontactsearchform'] = 'Contacts search form';
$labels['arialabelmailquicksearchbox'] = 'Email search input';
$labels['arialabelquicksearchbox'] = 'Search input';
$labels['arialabelfolderlist'] = 'Email folder selection';
$labels['arialabelmessagelist'] = 'Email Messages Listing';
$labels['arialabelmailpreviewframe'] = 'Message preview';
$labels['arialabelmailboxmenu'] = 'Folder actions menu';
$labels['arialabellistselectmenu'] = 'List selection menu';
$labels['arialabelthreadselectmenu'] = 'Threads listing menu';
$labels['arialabelmessagelistoptions'] = 'Message list display and sorting options';
$labels['arialabelmailimportdialog'] = 'Message import dialog';
$labels['arialabelmessagenav'] = 'Message navigation';
$labels['arialabelmessagebody'] = 'Message Body';
$labels['arialabelmessageactions'] = 'Message actions';
$labels['arialabelcontactquicksearch'] = 'Contacts search form';
$labels['arialabelcontactsearchbox'] = 'Contact search input';
$labels['arialabelmessageheaders'] = 'Message headers';
$labels['arialabelcomposeoptions'] = 'Composition options';
$labels['arialabelresponsesmenu'] = 'Canned responses menu';
$labels['arialabelattachmentuploadform'] = 'Attachment upload form';
$labels['arialabelattachmentpreview'] = 'Attachment preview';
$labels['ariasummarycomposecontacts'] = 'List of contacts and groups to select as recipients';
$labels['arialabelcontactexportoptions'] = 'Contact export options';
$labels['arialabelabookgroupoptions'] = 'Addressbook/group options';
$labels['arialabelpreferencesform'] = 'Preferences form';
$labels['arialabelidentityeditfrom'] = 'Identity edit form';
$labels['arialabelresonseeditfrom'] = 'Response edit form';
$labels['helplistnavigation'] = 'List keyboard navigation';
$labels['helplistkeyboardnavigation'] = "Arrows up/down: Move row focus/selection.
Space: Select focused row.
Shift + up/down: Select additional row above/below.
Ctrl + Space: Add focused row to selection/remove from selection.";
$labels['helplistkeyboardnavmessages'] = "Arrows right/left: expand/collapse message thread (in threads mode only).
Enter: Open the selected/focused message.
Delete: Move selected messages to Trash.";
$labels['helplistkeyboardnavcontacts'] = "Enter: Open the selected/focused contact.";
?>
program/steps/addressbook/edit.inc
@@ -98,12 +98,15 @@
function rcmail_contact_edithead($attrib)
{
    global $RCMAIL;
    // check if we have a valid result
    $record = rcmail_get_edit_record();
    $i_size = !empty($attrib['size']) ? $attrib['size'] : 20;
    $form = array(
        'head' => array(
            'name' => $RCMAIL->gettext('contactnameandorg'),
            'content' => array(
                'prefix' => array('size' => $i_size),
                'firstname' => array('size' => $i_size, 'visible' => true),
program/steps/addressbook/func.inc
@@ -395,7 +395,7 @@
                        ), '&raquo;');
                    }
                    else
                        $val = '&nbsp;';
                        $val = '';
                    break;
                default:
@@ -422,7 +422,7 @@
    unset($attrib['name']);
    $OUTPUT->add_gui_object('addresslist_title', $attrib['id']);
    $OUTPUT->add_label('contacts');
    $OUTPUT->add_label('contacts','uponelevel');
    return html::tag($attrib['tag'], $attrib, $RCMAIL->gettext($attrib['label']), html::$common_attrib);
}
@@ -518,7 +518,7 @@
    foreach ($coltypes as $col => $prop) {
        if ($prop['subtypes']) {
            $subtype_names = array_map('rcmail_get_type_label', $prop['subtypes']);
            $select_subtype = new html_select(array('name' => '_subtype_'.$col.'[]', 'class' => 'contactselectsubtype'));
            $select_subtype = new html_select(array('name' => '_subtype_'.$col.'[]', 'class' => 'contactselectsubtype', 'title' => $prop['label'] . ' ' . $RCMAIL->gettext('type')));
            $select_subtype->add($subtype_names, $prop['subtypes']);
            $coltypes[$col]['subtypes_select'] = $select_subtype->show();
        }
@@ -607,7 +607,7 @@
                // prepare subtype selector in edit mode
                if ($edit_mode && is_array($colprop['subtypes'])) {
                    $subtype_names = array_map('rcmail_get_type_label', $colprop['subtypes']);
                    $select_subtype = new html_select(array('name' => '_subtype_'.$col.'[]', 'class' => 'contactselectsubtype'));
                    $select_subtype = new html_select(array('name' => '_subtype_'.$col.'[]', 'class' => 'contactselectsubtype', 'title' => $colprop['label'] . ' ' . $RCMAIL->gettext('type')));
                    $select_subtype->add($subtype_names, $colprop['subtypes']);
                }
                else
@@ -648,6 +648,8 @@
                foreach ($values as $i => $val) {
                    if ($subtypes[$i])
                        $subtype = $subtypes[$i];
                    $colprop['id'] = 'ff_' . $col . intval($coltypes[$field]['count']);
                    // render composite field
                    if ($colprop['type'] == 'composite') {
@@ -714,7 +716,7 @@
                    // display row with label
                    if ($label) {
                        $rows .= html::div('row',
                            html::div('contactfieldlabel label', $select_subtype ? $select_subtype->show($subtype) : rcube::Q($label)) .
                            html::div('contactfieldlabel label', $select_subtype ? $select_subtype->show($subtype) : html::label($colprop['id'], rcube::Q($label))) .
                            html::div('contactfieldcontent '.$colprop['type'], $val));
                    }
                    else   // row without label
@@ -803,7 +805,7 @@
    else
        $ff_value = '-del-'; // will disable delete-photo action
    $img = html::img(array('src' => $photo_img, 'border' => 1, 'alt' => ''));
    $img = html::img(array('src' => $photo_img, 'border' => 1, 'alt' => $RCMAIL->gettext('contactphoto')));
    $content = html::div($attrib, $img);
    if ($CONTACT_COLTYPES['photo'] && ($RCMAIL->action == 'edit' || $RCMAIL->action == 'add')) {
program/steps/addressbook/show.inc
@@ -60,6 +60,7 @@
    $form = array(
        'head' => array(  // section 'head' is magic!
            'name' => $RCMAIL->gettext('contactnameandorg'),
            'content' => array(
                'prefix' => array('type' => 'text'),
                'firstname' => array('type' => 'text'),
program/steps/mail/compose.inc
@@ -969,7 +969,7 @@
        $OUTPUT->set_env('spellcheck_langs', join(',', $editor_lang_set));
    }
    $out .= "\n".'<iframe name="savetarget" src="program/resources/blank.gif" style="width:0;height:0;border:none;visibility:hidden;"></iframe>';
    $out .= "\n".'<iframe name="savetarget" src="program/resources/blank.gif" style="width:0;height:0;border:none;visibility:hidden;" aria-hidden="true"></iframe>';
    return $out;
}
@@ -1859,9 +1859,10 @@
    foreach ($RCMAIL->get_compose_responses(true) as $response) {
        $key = $response['key'];
        $item = html::a(array(
            'href '=> '#'.urlencode($response['name']),
            'href' => '#'.urlencode($response['name']),
            'class' => rtrim('insertresponse ' . $attrib['itemclass']),
            'unselectable' => 'on',
            'tabindex' => '0',
            'rel' => $key,
        ), rcube::Q($response['name']));
program/steps/mail/func.inc
@@ -111,7 +111,9 @@
    if (!$OUTPUT->ajax_call) {
        $OUTPUT->add_label('checkingmail', 'deletemessage', 'movemessagetotrash',
            'movingmessage', 'copyingmessage', 'deletingmessage', 'markingmessage',
            'copy', 'move', 'quota', 'replyall', 'replylist', 'stillsearching');
            'copy', 'move', 'quota', 'replyall', 'replylist', 'stillsearching',
            'flagged', 'unflagged', 'unread', 'deleted', 'replied', 'forwarded',
            'priority', 'withattachment');
    }
    $pagetitle = $RCMAIL->localize_foldername($mbox_name, true);
@@ -531,14 +533,19 @@
        $a_sort_cols = array('subject', 'date', 'from', 'to', 'fromto', 'size', 'cc');
    if (!empty($attrib['optionsmenuicon'])) {
        $onclick = 'return ' . rcmail_output::JS_OBJECT_NAME . ".command('menu-open', 'messagelistmenu')";
        if ($attrib['optionsmenuicon'] === true || $attrib['optionsmenuicon'] == 'true')
            $list_menu = html::div(array('onclick' => $onclick, 'class' => 'listmenu',
                'id' => 'listmenulink', 'title' => $RCMAIL->gettext('listoptions')));
        else
            $list_menu = html::a(array('href' => '#', 'onclick' => $onclick),
                html::img(array('src' => $skin_path . $attrib['optionsmenuicon'],
                    'id' => 'listmenulink', 'title' => $RCMAIL->gettext('listoptions'))));
        $onclick = 'return ' . rcmail_output::JS_OBJECT_NAME . ".command('menu-open', 'messagelistmenu', this, event)";
        $inner   = $RCMAIL->gettext('listoptions');
        if (is_string($attrib['optionsmenuicon']) && $attrib['optionsmenuicon'] != 'true') {
            $inner = html::img(array('src' => $skin_path . $attrib['optionsmenuicon'], 'alt' => $RCMAIL->gettext('listoptions')));
        }
        $list_menu = html::a(array(
            'href' => '#list-options',
            'onclick' => $onclick,
            'class' => 'listmenu',
            'id' => 'listmenulink',
            'title' => $RCMAIL->gettext('listoptions'),
            'tabindex' => '0',
        ), $inner);
    }
    else {
        $list_menu = '';
@@ -558,12 +565,14 @@
        // get column name
        switch ($col) {
        case 'flag':
            $col_name = html::span('flagged', '&nbsp;');
            $col_name = html::span('flagged', $RCMAIL->gettext('flagged'));
            break;
        case 'attachment':
        case 'priority':
            $col_name = html::span($col, $RCMAIL->gettext($col));
            break;
        case 'status':
            $col_name = html::span($col, '&nbsp;');
            $col_name = html::span($col, $RCMAIL->gettext('readstatus'));
            break;
        case 'threads':
            $col_name = $list_menu;
program/steps/mail/list_contacts.inc
@@ -110,7 +110,7 @@
            $keyname = $row['_type'] == 'group' ? 'contactgroup' : 'contact';
            $OUTPUT->command('add_contact_row', $row_id, array(
                $keyname => html::span(array('title' => $email), rcube::Q($name ? $name : $email) .
                $keyname => html::a(array('title' => $email), rcube::Q($name ? $name : $email) .
                    ($name && count($emails) > 1 ? '&nbsp;' . html::span('email', rcube::Q($email)) : '')
                )), $classname);
        }
program/steps/mail/search_contacts.inc
@@ -87,7 +87,7 @@
            $row_id = $row['ID'].'-'.$i;
            $jsresult[$row_id] = format_email_recipient($email, $name);
            $OUTPUT->command('add_contact_row', $row_id, array(
                'contact' => html::span(array('title' => $email), rcube::Q($name ? $name : $email) .
                'contact' => html::a(array('title' => $email), rcube::Q($name ? $name : $email) .
                    ($name && count($emails) > 1 ? '&nbsp;' . html::span('email', rcube::Q($email)) : '')
                )), 'person');
        }
program/steps/mail/show.inc
@@ -199,6 +199,7 @@
    if (sizeof($MESSAGE->attachments)) {
        foreach ($MESSAGE->attachments as $attach_prop) {
            $filename = rcmail_attachment_name($attach_prop, true);
            $size = '';
            if ($PRINT_MODE) {
                $size = $RCMAIL->message_part_size($attach_prop);
@@ -213,6 +214,10 @@
                    $title = '';
                }
                if ($attach_prop->size) {
                    $size = ' ' . html::span('attachment-size', '(' . $RCMAIL->show_bytes($attach_prop->size) . ')');
                }
                $mimetype = rcmail_fix_mimetype($attach_prop->mimetype);
                $class    = rcube_utils::file2class($mimetype, $filename);
                $id       = 'attach' . $attach_prop->mime_id;
@@ -222,7 +227,7 @@
                        rcmail_output::JS_OBJECT_NAME, $attach_prop->mime_id),
                    'onmouseover' => $title ? '' : 'rcube_webmail.long_subject_title_ex(this, 0)',
                    'title'       => rcube::Q($title),
                    ), rcube::Q($filename));
                    ), rcube::Q($filename) . $size);
                $ol .= html::tag('li', array('class' => $class, 'id' => $id), $link);
program/steps/settings/edit_folder.inc
@@ -132,6 +132,7 @@
        }
        $select = $RCMAIL->folder_selector(array(
            'id'          => '_parent',
            'name'        => '_parent',
            'noselection' => '---',
            'realnames'   => false,
@@ -155,7 +156,7 @@
    // Settings: threading
    if ($threading_supported && ($mbox_imap == 'INBOX' || (!$options['noselect'] && !$options['is_root']))) {
        $select = new html_select(array('name' => '_viewmode', 'id' => '_listmode'));
        $select = new html_select(array('name' => '_viewmode', 'id' => '_viewmode'));
        $select->add($RCMAIL->gettext('list'), 0);
        $select->add($RCMAIL->gettext('threads'), 1);
program/steps/settings/func.inc
@@ -343,7 +343,7 @@
                        if (is_array($meta) && $meta['name']) {
                            $skinname     = $meta['name'];
                            $author_link  = $meta['url'] ? html::a(array('href' => $meta['url'], 'target' => '_blank'), rcube::Q($meta['author'])) : rcube::Q($meta['author']);
                            $license_link = $meta['license-url'] ? html::a(array('href' => $meta['license-url'], 'target' => '_blank'), rcube::Q($meta['license'])) : rcube::Q($meta['license']);
                            $license_link = $meta['license-url'] ? html::a(array('href' => $meta['license-url'], 'target' => '_blank', 'tabindex' => '-1'), rcube::Q($meta['license'])) : rcube::Q($meta['license']);
                        }
                        $skinnames[] = mb_strtolower($skinname);
program/steps/settings/responses.inc
@@ -95,7 +95,7 @@
{
    global $RCMAIL, $OUTPUT;
    $attrib += array('id' => 'rcmresponseslist', 'tagname' => 'table', 'cols' => 1);
    $attrib += array('id' => 'rcmresponseslist', 'tagname' => 'table');
    $plugin = $RCMAIL->plugins->exec_hook('responses_list', array(
        'list' => $RCMAIL->get_compose_responses(true),
skins/classic/addressbook.css
@@ -279,6 +279,11 @@
    padding: 0;
}
#contacthead > legend
{
    display: none;
}
#contacthead .names span.namefield,
#contacthead .names input
{
skins/classic/common.css
@@ -609,6 +609,7 @@
/***** common table settings ******/
table.records-table thead tr th,
table.records-table thead tr td
{
  height: 20px;
@@ -619,6 +620,7 @@
  background: url(images/listheader.gif) top left repeat-x #CCC;
  font-size: 11px;
  font-weight: bold;
  text-align: left;
}
table.records-table tbody tr td
@@ -629,7 +631,8 @@
  white-space: nowrap;
  border-bottom: 1px solid #EBEBEB;
  overflow: hidden;
  text-align: left;
  text-align: left;
    outline: none;
}
table.records-table tr
skins/classic/mail.css
@@ -719,6 +719,7 @@
  z-index: 2;
}
.messagelist thead tr th,
.messagelist thead tr td
{
  height: 20px;
@@ -729,25 +730,26 @@
  background: url(images/listheader.gif) top left repeat-x #CCC;
  font-size: 11px;
  font-weight: bold;
  text-align: left;
}
.messagelist thead tr td.sortedASC,
.messagelist thead tr td.sortedDESC
.messagelist thead tr > .sortedASC,
.messagelist thead tr > .sortedDESC
{
  background-position: 0 -26px;
}
.messagelist thead tr td.sortedASC a
.messagelist thead tr > .sortedASC a
{
  background: url(images/icons/sort.gif) right 0 no-repeat;
}
.messagelist thead tr td.sortedDESC a
.messagelist thead tr > .sortedDESC a
{
  background: url(images/icons/sort.gif) right -14px no-repeat;
}
.messagelist thead tr td a
.messagelist thead tr a
{
  display: block;
  width: auto !important;
@@ -756,18 +758,19 @@
  text-decoration: none;
}
.messagelist thead tr td.size.sortedASC a,
.messagelist thead tr td.size.sortedDESC a
.messagelist thead tr > .size.sortedASC a,
.messagelist thead tr > .size.sortedDESC a
{
  padding-right: 18px;
}
.messagelist thead tr td.subject
.messagelist thead tr > .subject
{
  padding-left: 18px;
  width: 99%;
}
.messagelist tbody tr th,
.messagelist tbody tr td
{
  height: 20px;
@@ -780,6 +783,7 @@
  -o-text-overflow: ellipsis;
  border-bottom: 1px solid #EBEBEB;
  cursor: default;
  outline: none;
}
.messagelist tbody tr td a
@@ -803,40 +807,42 @@
  cursor: pointer;
}
.messagelist tr td.flag span,
.messagelist tr td.status span,
.messagelist tr td.attachment span,
.messagelist tr td.priority span
.messagelist tr > .flag span,
.messagelist tr > .status span,
.messagelist tr > .attachment span,
.messagelist tr > .priority span
{
  display: block;
  width: 15px;
  text-indent: -5000px;
  overflow: hidden;
}
.messagelist tr td div.collapsed,
.messagelist tr td div.expanded,
.messagelist tr td.threads div.listmenu,
.messagelist tr td.attachment span.attachment,
.messagelist tr td.attachment span.report,
.messagelist tr td.priority span.priority,
.messagelist tr td.priority span.prio1,
.messagelist tr td.priority span.prio2,
.messagelist tr td.priority span.prio3,
.messagelist tr td.priority span.prio4,
.messagelist tr td.priority span.prio5,
.messagelist tr td.flag span.flagged,
.messagelist tr td.flag span.unflagged,
.messagelist tr td.flag span.unflagged:hover,
.messagelist tr td.status span.status,
.messagelist tr td.status span.msgicon,
.messagelist tr td.status span.deleted,
.messagelist tr td.status span.unread,
.messagelist tr td.status span.unreadchildren,
.messagelist tr td.subject span.msgicon,
.messagelist tr td.subject span.deleted,
.messagelist tr td.subject span.unread,
.messagelist tr td.subject span.replied,
.messagelist tr td.subject span.forwarded,
.messagelist tr td.subject span.unreadchildren
.messagelist tr > .threads .listmenu,
.messagelist tr > .attachment span.attachment,
.messagelist tr > .attachment span.report,
.messagelist tr > .priority span.priority,
.messagelist tr > .priority span.prio1,
.messagelist tr > .priority span.prio2,
.messagelist tr > .priority span.prio3,
.messagelist tr > .priority span.prio4,
.messagelist tr > .priority span.prio5,
.messagelist tr > .flag span.flagged,
.messagelist tr > .flag span.unflagged,
.messagelist tr > .flag span.unflagged:hover,
.messagelist tr > .status span.status,
.messagelist tr > .status span.msgicon,
.messagelist tr > .status span.deleted,
.messagelist tr > .status span.unread,
.messagelist tr > .status span.unreadchildren,
.messagelist tr > .subject span.msgicon,
.messagelist tr > .subject span.deleted,
.messagelist tr > .subject span.unread,
.messagelist tr > .subject span.replied,
.messagelist tr > .subject span.forwarded,
.messagelist tr > .subject span.unreadchildren
{
  display: inline-block;
  vertical-align: middle;
@@ -845,99 +851,99 @@
  background: url(images/messageicons.png) center no-repeat;
}
.messagelist tr td.attachment span.attachment
.messagelist tr > .attachment span.attachment
{
  background-position: 0 -170px;
}
.messagelist tr td.attachment span.report
.messagelist tr > .attachment span.report
{
  background-position: 0 -255px;
}
.messagelist tr td.priority span.priority
.messagelist tr > .priority span.priority
{
  background-position: 0 -309px;
}
.messagelist tr td.priority span.prio5
.messagelist tr > .priority span.prio5
{
  background-position: 0 -358px;
}
.messagelist tr td.priority span.prio4
.messagelist tr > .priority span.prio4
{
  background-position: 0 -340px;
}
.messagelist tr td.priority span.prio3
.messagelist tr > .priority span.prio3
{
  background-position: 0 -324px;
}
.messagelist tr td.priority span.prio2
.messagelist tr > .priority span.prio2
{
  background-position: 0 -309px;
}
.messagelist tr td.priority span.prio1
.messagelist tr > .priority span.prio1
{
  background-position: 0 -290px;
}
.messagelist tr td.flag span.flagged
.messagelist tr > .flag span.flagged
{
  background-position: 0 -153px;
}
.messagelist tr td.flag span.unflagged:hover
.messagelist tr > .flag span.unflagged:hover
{
  background-position: 0 -136px;
}
.messagelist tr td.subject span.msgicon,
.messagelist tr td.subject span.unreadchildren
.messagelist tr > .subject span.msgicon,
.messagelist tr > .subject span.unreadchildren
{
  background-position: 0 -51px;
  margin: 0 2px;
}
.messagelist tr td.subject span.replied
.messagelist tr > .subject span.replied
{
  background-position: 0 -85px;
}
.messagelist tr td.subject span.forwarded
.messagelist tr > .subject span.forwarded
{
  background-position: 0 -68px;
}
.messagelist tr td.subject span.replied.forwarded
.messagelist tr > .subject span.replied.forwarded
{
  background-position: 0 -102px;
}
.messagelist tr td.status span.msgicon,
.messagelist tr td.flag span.unflagged,
.messagelist tr td.status span.unreadchildren
.messagelist tr > .status span.msgicon,
.messagelist tr > .flag span.unflagged,
.messagelist tr > .status span.unreadchildren
{
  background-position: 0 17px; /* no icon */
}
.messagelist tr td.status span.msgicon:hover
.messagelist tr > .status span.msgicon:hover
{
  background-position: 0 -272px;
}
.messagelist tr td.status span.deleted,
.messagelist tr td.subject span.deleted
.messagelist tr > .status span.deleted,
.messagelist tr > .subject span.deleted
{
  background-position: 0 -187px;
}
.messagelist tr td.status span.status,
.messagelist tr td.status span.unread,
.messagelist tr td.subject span.unread
.messagelist tr > .status span.status,
.messagelist tr > .status span.unread,
.messagelist tr > .subject span.unread
{
  background-position: 0 -119px;
}
@@ -954,10 +960,12 @@
  cursor: pointer;
}
.messagelist tr td.threads div.listmenu
.messagelist tr > .threads .listmenu
{
  background-position: 0 -238px;
  cursor: pointer;
  overflow: hidden;
  text-indent: -5000px;
}
.messagelist tbody tr td.subject
@@ -977,45 +985,45 @@
  text-decoration: underline;
}
.messagelist tr td.attachment,
.messagelist tr td.threads,
.messagelist tr td.status,
.messagelist tr td.flag,
.messagelist tr td.priority
.messagelist tr > .attachment,
.messagelist tr > .threads,
.messagelist tr > .status,
.messagelist tr > .flag,
.messagelist tr > .priority
{
  width: 17px;
  padding: 0 0 0 2px;
}
.messagelist tr td.size
.messagelist tr > .size
{
  width: 60px;
  text-align: right;
  padding: 0 2px;
}
.messagelist tr td.fromto,
.messagelist tr td.from,
.messagelist tr td.to,
.messagelist tr td.cc,
.messagelist tr td.replyto
.messagelist tr > .fromto,
.messagelist tr > .from,
.messagelist tr > .to,
.messagelist tr > .cc,
.messagelist tr > .replyto
{
  width: 180px;
  padding: 0 2px;
}
.messagelist tr td.date
.messagelist tr > .date
{
  width: 135px;
  padding: 0 2px;
}
.messagelist tr td.folder
.messagelist tr > .folder
{
  width: 135px;
}
.messagelist tr td.hidden
.messagelist tr > .hidden
{
  display: none;
}
@@ -1038,6 +1046,7 @@
}
/* This padding-left minus the focused padding left should be half of the focused border-left */
.messagelist thead tr th:first-child,
.messagelist thead tr td:first-child,
.messagelist tbody tr td:first-child {
    border-left: 0;
@@ -1058,21 +1067,15 @@
.messagelist tr.selected td
{
  color: #FFFFFF;
  background-color: #CC3333;
}
.messagelist tr.unfocused td
{
  color: #FFFFFF;
  background-color: #929292;
}
.messagelist tr.selected td a
.messagelist.focus tr.selected td
{
  color: #FFFFFF;
  background-color: #CC3333;
}
.messagelist tr.unfocused td a
.messagelist tr.selected td a
{
  color: #FFFFFF;
}
skins/larry/addressbook.css
@@ -138,56 +138,25 @@
    background: url(images/listicons.png) -2px -1180px no-repeat;
}
/* This padding-left should be equal to the focused border-left + the focused padding-left */
#contacts-table thead tr td:first-child,
#contacts-table tbody tr td:first-child {
    border-left: 0;
    padding-left: 36px;
}
/* because of border-collapse, we make the left border twice what we want it to be - half will be hidden to the left */
#contacts-table tbody tr.focused > td:first-child {
    border-left: 2px solid #b0ccd7;
    padding-left: 34px;
}
#contacts-table tbody tr.selected.focused > td:first-child {
    border-left-color: #9ec2d0;
}
#contacts-table .contact td.name {
    background-position: 6px -1603px;
}
#contacts-table .contact.focused td.name {
    background-position: 4px -1603px;
}
#contacts-table .contact.selected td.name,
#contacts-table .contact.unfocused td.name {
    background-position: 6px -1627px;
    font-weight: bold;
}
#contacts-table .contact.selected.focused td.name {
#contacts-table .contact.selected td.name {
    background-position: 4px -1627px;
    font-weight: bold;
}
#contacts-table .group td.name {
    background-position: 6px -1555px;
}
#contacts-table .group.focused td.name {
    background-position: 4px -1555px;
}
#contacts-table .group.selected td.name,
#contacts-table .group.unfocused td.name {
    background-position: 6px -1579px;
#contacts-table .group.selected td.name {
    background-position: 4px -1579px;
    font-weight: bold;
}
#contacts-table .group.selected.focused td.name {
#contacts-table.focus .group.selected.focused td.name {
    background-position: 4px -1579px;
}
@@ -232,6 +201,8 @@
    float: left;
    margin: 0 18px 20px 0;
    width: 112px;
    border: 0;
    padding: 0;
}
#contactpic {
@@ -267,6 +238,10 @@
    opacity: 0.05;
}
#contactphoto .formlinks a[aria-disabled='true'] {
    visibility: hidden;
}
#contacthead {
    border: 0;
    margin: 0 16em 1em 0;
@@ -275,6 +250,10 @@
    font-size: 12px;
}
#contacthead > legend {
    display: none;
}
form #contacthead {
    margin-right: 0;
}
skins/larry/includes/footer.html
@@ -6,6 +6,7 @@
var UI = new rcube_mail_ui();
$(document).ready(function(){
    UI.set('errortitle', '<roundcube:label name="errortitle" quoting="javascript" />');
    UI.set('toggleoptions', '<roundcube:label name="toggleadvancedoptions" quoting="javascript" />');
    UI.init();
});
skins/larry/includes/header.html
@@ -1,5 +1,6 @@
<div id="header">
<div id="topline">
<div id="topline" role="banner" aria-labelledby="aria-label-topnav">
    <h2 id="aria-label-topnav" class="voice"><roundcube:label name="arialabeltopnav" /></h2>
    <div class="topleft">
        <roundcube:container name="topline-left" id="topline-left" />
        <roundcube:button name="about" type="link" label="about" class="about-link" onclick="UI.show_about(this);return false" condition="!env:extwin" />
@@ -21,13 +22,14 @@
<roundcube:if condition="!env:extwin &amp;&amp; !env:framed" />
<div id="topnav">
    <div id="taskbar" class="topright">
    <roundcube:button command="mail" label="mail" class="button-mail" classSel="button-mail button-selected" innerClass="button-inner" />
    <roundcube:button command="addressbook" label="addressbook" class="button-addressbook" classSel="button-addressbook button-selected" innerClass="button-inner" />
    <roundcube:container name="taskbar" id="taskbar" />
    <roundcube:button command="settings" label="settings" class="button-settings" classSel="button-settings button-selected" innerClass="button-inner" />
    <roundcube:button command="logout" label="logout" class="button-logout" classSel="button-logout" innerClass="button-inner" />
    <span class="minmodetoggle"></span>
    <h2 id="aria-label-tasknav" class="voice"><roundcube:label name="arialabeltasknav" /></h2>
    <div id="taskbar" class="topright" role="navigation" aria-labelledby="aria-label-tasknav">
        <roundcube:button command="mail" label="mail" class="button-mail" classSel="button-mail button-selected" innerClass="button-inner" />
        <roundcube:button command="addressbook" label="addressbook" class="button-addressbook" classSel="button-addressbook button-selected" innerClass="button-inner" />
        <roundcube:container name="taskbar" id="taskbar" />
        <roundcube:button command="settings" label="settings" class="button-settings" classSel="button-settings button-selected" innerClass="button-inner" />
        <roundcube:button command="logout" label="logout" class="button-logout" classSel="button-logout" innerClass="button-inner" />
        <span class="minmodetoggle" role="presentation"></span>
    </div>
    <roundcube:object name="logo" src="/images/roundcube_logo.png" id="toplogo" alt="Logo" onclick="if(window.rcmail)rcmail.command('switch-task','mail')" />
</div>
skins/larry/includes/mailtoolbar.html
@@ -3,11 +3,11 @@
<roundcube:button command="reply" type="link" class="button reply disabled" classAct="button reply" classSel="button reply pressed" label="reply" title="replytomessage" />
<span class="dropbutton">
    <roundcube:button command="reply-all" type="link" class="button reply-all disabled" classAct="button reply-all" classSel="button reply-all pressed" label="replyall" title="replytoallmessage" />
    <span class="dropbuttontip" id="replyallmenulink" onclick="UI.show_popup('replyallmenu');return false"></span>
    <a href="#reply-all" class="dropbuttontip" id="replyallmenulink" onclick="UI.toggle_popup('replyallmenu',event);return false" aria-haspopup="true" aria-expanded="false" aria-owns="replyallmenu-menu" tabindex="0">Reply-all options</a>
</span>
<span class="dropbutton">
    <roundcube:button command="forward" type="link" class="button forward disabled" classAct="button forward" classSel="button forward pressed" label="forward" title="forwardmessage" />
    <span class="dropbuttontip" id="forwardmenulink" onclick="UI.show_popup('forwardmenu');return false"></span>
    <a href="#forward" class="dropbuttontip" id="forwardmenulink" onclick="UI.toggle_popup('forwardmenu',event);return false" aria-haspopup="true" aria-expanded="false" aria-owns="forwardmenu-menu" tabindex="0">Forwarding options</a>
</span>
<roundcube:button command="delete" type="link" class="button delete disabled" classAct="button delete" classSel="button delete pressed" label="delete" title="deletemessage" />
<roundcube:if condition="template:name == 'message'" />
@@ -15,44 +15,48 @@
<roundcube:button command="print" type="link" class="button print disabled" classAct="button print" classSel="button print pressed" label="print" title="printmessage" />
<roundcube:endif />
<roundcube:container name="toolbar" id="mailtoolbar" />
<roundcube:button name="markmenulink" id="markmessagemenulink" type="link" class="button markmessage" label="mark" title="markmessages" onclick="UI.show_popup('markmessagemenu');return false" />
<roundcube:button name="messagemenulink" id="messagemenulink" type="link" class="button more" label="more" title="moreactions" onclick="UI.show_popup('messagemenu');return false" />
<roundcube:button name="markmenulink" id="markmessagemenulink" type="link" class="button markmessage" label="mark" title="markmessages" onclick="UI.toggle_popup('markmessagemenu',event);return false" aria-haspopup="true" aria-expanded="false" aria-owns="markmessagemenu-menu" />
<roundcube:button name="messagemenulink" id="messagemenulink" type="link" class="button more" label="more" title="moreactions" onclick="UI.toggle_popup('messagemenu',event);return false" aria-haspopup="true" aria-expanded="false" aria-owns="messagemenu-menu" />
<div id="forwardmenu" class="popupmenu">
    <ul class="toolbarmenu">
        <li><roundcube:button command="forward-inline" label="forwardinline" prop="sub" classAct="forwardlink active" class="forwardlink" /></li>
        <li><roundcube:button command="forward-attachment" label="forwardattachment" prop="sub" classAct="forwardattachmentlink active" class="forwardattachmentlink" /></li>
<div id="forwardmenu" class="popupmenu" aria-hidden="true">
    <h3 id="aria-label-forwardmenu" class="voice">Forwarding options</h3>
    <ul id="forwardmenu-menu" class="toolbarmenu" role="menu" aria-labelledby="aria-label-forwardmenu">
        <li role="menuitem"><roundcube:button command="forward-inline" label="forwardinline" prop="sub" classAct="forwardlink active" class="forwardlink" /></li>
        <li role="menuitem"><roundcube:button command="forward-attachment" label="forwardattachment" prop="sub" classAct="forwardattachmentlink active" class="forwardattachmentlink" /></li>
        <roundcube:container name="forwardmenu" id="forwardmenu" />
    </ul>
</div>
<div id="replyallmenu" class="popupmenu">
    <ul class="toolbarmenu">
        <li><roundcube:button command="reply-all" label="replyall" prop="sub" class="replyalllink" classAct="replyalllink active" /></li>
        <li><roundcube:button command="reply-list" label="replylist" prop="sub" class="replylistlink" classAct="replylistlink active" /></li>
<div id="replyallmenu" class="popupmenu" aria-hidden="true">
    <h3 id="aria-label-replyallmenu" class="voice">Reply-all options</h3>
    <ul id="replyallmenu-menu" class="toolbarmenu" role="menu" aria-labelledby="aria-label-replyallmenu">
        <li role="menuitem"><roundcube:button command="reply-all" label="replyall" prop="sub" class="replyalllink" classAct="replyalllink active" /></li>
        <li role="menuitem"><roundcube:button command="reply-list" label="replylist" prop="sub" class="replylistlink" classAct="replylistlink active" /></li>
        <roundcube:container name="replyallmenu" id="replyallmenu" />
    </ul>
</div>
<div id="messagemenu" class="popupmenu">
  <ul class="toolbarmenu iconized">
    <li><roundcube:button command="print" label="printmessage" class="icon" classAct="icon active" innerclass="icon print" /></li>
    <li><roundcube:button command="download" label="emlsave" class="icon" classAct="icon active" innerclass="icon download" /></li>
    <li><roundcube:button command="edit" prop="new" label="editasnew" class="icon" classAct="icon active" innerclass="icon edit" /></li>
    <li><roundcube:button command="viewsource" label="viewsource" class="icon" classAct="icon active" innerclass="icon viewsource" /></li>
    <li><roundcube:button command="move" label="moveto" class="icon" classAct="icon active" innerclass="icon move folder-selector-link" /></li>
    <li><roundcube:button command="copy" label="copyto" class="icon" classAct="icon active" innerclass="icon copy folder-selector-link" /></li>
    <li><roundcube:button command="open" label="openinextwin" target="_blank" class="icon" classAct="icon active" innerclass="icon extwin" /></li>
<div id="messagemenu" class="popupmenu" aria-hidden="true">
  <h3 id="aria-label-messagemenu" class="voice">More message toolbar actions</h3>
  <ul id="messagemenu-menu" class="toolbarmenu iconized" role="menu" aria-labelledby="aria-label-messagemenu">
    <li role="menuitem"><roundcube:button command="print" label="printmessage" class="icon" classAct="icon active" innerclass="icon print" /></li>
    <li role="menuitem"><roundcube:button command="download" label="emlsave" class="icon" classAct="icon active" innerclass="icon download" /></li>
    <li role="menuitem"><roundcube:button command="edit" prop="new" label="editasnew" class="icon" classAct="icon active" innerclass="icon edit" /></li>
    <li role="menuitem"><roundcube:button command="viewsource" label="viewsource" class="icon" classAct="icon active" innerclass="icon viewsource" /></li>
    <li role="menuitem"><roundcube:button command="move" label="moveto" class="icon" classAct="icon active" innerclass="icon move folder-selector-link" /></li>
    <li role="menuitem"><roundcube:button command="copy" label="copyto" class="icon" classAct="icon active" innerclass="icon copy folder-selector-link" /></li>
    <li role="menuitem"><roundcube:button command="open" label="openinextwin" target="_blank" class="icon" classAct="icon active" innerclass="icon extwin" /></li>
    <roundcube:container name="messagemenu" id="messagemenu" />
  </ul>
</div>
<div id="markmessagemenu" class="popupmenu">
  <ul class="toolbarmenu iconized">
    <li><roundcube:button command="mark" prop="read" label="markread" classAct="icon active" class="icon" innerclass="icon read" /></li>
    <li><roundcube:button command="mark" prop="unread" label="markunread" classAct="icon active" class="icon" innerclass="icon unread" /></li>
    <li><roundcube:button command="mark" prop="flagged" label="markflagged" classAct="icon active" class="icon" innerclass="icon flagged" /></li>
    <li><roundcube:button command="mark" prop="unflagged" label="markunflagged" classAct="icon active" class="icon" innerclass="icon unflagged" /></li>
<div id="markmessagemenu" class="popupmenu" aria-hidden="true">
  <h3 id="aria-label-markmessagemenu" class="voice">Mark selected messages as...</h3>
  <ul id="markmessagemenu-menu" class="toolbarmenu iconized" role="menu" aria-labelledby="aria-label-markmessagemenu">
    <li role="menuitem"><roundcube:button command="mark" prop="read" label="markread" classAct="icon active" class="icon" innerclass="icon read" /></li>
    <li role="menuitem"><roundcube:button command="mark" prop="unread" label="markunread" classAct="icon active" class="icon" innerclass="icon unread" /></li>
    <li role="menuitem"><roundcube:button command="mark" prop="flagged" label="markflagged" classAct="icon active" class="icon" innerclass="icon flagged" /></li>
    <li role="menuitem"><roundcube:button command="mark" prop="unflagged" label="markunflagged" classAct="icon active" class="icon" innerclass="icon unflagged" /></li>
    <roundcube:container name="markmenu" id="markmessagemenu" />
  </ul>
</div>
skins/larry/includes/settingstabs.html
@@ -1,7 +1,9 @@
<div id="settings-sections" class="uibox listbox">
<h2 class="boxtitle"><roundcube:label name="settings" /></h2>
<div id="settings-sections" class="uibox listbox" role="navigation" aria-labelledby="aria-label-settingstabs">
<h2 class="boxtitle" id="aria-label-settingstabs"><roundcube:label name="settings" /></h2>
<div id="settings-tabs" class="scroller">
    <roundcube:object name="settingstabs" class="listitem" />
    <ul class="listing iconized">
        <roundcube:object name="settingstabs" class="listitem" tagname="li" />
    </ul>
    <roundcube:container name="tabs" id="settings-tabs" />
</div>
</div>
skins/larry/mail.css
@@ -162,6 +162,7 @@
    padding-right: 36px;
}
#mailboxlist li.mailbox > a:focus,
#mailboxlist li.mailbox.selected > a {
    background-position: 6px -21px;
}
@@ -170,6 +171,7 @@
    background-position: 6px -189px;
}
#mailboxlist li.mailbox.inbox > a:focus,
#mailboxlist li.mailbox.inbox.selected > a {
    background-position: 6px -213px;
}
@@ -178,6 +180,7 @@
    background-position: 6px -238px;
}
#mailboxlist li.mailbox.drafts > a:focus,
#mailboxlist li.mailbox.drafts.selected > a {
    background-position: 6px -262px;
}
@@ -186,6 +189,7 @@
    background-position: 6px -286px;
}
#mailboxlist li.mailbox.sent > a:focus,
#mailboxlist li.mailbox.sent.selected > a {
    background-position: 6px -310px;
}
@@ -194,6 +198,7 @@
    background-position: 6px -334px;
}
#mailboxlist li.mailbox.junk > a:focus,
#mailboxlist li.mailbox.junk.selected > a {
    background-position: 6px -358px;
}
@@ -202,6 +207,7 @@
    background-position: 6px -382px;
}
#mailboxlist li.mailbox.trash > a:focus,
#mailboxlist li.mailbox.trash.selected > a {
    background-position: 6px -406px;
}
@@ -210,6 +216,7 @@
    background-position: 6px -1924px;
}
#mailboxlist li.mailbox.trash.empty > a:focus,
#mailboxlist li.mailbox.trash.empty.selected > a {
    background-position: 6px -1948px;
}
@@ -218,6 +225,7 @@
    background-position: 6px -1699px;
}
#mailboxlist li.mailbox.archive > a:focus,
#mailboxlist li.mailbox.archive.selected > a {
    background-position: 6px -1723px;
}
@@ -226,6 +234,7 @@
    background-position: 23px -238px;
}
#mailboxlist li.mailbox ul li.drafts > a:focus,
#mailboxlist li.mailbox ul li.drafts.selected > a {
    background-position: 23px -262px;
}
@@ -234,6 +243,7 @@
    background-position: 23px -286px;
}
#mailboxlist li.mailbox ul li.sent > a:focus,
#mailboxlist li.mailbox ul li.sent.selected > a {
    background-position: 23px -310px;
}
@@ -242,6 +252,7 @@
    background-position: 23px -334px;
}
#mailboxlist li.mailbox ul li.junk > a:focus,
#mailboxlist li.mailbox ul li.junk.selected > a {
    background-position: 23px -358px;
}
@@ -250,6 +261,7 @@
    background-position: 23px -382px;
}
#mailboxlist li.mailbox ul li.trash > a:focus,
#mailboxlist li.mailbox ul li.trash.selected > a {
    background-position: 23px -406px;
}
@@ -258,6 +270,7 @@
    background-position: 23px -1924px;
}
#mailboxlist li.mailbox ul li.trash.empty > a:focus,
#mailboxlist li.mailbox ul li.trash.empty.selected > a {
    background-position: 23px -1948px;
}
@@ -266,6 +279,7 @@
    background-position: 23px -1699px;
}
#mailboxlist li.mailbox ul li.archive > a:focus,
#mailboxlist li.mailbox ul li.archive.selected > a {
    background-position: 23px -1723px;
}
@@ -304,6 +318,7 @@
    padding-left: 52px;  /* 36 + 1 x 16 */
    background-position: 22px -95px;  /* 6 + 1 x 16 */
}
#mailboxlist li.mailbox ul li > a:focus,
#mailboxlist li.mailbox ul li.selected > a {
    background-position: 22px -119px;
}
@@ -316,6 +331,7 @@
    padding-left: 68px;  /* 2x */
    background-position: 38px -95px;
}
#mailboxlist li.mailbox ul ul li > a:focus,
#mailboxlist li.mailbox ul ul li.selected > a {
    background-position: 38px -119px;
}
@@ -327,6 +343,7 @@
    padding-left: 84px;  /* 3x */
    background-position: 54px -95px;
}
#mailboxlist li.mailbox ul ul ul li > a:focus,
#mailboxlist li.mailbox ul ul ul li.selected > a {
    background-position: 54px -119px;
}
@@ -338,6 +355,7 @@
    padding-left: 100px;  /* 4x */
    background-position: 70px -95px;
}
#mailboxlist li.mailbox ul ul ul ul li > a:focus,
#mailboxlist li.mailbox ul ul ul ul li.selected > a {
    background-position: 70px -119px;
}
@@ -464,66 +482,66 @@
    z-index: 2;
}
.messagelist thead td:first-child {
.messagelist thead th:first-child {
    border-radius: 4px 0 0 0; /* for Chrome */
}
.messagelist tr td.attachment,
.messagelist tr td.threads,
.messagelist tr td.status,
.messagelist tr td.flag,
.messagelist tr td.priority {
.messagelist tr > .attachment,
.messagelist tr > .threads,
.messagelist tr > .status,
.messagelist tr > .flag,
.messagelist tr > .priority {
    width: 20px;
    padding: 2px 3px;
}
.webkit .messagelist tr td.attachment,
.webkit .messagelist tr td.threads,
.webkit .messagelist tr td.status,
.webkit .messagelist tr td.flag,
.webkit .messagelist tr td.priority {
.webkit .messagelist tr > .attachment,
.webkit .messagelist tr > .threads,
.webkit .messagelist tr > .status,
.webkit .messagelist tr > .flag,
.webkit .messagelist tr > .priority {
    width: 26px;
}
.messagelist tr td.threads {
.messagelist tr > .threads {
    width: 26px;
}
.webkit .messagelist tr td.threads {
.webkit .messagelist tr > .threads {
    width: 30px;
}
.messagelist tr td.threads,
.messagelist tr td.threads + td {
.messagelist tr > .threads,
.messagelist tr > .threads + td {
    border-left: 0;
}
.messagelist tr td.size {
.messagelist tr > .size {
    width: 60px;
    text-align: right;
}
.messagelist thead tr td.size {
.messagelist thead tr th.size {
    text-align: left;
}
.messagelist tr td.fromto,
.messagelist tr td.from,
.messagelist tr td.to,
.messagelist tr td.cc,
.messagelist tr td.replyto {
.messagelist tr > .fromto,
.messagelist tr > .from,
.messagelist tr > .to,
.messagelist tr > .cc,
.messagelist tr > .replyto {
    width: 200px;
}
.messagelist tr td.date {
.messagelist tr > .date {
    width: 155px;
}
.messagelist tr td.folder {
.messagelist tr > .folder {
    width: 135px;
}
.messagelist tr td.hidden {
.messagelist tr > .hidden {
    display: none;
}
@@ -540,19 +558,22 @@
/*    background-color: #fff; */
}
.messagelist tr.flagged th,
.messagelist tr.flagged td,
.messagelist tr.flagged td a {
    color: #f30;
}
.messagelist thead tr td.sortedASC a,
.messagelist thead tr td.sortedDESC a {
.messagelist thead tr th.sortedASC a,
.messagelist thead tr th.sortedDESC a {
    color: #004458;
    text-decoration: underline;
    background: url(images/listicons.png) right -912px no-repeat;
    background-image: url(images/listicons.png);
    background-repeat: no-repeat;
    background-position: right -912px;
}
.messagelist thead tr td.sortedASC a {
.messagelist thead tr th.sortedASC a {
    background-position: right -944px;
}
@@ -574,39 +595,41 @@
    cursor: pointer;
}
.messagelist tr td.flag span,
.messagelist tr td.status span,
.messagelist tr td.attachment span,
.messagelist tr td.priority span {
.messagelist tr > .flag span,
.messagelist tr > .status span,
.messagelist tr > .attachment span,
.messagelist tr > .priority span {
    display: block;
    width: 20px;
    text-indent: -5000px;
    overflow: hidden;
}
.messagelist tr td div.collapsed,
.messagelist tr td div.expanded,
.messagelist tr td.threads div.listmenu,
.messagelist tr td.attachment span.attachment,
.messagelist tr td.attachment span.report,
.messagelist tr td.priority span.priority,
.messagelist tr td.priority span.prio1,
.messagelist tr td.priority span.prio2,
.messagelist tr td.priority span.prio3,
.messagelist tr td.priority span.prio4,
.messagelist tr td.priority span.prio5,
.messagelist tr td.flag span.flagged,
.messagelist tr td.flag span.unflagged,
.messagelist tr td.flag span.unflagged:hover,
.messagelist tr td.status span.status,
.messagelist tr td.status span.msgicon,
.messagelist tr td.status span.deleted,
.messagelist tr td.status span.unread,
.messagelist tr td.status span.unreadchildren,
.messagelist tr td.subject span.msgicon,
.messagelist tr td.subject span.deleted,
.messagelist tr td.subject span.unread,
.messagelist tr td.subject span.replied,
.messagelist tr td.subject span.forwarded,
.messagelist tr td.subject span.unreadchildren {
.messagelist tr > .threads .listmenu,
.messagelist tr > .attachment span.attachment,
.messagelist tr > .attachment span.report,
.messagelist tr > .priority span.priority,
.messagelist tr > .priority span.prio1,
.messagelist tr > .priority span.prio2,
.messagelist tr > .priority span.prio3,
.messagelist tr > .priority span.prio4,
.messagelist tr > .priority span.prio5,
.messagelist tr > .flag span.flagged,
.messagelist tr > .flag span.unflagged,
.messagelist tr > .flag span.unflagged:hover,
.messagelist tr > .status span.status,
.messagelist tr > .status span.msgicon,
.messagelist tr > .status span.deleted,
.messagelist tr > .status span.unread,
.messagelist tr > .status span.unreadchildren,
.messagelist tr > .subject span.msgicon,
.messagelist tr > .subject span.deleted,
.messagelist tr > .subject span.unread,
.messagelist tr > .subject span.replied,
.messagelist tr > .subject span.forwarded,
.messagelist tr > .subject span.unreadchildren {
    display: inline-block;
    vertical-align: middle;
    height: 18px;
@@ -619,7 +642,7 @@
    background-position: 0 -996px;
}
.messagelist thead tr td.attachment span.attachment {
.messagelist thead tr th.attachment span.attachment {
    background-position: -24px -997px;
}
@@ -627,7 +650,7 @@
    background-position: -24px -1116px;
}
.messagelist thead tr td.priority span.priority {
.messagelist thead tr th.priority span.priority {
    background-position: -24px -1845px;
}
@@ -651,15 +674,15 @@
    background-position: 0 -1036px;
}
.messagelist thead tr td.flag span.flagged {
.messagelist thead tr th.flag span.flagged {
    background-position: -22px -1036px;
}
.messagelist tr td.status span.msgicon:hover {
    background-position: -23px -1056px;
.messagelist tr:hover td.status span.msgicon {
    background-position: -23px -1057px;
}
.messagelist tr td.flag span.unflagged:hover {
.messagelist tr:hover td.flag span.unflagged {
    background-position: -23px -1076px;
}
@@ -702,10 +725,10 @@
.messagelist tr td.status span.unread,
.messagelist tr td.subject span.unread,
.messagelist tr td.status span.unread:hover {
    background-position: 0 -1016px;
    background-position: 0 -1017px;
}
.messagelist thead tr td.status span.status {
.messagelist thead tr th.status span.status {
    background-position: -23px -1017px;
}
@@ -719,13 +742,23 @@
    cursor: pointer;
}
.messagelist tr td.threads div.listmenu {
    background-position: 0 -976px;
.messagelist tr th.threads .listmenu {
    background-position: 4px -972px;
    cursor: pointer;
    width: 26px;
    width: 24px;
    height: 21px;
    overflow: hidden;
    text-indent: -5000px;
    margin: -3px -5px -2px -6px;
    padding: 3px  5px  2px  6px;
}
.messagelist thead tr td.subject,
.messagelist tr th.threads .listmenu:focus {
    background-color: rgba(73,180,210,0.7);
    outline: none;
}
.messagelist thead tr th.subject,
.messagelist tbody tr td.subject {
    width: 99%;
    white-space: nowrap;
@@ -907,6 +940,16 @@
    background: linear-gradient(left, #fbfbfb 0, #e9e9e9 100%);
    border-right: 1px solid #dfdfdf;
    border-radius: 3px 0 0 0; /* for Opera */
}
.moreheaderstoggle:focus {
    background: #f2f2f2;
    background: -moz-linear-gradient(left, #66bcd9 0, #49b3d2 100%);
    background: -webkit-gradient(linear, left top, right top, color-stop(0,#66bcd9), color-stop(100%,#49b3d2));
    background: -o-linear-gradient(left, #66bcd9 0, #49b3d2 100%);
    background: -ms-linear-gradient(left, #66bcd9 0, #49b3d2 100%);
    background: linear-gradient(left, #66bcd9 0, #49b3d2 100%);
    border-right-color: #149cc5;
}
.moreheaderstoggle .iconlink {
@@ -1303,11 +1346,17 @@
    margin-left: 0.5em;
}
#compose-contacts li a, #contacts-table td {
    background: url(images/listicons.png) -100px 0 no-repeat;
#compose-contacts li a,
#contacts-table td {
    background-image: url(images/listicons.png);
    background-position: -100px 0;
    background-repeat: no-repeat;
    overflow: hidden;
    padding-left: 36px;
    text-overflow: ellipsis;
}
#compose-contacts li a {
    padding-left: 36px;
}
#contacts-table td.contactgroup a {
@@ -1331,6 +1380,7 @@
    background-position: 6px -766px;
}
#compose-contacts li.addressbook a:focus,
#compose-contacts li.addressbook.selected a {
    background-position: 6px -791px;
}
@@ -1339,20 +1389,36 @@
    background-position: 6px -1555px;
}
#contacts-table.focus tr.focused td.contactgroup {
    background-position: 4px -1555px;
}
#contacts-table tr.unfocused td.contactgroup,
#contacts-table tr.selected td.contactgroup {
    background-position: 6px -1579px;
}
#contacts-table.focus tr.selected.focused td.contactgroup {
    background-position: 4px -1579px;
}
#contacts-table td.contact {
    background-position: 6px -1603px;
}
#contacts-table.focus tr.focused td.contact {
    background-position: 4px -1603px;
}
#contacts-table tr.unfocused td.contact,
#contacts-table tr.selected td.contact {
    background-position: 6px -1627px;
}
#contacts-table.focus tr.selected.focused td.contact {
    background-position: 4px -1627px;
}
#compose-content {
    position: absolute;
    top: 0;
skins/larry/settings.css
@@ -70,7 +70,7 @@
    width: 20px;
    height: 18px;
    background: url('images/listicons.png') 0 -1157px no-repeat;
    text-indent: 1000px;
    text-indent: -5000px;
    overflow: hidden;
}
@@ -78,9 +78,10 @@
    background-position: -24px -1137px;
}
#sections-table tbody td.section,
#settings-sections span.listitem a,
#settings-sections span.tablink a {
#sections-table tbody td,
#sections-table .listitem span,
#settings-sections .listitem a,
#settings-sections .tablink a {
    padding-left: 36px;
    background-image: url(images/listicons.png);
    background-position: -100px 0;
@@ -88,120 +89,120 @@
}
/* note: support span.tablink because this is used by plugins */
#settings-sections span.listitem a,
#settings-sections span.tablink a {
#settings-sections .listitem a,
#settings-sections .tablink a {
    background-position: 6px -862px;
}
#settings-sections span.selected a,
#settings-sections span.tablink.selected a {
#settings-sections .selected a,
#settings-sections .tablink.selected a {
    background-position: 6px -887px;
}
#settings-sections span.preferences a {
#settings-sections .preferences a {
    background-position: 6px -431px;
}
#settings-sections span.preferences.selected a {
#settings-sections .preferences.selected a {
    background-position: 6px -455px;
}
#settings-sections span.folders a,
#sections-table #rcmrowfolders td.section {
#settings-sections .folders a,
#sections-table #rcmrowfolders .section {
    background-position: 6px 2px;
}
#settings-sections span.folders.selected a,
#sections-table #rcmrowfolders.selected td.section {
#settings-sections .folders.selected a,
#sections-table #rcmrowfolders.selected .section {
    background-position: 6px -22px;
}
#settings-sections span.identities a {
#settings-sections .identities a {
    background-position: 6px -478px;
}
#settings-sections span.identities.selected a {
#settings-sections .identities.selected a {
    background-position: 6px -502px;
}
#settings-sections span.filter a {
#settings-sections .filter a {
    background-position: 6px -1746px;
}
#settings-sections span.filter.selected a {
#settings-sections .filter.selected a {
    background-position: 6px -1770px;
}
#settings-sections span.password a {
#settings-sections .password a {
    background-position: 6px -1795px;
}
#settings-sections span.password.selected a {
#settings-sections .password.selected a {
    background-position: 6px -1819px;
}
#settings-sections span.responses a {
#settings-sections .responses a {
    background-position: 6px -1972px;
}
#settings-sections span.responses.selected a {
#settings-sections .responses.selected a {
    background-position: 6px -1996px;
}
#sections-table #rcmrowgeneral td.section {
    background-position: 6px -573px;
#sections-table #rcmrowgeneral .section {
    background-position: 4px -573px;
}
#sections-table #rcmrowgeneral.selected td.section {
    background-position: 6px -598px;
#sections-table #rcmrowgeneral.selected .section {
    background-position: 4px -598px;
}
#sections-table #rcmrowmailbox td.section {
    background-position: 6px -621px;
#sections-table #rcmrowmailbox .section {
    background-position: 4px -621px;
}
#sections-table #rcmrowmailbox.selected td.section {
    background-position: 6px -646px;
#sections-table #rcmrowmailbox.selected .section {
    background-position: 4px -646px;
}
#sections-table #rcmrowcompose td.section {
    background-position: 6px -670px;
#sections-table #rcmrowcompose .section {
    background-position: 4px -670px;
}
#sections-table #rcmrowcompose.selected td.section {
    background-position: 6px -695px;
#sections-table #rcmrowcompose.selected .section {
    background-position: 4px -695px;
}
#sections-table #rcmrowmailview td.section {
    background-position: 6px -718px;
#sections-table #rcmrowmailview .section {
    background-position: 4px -718px;
}
#sections-table #rcmrowmailview.selected td.section {
    background-position: 6px -742px;
#sections-table #rcmrowmailview.selected .section {
    background-position: 4px -742px;
}
#sections-table #rcmrowaddressbook td.section {
    background-position: 6px -766px;
#sections-table #rcmrowaddressbook .section {
    background-position: 4px -766px;
}
#sections-table #rcmrowaddressbook.selected td.section {
    background-position: 6px -791px;
#sections-table #rcmrowaddressbook.selected .section {
    background-position: 4px -791px;
}
#sections-table #rcmrowserver td.section {
    background-position: 6px -814px;
#sections-table #rcmrowserver .section {
    background-position: 4px -814px;
}
#sections-table #rcmrowserver.selected td.section {
    background-position: 6px -838px;
#sections-table #rcmrowserver.selected .section {
    background-position: 4px -838px;
}
#sections-table #rcmrowcalendar td.section {
    background-position: 6px -526px;
#sections-table #rcmrowcalendar .section {
    background-position: 4px -526px;
}
#sections-table #rcmrowcalendar.selected td.section {
    background-position: 6px -550px;
#sections-table #rcmrowcalendar.selected .section {
    background-position: 4px -550px;
}
#folderslist,
skins/larry/styles.css
@@ -35,6 +35,10 @@
  border: 0;
}
.voice {
    display: none;
}
input[type="text"],
input[type="password"],
textarea {
@@ -310,6 +314,16 @@
    box-shadow: inset 0 1px 2px 0 #555;
    border-right-color: #555;
    border-left-color: #555;
}
.buttongroup a.button:focus,
.buttongroup a.button.selected:focus {
    background: #f2f2f2;
    background: -moz-linear-gradient(top, #49b3d2 0, #66bcd9 100%);
    background: -webkit-gradient(linear, left top, left bottom, color-stop(0,#49b3d2), color-stop(100%,#66bcd9));
    background: -o-linear-gradient(top, #49b3d2 0, #66bcd9 100%);
    background: -ms-linear-gradient(top, #49b3d2 0, #66bcd9 100%);
    background: linear-gradient(top, #49b3d2 0, #66bcd9 100%);
}
.pagenav a.button {
@@ -950,6 +964,13 @@
    background: url(images/buttons.png) -1000px 0 no-repeat;
}
#taskbar a:focus {
    color: #fff;
    text-shadow: 0px 1px 1px #666;
    background-color: rgba(73,180,210,0.7);
    outline: none;
}
#taskbar a.button-selected {
    color: #3cf;
    background-color: #2c2c2c;
@@ -1115,6 +1136,7 @@
}
.boxtitle,
.uibox .listing thead th,
.uibox .listing thead td {
    font-size: 12px;
    font-weight: bold;
@@ -1126,7 +1148,14 @@
    white-space: nowrap;
}
.uibox .listing thead th,
.uibox .listing thead td {
    padding-bottom: 8px;
    height: auto;
}
.uibox .boxtitle,
.uibox .listing thead th,
.uibox .listing thead td {
    background: #b0ccd7;
    color: #004458;
@@ -1145,6 +1174,7 @@
}
.listbox .listitem a,
.listbox .listitem span,
.listbox .tablink a,
.listing tbody td,
.listing li a {
@@ -1162,17 +1192,40 @@
    display: table-cell;
    height: auto;
    min-height: 14px;
    outline: none;
}
.listing tbody td a {
    color: #376572;
    text-shadow: 0px 1px 1px #fff;
    text-decoration: none;
}
.webkit .listing tbody td {
    height: 14px;
}
/* This padding-left minus the focused padding left should be half of the focused border-left */
.listing thead tr td:first-child,
.listing tbody tr td:first-child {
    border-left: 2px solid transparent;
    padding-left: 6px;
}
.listing.iconized thead tr td:first-child,
.listing.iconized tbody tr td:first-child {
    padding-left: 34px;
}
/* because of border-collapse, we make the left border twice what we want it to be - half will be hidden to the left */
.listing.focus tbody tr.focused > td:first-child {
    border-left: 2px solid #739da8;
}
.listbox .listitem.selected,
.listbox .tablink.selected,
.listbox .listitem.selected > a,
.listbox .tablink.selected > a,
.listing tbody tr.unfocused td,
.listing tbody tr.selected td,
.listing li.selected,
.listing li.selected > a {
@@ -1237,6 +1290,16 @@
    padding-left: 20px;
    overflow: hidden;
    text-overflow: ellipsis;
}
ul.treelist li a:focus,
ul.listing .listitem a:focus,
ul.listing .listitem span:focus,
ul.listing.focus .listitem.focused span {
    color: #fff !important;
    background-color: rgba(73,180,210,0.6);
    text-shadow: 0px 1px 1px #666;
    outline: none;
}
ul.treelist ul li a {
@@ -1319,6 +1382,13 @@
    margin-top: 1px;
}
.boxfooter a.listbutton:focus {
    color: #fff;
    background-color: rgba(73,180,210,0.6);
    text-shadow: 0px 1px 1px #666;
    outline: none;
}
.uibox .boxfooter .listbutton:first-child {
    border-radius: 0 0 0 4px;
}
@@ -1328,7 +1398,9 @@
    width: 48px;
    height: 35px;
    text-indent: -5000px;
    background: url(images/buttons.png) -1000px 0 no-repeat;
    background-image: url(images/buttons.png);
    background-position: -1000px 0;
    background-repeat: no-repeat;
}
.boxfooter .listbutton.add .inner {
@@ -1442,6 +1514,7 @@
    border: 0;
}
.records-table thead th,
.records-table thead td {
    color: #69939e;
    font-size: 11px;
@@ -1456,13 +1529,17 @@
    padding: 8px 7px;
    overflow: hidden;
    text-overflow: ellipsis;
    text-align: left;
}
.records-table.sortheader thead th,
.records-table.sortheader thead td {
    padding: 0;
}
.records-table thead th a,
.records-table thead td a,
.records-table thead th span,
.records-table thead td span {
    display: block;
    padding: 7px 7px;
@@ -1470,6 +1547,14 @@
    text-decoration: none;
    overflow: hidden;
    text-overflow: ellipsis;
}
.records-table thead th a:focus,
.records-table thead td a:focus {
    color: #fff;
    background-color: rgba(73,180,210,0.7);
    text-shadow: 0px 1px 1px #666;
    outline: none;
}
.records-table tbody td {
@@ -1481,27 +1566,28 @@
    overflow: hidden;
    text-overflow: ellipsis;
    background-color: #fff;
    outline: none;
}
/* This padding-left minus the focused padding left should be half of the focused border-left */
.records-table thead tr th:first-child,
.records-table thead tr td:first-child,
.records-table tbody tr td:first-child {
    border-left: 0;
    padding-left: 6px;
}
/* because of border-collapse, we make the left border twice what we want it to be - half will be hidden to the left */
.records-table tbody tr.focused > td:first-child {
    border-left: 2px solid #b0ccd7;
    border-left: 2px solid transparent;
    padding-left: 4px;
}
.records-table tbody tr.selected.focused > td:first-child {
    border-left-color: #49b3d2;
/* because of border-collapse, we make the left border twice what we want it to be - half will be hidden to the left */
.records-table.focus tbody tr.focused > td:first-child {
    border-left: 2px solid #49b3d2;
}
.records-table tr.selected td {
    color: #fff !important;
    background-color: #4db0d2 !important;
}
.records-table.focus tr.selected td {
    background: #019bc6;
    background: -moz-linear-gradient(top, #019bc6 0%, #017cb4 100%);
    background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#019bc6), color-stop(100%,#017cb4));
@@ -1512,16 +1598,6 @@
.records-table tr.selected td a,
.records-table tr.selected td span {
    color: #fff !important;
}
.records-table tr.unfocused td {
    color: #fff !important;
    background-color: #4db0d2 !important;
}
.records-table tr.unfocused td a,
.records-table tr.unfocused td span {
    color: #fff !important;
}
@@ -1921,6 +1997,14 @@
    border-radius: 0;
}
.dropbutton .dropbuttontip:focus,
.toolbar a.button:focus {
    color: #fff;
    text-shadow: 0px 1px 1px #666;
    background-color: rgba(30,150,192, 0.5);
    border-radius: 3px;
}
.toolbar a.button.disabled {
    opacity: 0.4;
    filter: alpha(opacity=40);
@@ -1936,12 +2020,16 @@
    position: absolute;
    right: 0;
    top: 0;
    height: 42px;
    height: 41px;
    width: 18px;
    overflow: hidden;
    text-indent: -5000px;
    background: url(images/buttons.png) 0 -1255px no-repeat;
    cursor: pointer;
    outline: none;
}
.dropbutton .dropbuttontip:focus,
.dropbutton .dropbuttontip:hover {
    background-position: -26px -1255px;
}
@@ -2132,6 +2220,19 @@
}
a.menuselector:focus,
a.menuselector.focus,
a.iconbutton:focus,
.pagenav a.button:focus {
    border-color: #4fadd5;
    -webkit-box-shadow: 0 0 4px 2px rgba(71,135,177, 0.8);
       -moz-box-shadow: 0 0 4px 2px rgba(71,135,177, 0.8);
         -o-box-shadow: 0 0 4px 2px rgba(71,135,177, 0.8);
            box-shadow: 0 0 4px 2px rgba(71,135,177, 0.8);
    outline: none;
}
/*** quota indicator ***/
#quotadisplay {
@@ -2224,6 +2325,7 @@
.googie_list td.googie_list_onhover,
ul.toolbarmenu li a.active:hover,
ul.toolbarmenu li a.active:focus,
#rcmKSearchpane ul li.selected,
select.decorated option:hover,
select.decorated option[selected='selected'] {
@@ -2233,6 +2335,7 @@
    background: -o-linear-gradient(top, #00aad6 0%, #008fc9 100%);
    background: -ms-linear-gradient(top, #00aad6 0%, #008fc9 100%);
    background: linear-gradient(top, #00aad6 0%, #008fc9 100%);
    outline: none;
}
ul.toolbarmenu.iconized li a,
@@ -2620,6 +2723,7 @@
    overflow: hidden;
    text-overflow: ellipsis;
    line-height: 20px;
    outline: none;
}
.attachmentslist li a.drop {
@@ -2631,6 +2735,15 @@
    right: 0;
    top: 0;
    padding: 0;
    overflow: hidden;
    text-indent: -5000px;
    outline: none;
}
.attachmentslist li a:focus,
.attachmentslist li a.drop:focus {
    background-color: rgba(30,150,192, 0.5);
    border-radius: 2px;
}
#compose-attachments ul li {
@@ -2665,26 +2778,22 @@
/*** fieldset tabs ***/
.tabsbar {
    margin-bottom: 12px;
    padding-top: 15px;
    height: 27px;
    white-space: nowrap;
.tabbed.ui-tabs {
    padding: 0;
    border: 0 !important;
    background: none;
}
.boxcontent.tabbed.ui-tabs {
    padding: 10px;
}
.ui-tabs .tabsbar.ui-tabs-nav {
    margin-bottom: 10px;
}
.ui-dialog-content .tabsbar {
    margin-bottom: 0;
}
.tabsbar .tablink {
    padding: 15px 1px 15px 0;
    background: #f8f8f8;
    background: -moz-linear-gradient(top, #f8f8f8 0%, #d3d3d3 50%, #f8f8f8 100%);
    background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#f8f8f8), color-stop(50%,#d3d3d3), color-stop(100%,#f8f8f8));
    background: -webkit-linear-gradient(top, #f8f8f8 0%, #d3d3d3 50%, #f8f8f8 100%);
    background: -o-linear-gradient(top, #f8f8f8 0%, #d3d3d3 50%, #f8f8f8 100%);
    background: -ms-linear-gradient(top, #f8f8f8 0%, #d3d3d3 50%, #f8f8f8 100%);
    background: linear-gradient(top, #f8f8f8 0%, #d3d3d3 50%, #f8f8f8 100%);
}
.tabsbar .tablink:last-child {
@@ -2695,30 +2804,15 @@
    border-right: 0;
}
.tabsbar .tablink a {
    padding: 15px;
    color: #999;
    font-size: 12px;
    font-weight: bold;
    text-decoration: none;
.ui-tabs .ui-tabs-nav li.tablink a {
    background: #fff;
    border-right: 1px solid #fafafa;
}
.tabsbar .tablink.selected a {
    color: #004458;
    background: #f6f6f6;
    background: -moz-linear-gradient(top, #fff 40%, #efefef 100%);
    background: -webkit-gradient(linear, left top, left bottom, color-stop(40%,#fff), color-stop(100%,#efefef));
    background: -o-linear-gradient(top, #fff 40%, #efefef 100%);
    background: -ms-linear-gradient(top, #fff 40%, #efefef 100%);
    background: linear-gradient(top, #fff 40%, #efefef 100%);
}
fieldset.tab {
.ui-tabs fieldset.ui-tabs-panel {
    border: 0;
    padding: 0;
    margin-left: 0;
    background: none;
}
#image-selector-form.droptarget {
skins/larry/templates/addressbook.html
@@ -10,25 +10,50 @@
<div id="mainscreen">
<h1 class="voice"><roundcube:label name="addressbook" /></h1>
<!-- toolbar -->
<div id="addressbooktoolbar" class="toolbar">
<h2 id="aria-label-toolbar" class="voice"><roundcube:label name="arialabeltoolbar" /></h2>
<div id="addressbooktoolbar" class="toolbar" role="toolbar" aria-labelledby="aria-label-toolbar">
    <roundcube:button command="import" type="link" class="button import disabled" classAct="button import" classSel="button import pressed" label="import" title="importcontacts" />
    <span class="dropbutton">
        <roundcube:button command="export" type="link" class="button export disabled" classAct="button export" classSel="button export pressed" label="export" title="exportvcards" />
        <span class="dropbuttontip" id="exportmenulink" onclick="UI.show_popup('exportmenu');return false"></span>
        <a href="#export" class="dropbuttontip" id="exportmenulink" onclick="return UI.toggle_popup('exportmenu',event)" aria-haspopup="true" aria-expanded="false" aria-owns="exportmenu-menu" tabindex="0"><roundcube:label name="arialabelcontactexportoptions" /></a>
    </span>
    <span class="spacer"></span>
    <roundcube:button command="compose" type="link" class="button compose disabled" classAct="button compose" classSel="button compose pressed" label="compose" title="writenewmessage" />
    <roundcube:button command="advanced-search" type="link" class="button search disabled" classAct="button search" classSel="button search pressed" label="advanced" title="advsearch" />
    <roundcube:container name="toolbar" id="addressbooktoolbar" />
    <div id="exportmenu" class="popupmenu" aria-hidden="true">
        <h3 id="aria-label-exportmenu" class="voice"><roundcube:label name="arialabelcontactexportoptions" /></h3>
        <ul id="exportmenu-menu" class="toolbarmenu" role="menu" aria-labelledby="aria-label-exportmenu">
            <li role="menuitem"><roundcube:button command="export" label="exportall" prop="sub" class="exportalllink" classAct="exportalllink active" /></li>
            <li role="menuitem"><roundcube:button command="export-selected" label="exportsel" prop="sub" class="exportsellink" classAct="exportsellink active" /></li>
        </ul>
    </div>
</div>
<!-- search box -->
<div id="quicksearchbar" class="searchbox">
<div id="quicksearchbar" class="searchbox" role="search" aria-labelledby="aria-label-searchform">
<h2 id="aria-label-searchform" class="voice"><roundcube:label name="arialabelcontactsearchform" /></h2>
<label for="quicksearchbox" class="voice"><roundcube:label name="arialabelquicksearchbox" /></label>
<roundcube:object name="searchform" id="quicksearchbox" />
<roundcube:button name="searchmenulink" id="searchmenulink" class="iconbutton searchoptions" onclick="UI.show_popup('searchmenu');return false" title="searchmod" content=" " />
<roundcube:button command="reset-search" id="searchreset" class="iconbutton reset" title="resetsearch" content=" " />
<roundcube:button command="menu-open" prop="searchmenu" id="searchmenulink" class="iconbutton searchoptions" title="searchmod" label="options" aria-haspopup="true" aria-expanded="false" aria-owns="searchmenu-menu" />
<roundcube:button command="reset-search" id="searchreset" class="iconbutton reset" title="resetsearch" label="resetsearch" />
<div id="searchmenu" class="popupmenu" data-editable="true">
    <h3 id="aria-label-searchmenu" class="voice"><roundcube:label name="searchmod" /></h3>
    <ul class="toolbarmenu" id="searchmenu-menu" role="menu" aria-labelledby="aria-label-searchmenu">
        <li role="menuitem"><label><input type="checkbox" name="s_mods[]" value="name" id="s_mod_name" onclick="UI.set_searchmod(this)" /> <span><roundcube:label name="name" /></span></label></li>
        <li role="menuitem"><label><input type="checkbox" name="s_mods[]" value="firstname" id="s_mod_firstname" onclick="UI.set_searchmod(this)" /> <span><roundcube:label name="firstname" /></span></label></li>
        <li role="menuitem"><label><input type="checkbox" name="s_mods[]" value="surname" id="s_mod_surname" onclick="UI.set_searchmod(this)" /> <span><roundcube:label name="surname" /></span></label></li>
        <li role="menuitem"><label><input type="checkbox" name="s_mods[]" value="email" id="s_mod_email" onclick="UI.set_searchmod(this)" /> <span><roundcube:label name="email" /></span></label></li>
        <li role="menuitem"><label><input type="checkbox" name="s_mods[]" value="*" id="s_mod_all" onclick="UI.set_searchmod(this)" /> <span><roundcube:label name="allfields" /></span></label></li>
    </ul>
</div>
</div>
<div id="mainscreencontent">
@@ -36,42 +61,64 @@
<div id="addressview-left">
<!-- sources/groups list -->
<div id="directorylistbox" class="uibox listbox">
<div id="directorylistbox" class="uibox listbox" role="navigation" aria-labelledby="directorylist-header">
<h2 id="directorylist-header" class="boxtitle"><roundcube:label name="groups" /></h2>
<div id="directorylist-content" class="scroller withfooter">
    <roundcube:object name="directorylist" id="directorylist" class="treelist listing iconized" />
</div>
<div id="directorylist-footer" class="boxfooter">
    <roundcube:button command="group-create" type="link" title="newcontactgroup" class="listbutton add disabled" classAct="listbutton add" innerClass="inner" content="+" /><roundcube:button name="groupoptions" id="groupoptionslink" type="link" title="moreactions" class="listbutton groupactions" onclick="UI.show_popup('groupoptions');return false" innerClass="inner" content="&#9881;" />
    <roundcube:button command="group-create" type="link" title="newcontactgroup" class="listbutton add disabled" classAct="listbutton add" innerClass="inner" label="newcontactgroup" /><roundcube:button name="groupoptions" id="groupoptionslink" type="link" title="moreactions" class="listbutton groupactions" onclick="return UI.toggle_popup('groupoptions',event)" innerClass="inner" label="arialabelabookgroupoptions" aria-haspopup="true" aria-expanded="false" aria-owns="groupoptionsmenu" />
</div>
</div>
<div id="groupoptions" class="popupmenu" aria-hidden="true">
    <h3 id="aria-label-groupoptions" class="voice"><roundcube:label name="arialabelabookgroupoptions" /></h3>
    <ul id="groupoptionsmenu" class="toolbarmenu" role="menu" aria-labelledby="aria-label-groupoptions">
        <li role="menuitem"><roundcube:button command="group-rename" label="grouprename" classAct="active" /></li>
        <li role="menuitem"><roundcube:button command="group-delete" label="groupdelete" classAct="active" /></li>
        <li role="menuitem"><roundcube:button command="search-create" label="searchsave" classAct="active" /></li>
        <li role="menuitem"><roundcube:button command="search-delete" label="searchdelete" classAct="active" /></li>
        <roundcube:container name="groupoptions" id="groupoptionsmenu" />
    </ul>
</div>
</div><!-- end addressview-left -->
<div id="addressview-right">
<div id="addressview-right" role="main" aria-labelledby="aria-label-contactslist">
<!-- contacts list -->
<div id="addresslist" class="uibox listbox">
<roundcube:object name="addresslisttitle" label="contacts" tag="h2" class="boxtitle" />
<roundcube:object name="addresslisttitle" label="contacts" tag="h2" class="boxtitle" id="aria-label-contactslist" />
<div class="scroller withfooter">
<roundcube:object name="addresslist" id="contacts-table" class="listing" noheader="true" />
</div>
<div class="boxfooter">
    <roundcube:button command="add" type="link" title="newcontact" class="listbutton add disabled" classAct="listbutton add" innerClass="inner" content="+" /><roundcube:button command="delete" type="link" title="deletecontact" class="listbutton delete disabled" classAct="listbutton delete" innerClass="inner" content="x" /><roundcube:button command="group-remove-selected" type="link" title="groupremoveselected" class="listbutton removegroup disabled" classAct="listbutton removegroup" innerClass="inner" content="-" />
    <roundcube:object name="recordsCountDisplay" class="countdisplay" label="fromtoshort" />
<roundcube:object name="addresslist" id="contacts-table" class="listing iconized" noheader="true" role="listbox" />
</div>
<div class="boxpagenav">
    <roundcube:button command="firstpage" type="link" class="icon firstpage disabled" classAct="icon firstpage" title="firstpage" content="|&amp;lt;" />
    <roundcube:button command="previouspage" type="link" class="icon prevpage disabled" classAct="icon prevpage" title="previouspage" content="&amp;lt;" />
    <roundcube:button command="nextpage" type="link" class="icon nextpage disabled" classAct="icon nextpage" title="nextpage" content="&amp;gt;" />
    <roundcube:button command="lastpage" type="link" class="icon lastpage disabled" classAct="icon lastpage" title="lastpage" content="&amp;gt;|" />
    <roundcube:button command="firstpage" type="link" class="icon firstpage disabled" classAct="icon firstpage" title="firstpage" label="first" />
    <roundcube:button command="previouspage" type="link" class="icon prevpage disabled" classAct="icon prevpage" title="previouspage" label="previous" />
    <roundcube:button command="nextpage" type="link" class="icon nextpage disabled" classAct="icon nextpage" title="nextpage" label="next" />
    <roundcube:button command="lastpage" type="link" class="icon lastpage disabled" classAct="icon lastpage" title="lastpage" label="last" />
</div>
<div class="boxfooter">
    <roundcube:button command="add" type="link" title="newcontact" class="listbutton add disabled" classAct="listbutton add" innerClass="inner" label="newcontact" /><roundcube:button command="delete" type="link" title="deletecontact" class="listbutton delete disabled" classAct="listbutton delete" innerClass="inner" label="deletecontact" /><roundcube:button command="group-remove-selected" type="link" title="groupremoveselected" class="listbutton removegroup disabled" classAct="listbutton removegroup" innerClass="inner" label="groupremoveselected" />
    <span class="countdisplay" aria-live="polite" aria-relevant="text">
        <span class="voice"><roundcube:label name="contacts" /></span>
        <roundcube:object name="recordsCountDisplay" label="fromtoshort" />
    </span>
</div>
</div>
<div class="voice" role="note">
<h3><roundcube:label name="helplistnavigation" /></h3>
<pre>
<roundcube:label name="helplistkeyboardnavigation" />
<roundcube:label name="helplistkeyboardnavcontacts" />
</pre>
</div>
<div id="contacts-box" class="uibox">
    <div class="iframebox">
        <roundcube:object name="addressframe" id="contact-frame" style="width:100%; height:100%" frameborder="0" src="/watermark.html" />
        <roundcube:object name="addressframe" id="contact-frame" style="width:100%; height:100%" frameborder="0" src="/watermark.html" title="contactproperties" />
    </div>
</div>
@@ -81,37 +128,10 @@
</div><!-- end mainscreen -->
<div id="exportmenu" class="popupmenu">
    <ul class="toolbarmenu">
        <li><roundcube:button command="export" label="exportall" prop="sub" class="exportalllink" classAct="exportalllink active" /></li>
        <li><roundcube:button command="export-selected" label="exportsel" prop="sub" class="exportsellink" classAct="exportsellink active" /></li>
    </ul>
</div>
<div id="searchmenu" class="popupmenu">
    <ul class="toolbarmenu">
        <li><label><input type="checkbox" name="s_mods[]" value="name" id="s_mod_name" onclick="UI.set_searchmod(this)" /> <span><roundcube:label name="name" /></span></label></li>
        <li><label><input type="checkbox" name="s_mods[]" value="firstname" id="s_mod_firstname" onclick="UI.set_searchmod(this)" /> <span><roundcube:label name="firstname" /></span></label></li>
        <li><label><input type="checkbox" name="s_mods[]" value="surname" id="s_mod_surname" onclick="UI.set_searchmod(this)" /> <span><roundcube:label name="surname" /></span></label></li>
        <li><label><input type="checkbox" name="s_mods[]" value="email" id="s_mod_email" onclick="UI.set_searchmod(this)" /> <span><roundcube:label name="email" /></span></label></li>
        <li><label><input type="checkbox" name="s_mods[]" value="*" id="s_mod_all" onclick="UI.set_searchmod(this)" /> <span><roundcube:label name="allfields" /></span></label></li>
    </ul>
</div>
<div id="groupoptions" class="popupmenu">
    <ul id="groupoptionsmenu" class="toolbarmenu">
        <li><roundcube:button command="group-rename" label="grouprename" classAct="active" /></li>
        <li><roundcube:button command="group-delete" label="groupdelete" classAct="active" /></li>
        <li><roundcube:button command="search-create" label="searchsave" classAct="active" /></li>
        <li><roundcube:button command="search-delete" label="searchdelete" classAct="active" /></li>
        <roundcube:container name="groupoptions" id="groupoptionsmenu" />
    </ul>
</div>
<div id="dragcontactmenu" class="popupmenu">
    <ul class="toolbarmenu">
        <li><roundcube:button command="move" onclick="return rcmail.drag_menu_action('move')" label="move" classAct="active" /></li>
        <li><roundcube:button command="copy" onclick="return rcmail.drag_menu_action('copy')" label="copy" classAct="active" /></li>
<div id="dragcontactmenu" class="popupmenu" aria-hidden="true">
    <ul class="toolbarmenu" role="menu">
        <li role="menuitem"><roundcube:button command="move" onclick="return rcmail.drag_menu_action('move')" label="move" classAct="active" /></li>
        <li role="menuitem"><roundcube:button command="copy" onclick="return rcmail.drag_menu_action('copy')" label="copy" classAct="active" /></li>
    </ul>
</div>
skins/larry/templates/compose.html
@@ -13,26 +13,27 @@
<div id="mainscreen">
<h1 class="voice"><roundcube:object name="pagetitle" /></h1>
<!-- toolbar -->
<div id="messagetoolbar" class="fullwidth">
<div id="mailtoolbar" class="toolbar">
    <roundcube:button command="list" type="link" class="button back disabled" classAct="button back" classSel="button back pressed" label="cancel" condition="!env:extwin" />
    <roundcube:button command="close" type="link" class="button close disabled" classAct="button close" classSel="button close pressed" label="cancel" condition="env:extwin" />
<h2 id="aria-label-toolbar" class="voice"><roundcube:label name="arialabeltoolbar" /></h2>
<div id="messagetoolbar" class="toolbar fullwidth" role="toolbar" aria-labelledby="aria-label-toolbar">
    <roundcube:button command="list" type="link" class="button back disabled" classAct="button back" label="cancel" condition="!env:extwin" tabindex="2" />
    <roundcube:button command="close" type="link" class="button close disabled" classAct="button close" label="cancel" condition="env:extwin" tabindex="2" />
    <span class="spacer"></span>
    <roundcube:button command="send" type="link" class="button send" classAct="button send" classSel="button send pressed" label="send" title="sendmessage" />
    <roundcube:button command="savedraft" type="link" class="button savedraft" classAct="button savedraft" classSel="button savedraft pressed" label="save" title="savemessage" />
    <roundcube:button command="send" type="link" class="button send disabled" classAct="button send" label="send" title="sendmessage" tabindex="2" />
    <roundcube:button command="savedraft" type="link" class="button savedraft disabled" classAct="button savedraft" label="save" title="savemessage" tabindex="2" />
    <span class="spacer"></span>
    <roundcube:if condition="config:enable_spellcheck" />
    <span class="dropbutton">
        <roundcube:button command="spellcheck" type="link" class="button spellcheck disabled" classAct="button spellcheck" classSel="button spellcheck pressed" label="spellcheck" title="checkspelling" />
        <span class="dropbuttontip" id="spellmenulink" onclick="UI.show_popup('spellmenu');return false"></span>
        <roundcube:button command="spellcheck" type="link" class="button spellcheck disabled" classAct="button spellcheck" classSel="button spellcheck pressed" label="spellcheck" title="checkspelling" tabindex="2" />
        <a href="#languages" class="dropbuttontip" id="spellmenulink" onclick="UI.toggle_popup('spellmenu',event);return false" aria-haspopup="true" aria-expanded="false"tabindex="2">Select Spell Language</a>
    </span>
    <roundcube:endif />
    <roundcube:button name="addattachment" type="link" class="button attach" classAct="button attach" classSel="button attach pressed" label="attach" title="addattachment" onclick="UI.show_uploadform();return false" />
    <roundcube:button command="insert-sig" type="link" class="button insertsig disabled" classAct="button insertsig" classSel="button insertsig pressed" label="signature" title="insertsignature" />
    <a href="#responses" class="button responses" label="responses" title="<roundcube:label name='insertresponse' />" id="responsesmenulink" unselectable="on" onmousedown="return false" onclick="UI.show_popup('responsesmenu');return false"><roundcube:label name="responses" /></a>
    <roundcube:button name="addattachment" type="link" class="button attach" label="attach" title="addattachment" onclick="UI.show_uploadform(event);return false" aria-haspopup="true" aria-expanded="false"tabindex="2" />
    <roundcube:button command="insert-sig" type="link" class="button insertsig disabled" classAct="button insertsig" label="signature" title="insertsignature" tabindex="2" />
    <a href="#responses" class="button responses" label="responses" title="<roundcube:label name='insertresponse' />" id="responsesmenulink" unselectable="on" onmousedown="return false" onclick="UI.toggle_popup('responsesmenu',event);return false" tabindex="2" aria-haspopup="true" aria-expanded="false" aria-owns="textresponsesmenu"><roundcube:label name="responses" /></a>
    <roundcube:container name="toolbar" id="compose-toolbar" />
</div>
</div>
<div id="mainscreencontent">
@@ -40,39 +41,43 @@
<div id="composeview-left">
<!-- inline address book -->
<div id="compose-contacts" class="uibox listbox">
<h2 class="boxtitle"><roundcube:label name="contacts" /></h2>
    <div class="listsearchbox">
<div id="compose-contacts" class="uibox listbox" role="region" aria-labelledby="aria-label-composecontacts">
<h2 id="aria-label-composecontacts" class="boxtitle"><roundcube:label name="contacts" /></h2>
    <div class="listsearchbox" role="search" aria-labelledby="aria-label-composequicksearch">
        <h3 id="aria-label-composequicksearch" class="voice"><roundcube:label name="arialabelcontactquicksearch" /></h3>
        <div class="searchbox">
            <label for="contactsearchbox" class="voice"><roundcube:label name="arialabelcontactsearchbox" /></label>
            <roundcube:object name="searchform" id="contactsearchbox" />
            <a id="searchmenulink" class="iconbutton searchicon"> </a>
            <roundcube:button command="reset-search" class="iconbutton reset" title="resetsearch" content=" " />
        </div>
    </div>
    <roundcube:object name="addressbooks" id="directorylist" class="listing" />
    <div class="scroller withfooter">
        <roundcube:object name="addresslist" id="contacts-table" class="listing" noheader="true" />
    <roundcube:object name="addressbooks" id="directorylist" class="treelist listing" summary="ariasummarycomposecontacts" />
    <div class="scroller withfooter" tabindex="-1">
        <roundcube:object name="addresslist" id="contacts-table" class="listing iconized" noheader="true" role="listbox" />
    </div>
<div class="boxfooter">
    <roundcube:button command="add-recipient" prop="to" type="link" title="to" class="listbutton addto disabled" classAct="listbutton addto" innerClass="inner" content="To+" /><roundcube:button command="add-recipient" prop="cc" type="link" title="cc" class="listbutton addcc disabled" classAct="listbutton addcc" innerClass="inner" content="Cc+" /><roundcube:button command="add-recipient" prop="bcc" type="link" title="bcc" class="listbutton addbcc disabled" classAct="listbutton addbcc" innerClass="inner" content="Bcc+" />
</div>
<div class="boxpagenav">
    <roundcube:button command="firstpage" type="link" class="icon firstpage disabled" classAct="icon firstpage" title="firstpage" content="|&amp;lt;" />
    <roundcube:button command="previouspage" type="link" class="icon prevpage disabled" classAct="icon prevpage" title="previouspage" content="&amp;lt;" />
    <roundcube:button command="nextpage" type="link" class="icon nextpage disabled" classAct="icon nextpage" title="nextpage" content="&amp;gt;" />
    <roundcube:button command="lastpage" type="link" class="icon lastpage disabled" classAct="icon lastpage" title="lastpage" content="&amp;gt;|" />
    <roundcube:button command="firstpage" type="link" class="icon firstpage disabled" classAct="icon firstpage" title="firstpage" label="first" />
    <roundcube:button command="previouspage" type="link" class="icon prevpage disabled" classAct="icon prevpage" title="previouspage" label="previous" />
    <roundcube:button command="nextpage" type="link" class="icon nextpage disabled" classAct="icon nextpage" title="nextpage" label="next" />
    <roundcube:button command="lastpage" type="link" class="icon lastpage disabled" classAct="icon lastpage" title="lastpage" label="last" />
</div>
</div>
</div>
<div id="composeview-right">
<div id="composeview-right" role="main">
<roundcube:form name="form" method="post" id="compose-content" class="uibox">
<!-- message headers -->
<div id="composeheaders">
<a href="#options" id="composeoptionstoggle" class="moreheaderstoggle"><span class="iconlink" title="<roundcube:label name='options' />"></span></a>
<div id="composeheaders" role="region" aria-labelledby="aria-label-composeheaders">
<h2 id="aria-label-composeheaders" class="voice"><roundcube:label name="arialabelmessageheaders" /></h2>
<a href="#options" id="composeoptionstoggle" class="moreheaderstoggle" title="<roundcube:label name='togglecomposeoptions' />" aria-exapnded="false"><span class="iconlink"></span></a>
<table class="headers-table compose-headers">
<tbody>
@@ -80,77 +85,78 @@
        <td class="title"><label for="_from"><roundcube:label name="from" /></label></td>
        <td class="editfield">
            <roundcube:object name="composeHeaders" part="from" form="form" id="_from" tabindex="1" />
            <a href="#identities" onclick="return rcmail.command('identities')" class="iconlink edit"><roundcube:label name="editidents" /></a>
            <a href="#identities" onclick="return rcmail.command('identities')" class="iconlink edit" tabindex="0"><roundcube:label name="editidents" /></a>
        </td>
    </tr><tr>
        <td class="title top"><label for="_to"><roundcube:label name="to" /></label></td>
        <td class="editfield"><roundcube:object name="composeHeaders" part="to" form="form" id="_to" cols="70" rows="1" tabindex="2" /></td>
        <td class="editfield"><roundcube:object name="composeHeaders" part="to" form="form" id="_to" cols="70" rows="1" tabindex="1" aria-required="true" /></td>
    </tr><tr id="compose-cc">
        <td class="title top">
            <label for="_cc"><roundcube:label name="cc" /></label>
            <a href="#cc" onclick="return UI.hide_header_row('cc');" class="iconbutton cancel" title="<roundcube:label name='delete' />">x</a>
            <a href="#cc" onclick="return UI.hide_header_row('cc');" class="iconbutton cancel" title="<roundcube:label name='delete' />" tabindex="3"><roundcube:label name="delete" /> <roundcube:label name="cc" /></a>
        </td>
        <td class="editfield"><roundcube:object name="composeHeaders" part="cc" form="form" id="_cc" cols="70" rows="1" tabindex="3" /></td>
        <td class="editfield"><roundcube:object name="composeHeaders" part="cc" form="form" id="_cc" cols="70" rows="1" tabindex="1" /></td>
    </tr><tr id="compose-bcc">
        <td class="title top">
            <label for="_bcc"><roundcube:label name="bcc" /></label>
            <a href="#bcc" onclick="return UI.hide_header_row('bcc');" class="iconbutton cancel" title="<roundcube:label name='delete' />">x</a>
            <a href="#bcc" onclick="return UI.hide_header_row('bcc');" class="iconbutton cancel" title="<roundcube:label name='delete' />" tabindex="3"><roundcube:label name="delete" /> <roundcube:label name="bcc" /></a>
        </td>
        <td class="editfield"><roundcube:object name="composeHeaders" part="bcc" form="form" id="_bcc" cols="70" rows="1" tabindex="4" /></td>
        <td class="editfield"><roundcube:object name="composeHeaders" part="bcc" form="form" id="_bcc" cols="70" rows="1" tabindex="1" /></td>
    </tr><tr id="compose-replyto">
        <td class="title top">
            <label for="_replyto"><roundcube:label name="replyto" /></label>
            <a href="#replyto" onclick="return UI.hide_header_row('replyto');" class="iconbutton cancel" title="<roundcube:label name='delete' />">x</a>
            <a href="#replyto" onclick="return UI.hide_header_row('replyto');" class="iconbutton cancel" title="<roundcube:label name='delete' />" tabindex="3"><roundcube:label name="delete" /> <roundcube:label name="replyto" /></a>
        </td>
        <td class="editfield"><roundcube:object name="composeHeaders" part="replyto" form="form" id="_replyto" size="70" tabindex="5" /></td>
        <td class="editfield"><roundcube:object name="composeHeaders" part="replyto" form="form" id="_replyto" size="70" tabindex="1" /></td>
    </tr><tr id="compose-followupto">
        <td class="title top">
            <label for="_followupto"><roundcube:label name="followupto" /></label>
            <a href="#followupto" onclick="return UI.hide_header_row('followupto');" class="iconbutton cancel" title="<roundcube:label name='delete' />">x</a>
            <a href="#followupto" onclick="return UI.hide_header_row('followupto');" class="iconbutton cancel" title="<roundcube:label name='delete' />" tabindex="3"><roundcube:label name="delete" /> <roundcube:label name="followupto" /></a>
        </td>
        <td class="editfield"><roundcube:object name="composeHeaders" part="followupto" form="form" id="_followupto" size="70" tabindex="7" /></td>
        <td class="editfield"><roundcube:object name="composeHeaders" part="followupto" form="form" id="_followupto" size="70" tabindex="1" /></td>
    </tr><tr>
        <td></td>
        <td class="formlinks">
            <a href="#cc" onclick="return UI.show_header_row('cc')" id="cc-link" class="iconlink add"><roundcube:label name="addcc" /></a>
            <a href="#bcc" onclick="return UI.show_header_row('bcc')" id="bcc-link" class="iconlink add"><roundcube:label name="addbcc" /></a>
            <a href="#reply-to" onclick="return UI.show_header_row('replyto')" id="replyto-link" class="iconlink add"><roundcube:label name="addreplyto" /></a>
            <a href="#followup-to" onclick="return UI.show_header_row('followupto')" id="followupto-link" class="iconlink add"><roundcube:label name="addfollowupto" /></a>
            <a href="#cc" onclick="return UI.show_header_row('cc')" id="cc-link" class="iconlink add" tabindex="3"><roundcube:label name="addcc" /></a>
            <a href="#bcc" onclick="return UI.show_header_row('bcc')" id="bcc-link" class="iconlink add" tabindex="3"><roundcube:label name="addbcc" /></a>
            <a href="#reply-to" onclick="return UI.show_header_row('replyto')" id="replyto-link" class="iconlink add" tabindex="3"><roundcube:label name="addreplyto" /></a>
            <a href="#followup-to" onclick="return UI.show_header_row('followupto')" id="followupto-link" class="iconlink add" tabindex="3"><roundcube:label name="addfollowupto" /></a>
        </td>
    </tr><tr>
        <td class="title"><label for="compose-subject"><roundcube:label name="subject" /></label></td>
        <td class="editfield"><roundcube:object name="composeSubject" id="compose-subject" form="form" tabindex="8" /></td>
        <td class="editfield"><roundcube:object name="composeSubject" id="compose-subject" form="form" tabindex="1" /></td>
    </tr>
</tbody>
</table>
<div id="composebuttons" class="formbuttons">
    <roundcube:button command="extwin" type="link" class="button extwin" classSel="button extwin pressed" innerClass="icon" title="openinextwin" content="[]" condition="!env:extwin" />
    <roundcube:button command="extwin" type="link" class="button extwin" classSel="button extwin pressed" innerClass="icon" title="openinextwin" label="openinextwin" condition="!env:extwin" />
</div>
<!-- (collapsable) message options -->
<div id="composeoptions">
<div id="composeoptions" role="region" aria-labelledby="aria-label-composeoptions">
    <h2 id="aria-label-composeoptions" class="voice"><roundcube:label name="arialabelcomposeoptions" /></h2>
    <roundcube:if condition="!in_array('htmleditor', (array)config:dont_override)" />
    <span class="composeoption">
        <label><roundcube:label name="editortype" />
            <roundcube:object name="editorSelector" editorid="composebody" tabindex="14" /></label>
            <roundcube:object name="editorSelector" editorid="composebody" tabindex="4" /></label>
    </span>
    <roundcube:endif />
    <span class="composeoption">
        <label for="rcmcomposepriority"><roundcube:label name="priority" />
            <roundcube:object name="prioritySelector" form="form" id="rcmcomposepriority" /></label>
            <roundcube:object name="prioritySelector" form="form" id="rcmcomposepriority" tabindex="4" /></label>
    </span>
    <span class="composeoption">
        <label><roundcube:object name="receiptCheckBox" form="form" id="rcmcomposereceipt" /> <roundcube:label name="returnreceipt" /></label>
        <label><roundcube:object name="receiptCheckBox" form="form" id="rcmcomposereceipt" tabindex="4" /> <roundcube:label name="returnreceipt" /></label>
    </span>
    <roundcube:if condition="config:smtp_server != ''" />
    <span class="composeoption">
        <label><roundcube:object name="dsnCheckBox" form="form" id="rcmcomposedsn" /> <roundcube:label name="dsn" /></label>
        <label><roundcube:object name="dsnCheckBox" form="form" id="rcmcomposedsn" tabindex="4" /> <roundcube:label name="dsn" /></label>
    </span>
    <roundcube:endif />
    <roundcube:if condition="!config:no_save_sent_messages" />
    <span class="composeoption">
        <label><roundcube:label name="savesentmessagein" /> <roundcube:object name="storetarget" maxlength="30" style="max-width:12em" /></label>
        <label><roundcube:label name="savesentmessagein" /> <roundcube:object name="storetarget" maxlength="30" style="max-width:12em" tabindex="4" /></label>
    </span>
    <roundcube:endif />
    <roundcube:container name="composeoptions" id="composeoptions" />
@@ -161,11 +167,13 @@
<!-- message compose body -->
<div id="composeview-bottom">
    <div id="composebodycontainer">
        <roundcube:object name="composeBody" id="composebody" form="form" cols="70" rows="20" tabindex="9" />
        <label for="composebody" class="voice"><roundcube:label name="arialabelmessagebody" /></label>
        <roundcube:object name="composeBody" id="composebody" form="form" cols="70" rows="20" tabindex="1" />
    </div>
    <div id="compose-attachments" class="rightcol">
    <div id="compose-attachments" class="rightcol" role="region" aria-labelledby="aria-label-composeattachments">
        <h2 id="aria-label-composeattachments" class="voice"><roundcube:label name="attachments" /></h2>
        <div style="text-align:center; margin-bottom:20px">
            <roundcube:button name="addattachment" type="input" class="button" classSel="button pressed" label="addattachment" onclick="UI.show_uploadform();return false" />
            <roundcube:button name="addattachment" type="input" class="button" classSel="button pressed" label="addattachment" onclick="UI.show_uploadform(event);return false" tabindex="1" />
        </div>
        <roundcube:object name="composeAttachmentList" id="attachment-list" class="attachmentslist" />
        <roundcube:object name="fileDropArea" id="compose-attachments" />
@@ -187,7 +195,8 @@
</div><!-- end mainscreen -->
<div id="upload-dialog" class="propform popupdialog" title="<roundcube:label name='addattachment' />">
<div id="upload-dialog" class="propform popupdialog" title="<roundcube:label name='addattachment' />" aria-hidden="true">
    <h2 id="aria-label-uploaddialog" class="voice"><roundcube:label name="arialabelattachmentuploadform" /></h2>
    <roundcube:object name="composeAttachmentForm" id="uploadform" buttons="no" />
    <div class="formbuttons">
        <roundcube:button command="send-attachment" type="input" class="button mainaction" label="upload" />
@@ -195,15 +204,16 @@
    </div>
</div>
<div id="spellmenu" class="popupmenu"></div>
<div id="spellmenu" class="popupmenu" aria-hidden="true"></div>
<div id="responsesmenu" class="popupmenu">
    <ul class="toolbarmenu" id="textresponsesmenu">
        <li class="separator" id=""><label><roundcube:label name="insertresponse" /></label></li>
<div id="responsesmenu" class="popupmenu" aria-hidden="true">
    <h3 id="aria-label-responsesmenu" class="voice"><roundcube:label name="arialabelresponsesmenu" /></h3>
    <ul class="toolbarmenu" id="textresponsesmenu" role="menu" aria-labelledby="aria-label-responsesmenu">
        <li role="separator" class="separator" id=""><label><roundcube:label name="insertresponse" /></label></li>
        <roundcube:object name="responseslist" id="responseslist" tagname="ul" itemclass="active" />
        <li class="separator"><label><roundcube:label name="manageresponses" /></label></li>
        <li><roundcube:button command="save-response" type="link" label="savenewresponse" classAct="active" unselectable="on" /></li>
        <li><roundcube:button command="responses" type="link" label="editresponses" classAct="active" /></li>
        <li role="separator" class="separator"><label><roundcube:label name="manageresponses" /></label></li>
        <li role="menuitem"><roundcube:button command="save-response" type="link" label="savenewresponse" classAct="active" unselectable="on" /></li>
        <li role="menuitem"><roundcube:button command="responses" type="link" label="editresponses" classAct="active" /></li>
    </ul>
</div>
skins/larry/templates/contactedit.html
@@ -16,7 +16,8 @@
        <div id="sourcename"><roundcube:label name="addressbook" />: <roundcube:var name="env:sourcename" condition="env:action!='add'" /><roundcube:object name="sourceselector" id="sourceselect" condition="env:action=='add'" /></div>
    <roundcube:endif />
    <div id="contactphoto">
    <fieldset id="contactphoto">
        <legend class="voice"><roundcube:label name="contactphoto" /></legend>
        <roundcube:object name="contactphoto" id="contactpic" placeholder="/images/contactpic.png" />
        <roundcube:if condition="env:photocol" />
        <roundcube:object name="fileDropArea" id="contactpic" />
@@ -25,7 +26,7 @@
            <roundcube:button command="delete-photo" type="link" label="delete" class="iconlink delete disabled" classAct="iconlink delete active" condition="env:photocol" />
        </div>
        <roundcube:endif />
    </div>
    </fieldset>
    <roundcube:object name="contactedithead" id="contacthead" size="16" form="editform" />
    <br style="clear:both" />
skins/larry/templates/folders.html
@@ -10,9 +10,11 @@
<div id="mainscreen" class="offset">
<h1 class="voice"><roundcube:label name="settings" /> : <roundcube:label name="folders" /></h1>
<roundcube:include file="/includes/settingstabs.html" />
<div id="settings-right">
<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>
@@ -20,11 +22,22 @@
<roundcube:object name="foldersubscription" form="subscriptionform" id="subscription-table" class="listing" noheader="true" />
</div>
<div id="folderslist-footer" class="boxfooter">
    <roundcube:button command="create-folder" type="link" title="createfolder" class="listbutton add disabled" classAct="listbutton add" innerClass="inner" content="+" /><roundcube:button name="mailboxmenulink" id="mailboxmenulink" type="link" title="folderactions" class="listbutton groupactions" onclick="UI.show_popup('mailboxmenu');return false" innerClass="inner" content="&#9881;" />
    <roundcube:button command="create-folder" type="link" title="createfolder" class="listbutton add disabled" classAct="listbutton add" innerClass="inner" label="createfolder" /><roundcube:button name="mailboxmenulink" id="mailboxmenulink" type="link" title="folderactions" class="listbutton groupactions" onclick="return UI.toggle_popup('mailboxmenu',event)" innerClass="inner" content="&#9881;" aria-haspopup="true" aria-expanded="false" aria-owns="mailboxoptionsmenu" />
    <roundcube:if condition="env:quota" />
        <span class="voice"><roundcube:label name="quota"></span>
        <roundcube:object name="quotaDisplay" id="quotadisplay" class="countdisplay" display="text" />
    <roundcube:endif />
</div>
<div id="mailboxmenu" class="popupmenu" aria-hidden="true">
    <h3 id="aria-label-mailboxmenu" class="voice"><roundcube:label name="arialabelmailboxmenu" /></h3>
    <ul class="toolbarmenu" id="mailboxoptionsmenu" role="menu" aria-labelledby="aria-label-mailboxmenu">
        <li role="menuitem"><roundcube:button command="delete-folder" label="delete" classAct="active" /></li>
        <li role="menuitem"><roundcube:button command="purge" type="link" label="empty" classAct="active" /></li>
        <roundcube:container name="mailboxoptions" id="mailboxoptionsmenu" />
    </ul>
</div>
</div>
<div id="folder-details" class="uibox contentbox">
@@ -35,14 +48,6 @@
</div>
</div>
<div id="mailboxmenu" class="popupmenu">
    <ul class="toolbarmenu" id="mailboxoptionsmenu">
        <li><roundcube:button command="delete-folder" label="delete" classAct="active" /></li>
        <li><roundcube:button command="purge" type="link" label="empty" classAct="active" /></li>
        <roundcube:container name="mailboxoptions" id="mailboxoptionsmenu" />
    </ul>
</div>
<roundcube:include file="/includes/footer.html" />
skins/larry/templates/identities.html
@@ -10,23 +10,25 @@
<div id="mainscreen" class="offset">
<h1 class="voice"><roundcube:label name="settings" /> : <roundcube:label name="identities" /></h1>
<roundcube:include file="/includes/settingstabs.html" />
<div id="settings-right">
<div id="settings-right" role="main" aria-labelledby="aria-label-identitieslist">
    
<div id="identitieslist" class="uibox listbox">
<h2 class="boxtitle"><roundcube:label name="identities" /></h2>
<h2 class="boxtitle" id="aria-label-identitieslist"><roundcube:label name="identities" /></h2>
<div class="scroller withfooter">
<roundcube:object name="identitiesList" id="identities-table" class="listing" cellspacing="0" summary="Identities list" noheader="true" editIcon="" />
<roundcube:object name="identitiesList" id="identities-table" class="listing" noheader="true" editIcon="" role="listbox" />
</div>
<div class="boxfooter">
<roundcube:button command="add" type="link" title="newidentity" class="listbutton add disabled" classAct="listbutton add" innerClass="inner" content="+" condition="config:identities_level:0<2" /><roundcube:button command="delete" type="link" title="delete" class="listbutton delete disabled" classAct="listbutton delete" innerClass="inner" content="-" condition="config:identities_level:0<2" />
<roundcube:button command="add" type="link" title="newidentity" class="listbutton add disabled" classAct="listbutton add" innerClass="inner" label="newidentity" condition="config:identities_level:0<2" /><roundcube:button command="delete" type="link" title="delete" class="listbutton delete disabled" classAct="listbutton delete" innerClass="inner" label="delete" condition="config:identities_level:0<2" />
</div>
</div>
<div id="identity-details" class="uibox contentbox">
    <div class="iframebox">
        <roundcube:object name="identityframe" id="preferences-frame" style="width:100%; height:100%" frameborder="0" src="/watermark.html" />
        <roundcube:object name="identityframe" id="preferences-frame" style="width:100%; height:100%" frameborder="0" src="/watermark.html" title="arialabelidentityeditfrom" />
    </div>
</div>
skins/larry/templates/importcontacts.html
@@ -15,7 +15,7 @@
</div>
<div id="pluginbody" class="offset uibox contentbox">
<h2 class="boxtitle"><roundcube:label name="importcontacts" /></h2>
<h1 class="boxtitle"><roundcube:label name="importcontacts" /></h1>
<div id="import-box" class="boxcontent">
<roundcube:object name="importstep" class="propform" />
skins/larry/templates/login.html
@@ -7,8 +7,10 @@
</head>
<body>
<h1 class="voice"><roundcube:object name="productname" /> <roundcube:label name="login" /></h1>
<div id="login-form">
<div class="box-inner">
<div class="box-inner" role="main">
<roundcube:object name="logo" src="/images/roundcube_logo.png" id="logo" />
<roundcube:form name="form" method="post">
@@ -17,15 +19,15 @@
</div>
<div class="box-bottom">
<div class="box-bottom" role="complementary">
    <roundcube:object name="message" id="message" />
    <noscript>
        <p class="noscriptwarning"><roundcube:label name="noscriptwarning" /></p>
    </noscript>
</div>
<div id="bottomline">
    <roundcube:var name="config:product_name"> <roundcube:object name="version" condition="config:display_version" />
<div id="bottomline" role="contentinfo">
    <roundcube:object name="productname" /> <roundcube:object name="version" condition="config:display_version" />
    <roundcube:if condition="config:support_url" />
        &nbsp;&#9679;&nbsp; <a href="<roundcube:var name='config:support_url' />" target="_blank" class="support-link"><roundcube:label name="support" /></a>
    <roundcube:endif />
skins/larry/templates/mail.html
@@ -17,8 +17,11 @@
<div id="mainscreen">
<h1 class="voice"><roundcube:label name="mail" /></h1>
<!-- toolbar -->
<div id="messagetoolbar" class="toolbar">
<h2 id="aria-label-toolbar" class="voice"><roundcube:label name="arialabeltoolbar" /></h2>
<div id="messagetoolbar" class="toolbar" role="toolbar" aria-labelledby="aria-label-toolbar">
    <roundcube:button command="checkmail" type="link" class="button checkmail disabled" classAct="button checkmail" classSel="button checkmail pressed" label="refresh" title="checkmail" />
    <roundcube:include file="/includes/mailtoolbar.html" />
</div>
@@ -27,14 +30,35 @@
<!-- search filter -->
<div id="searchfilter">
    <roundcube:object name="searchfilter" class="searchfilter decorated" />
    <label for="messagessearchfilter" class="voice"><roundcube:label name="arialabelmessagessearchfilter" /></label>
    <roundcube:object name="searchfilter" class="searchfilter decorated" id="messagessearchfilter" aria-controls="messagelist" />
</div>
<!-- search box -->
<div id="quicksearchbar" class="searchbox">
<div id="quicksearchbar" class="searchbox" role="search" aria-labelledby="aria-label-searchform">
<h2 id="aria-label-searchform" class="voice"><roundcube:label name="arialabelmailsearchform" /></h2>
<label for="quicksearchbox" class="voice"><roundcube:label name="arialabelmailquicksearchbox" /></label>
<roundcube:object name="searchform" id="quicksearchbox" />
<roundcube:button name="searchmenulink" id="searchmenulink" class="iconbutton searchoptions" onclick="UI.show_popup('searchmenu');return false" title="searchmod" content=" " />
<roundcube:button command="reset-search" id="searchreset" class="iconbutton reset" title="resetsearch" content=" " />
<roundcube:button command="menu-open" prop="searchmenu" id="searchmenulink" class="iconbutton searchoptions" title="searchmod" label="options" aria-haspopup="true" aria-expanded="false" aria-owns="searchmenu-menu" />
<roundcube:button command="reset-search" id="searchreset" class="iconbutton reset" title="resetsearch" label="resetsearch" />
<div id="searchmenu" class="popupmenu" data-editable="true">
    <h3 id="aria-label-searchmenu" class="voice"><roundcube:label name="searchmod" /></h3>
    <ul class="toolbarmenu" id="searchmenu-menu" role="menu" aria-labelledby="aria-label-searchmenu">
        <li role="menuitem"><label><input type="checkbox" name="s_mods[]" value="subject" id="s_mod_subject" onclick="UI.set_searchmod(this)" /> <span><roundcube:label name="subject" /></span></label></li>
        <li role="menuitem"><label><input type="checkbox" name="s_mods[]" value="from" id="s_mod_from" onclick="UI.set_searchmod(this)" /> <span><roundcube:label name="from" /></span></label></li>
        <li role="menuitem"><label><input type="checkbox" name="s_mods[]" value="to" id="s_mod_to" onclick="UI.set_searchmod(this)" /> <span><roundcube:label name="to" /></span></label></li>
        <li role="menuitem"><label><input type="checkbox" name="s_mods[]" value="cc" id="s_mod_cc" onclick="UI.set_searchmod(this)" /> <span><roundcube:label name="cc" /></span></label></li>
        <li role="menuitem"><label><input type="checkbox" name="s_mods[]" value="bcc" id="s_mod_bcc" onclick="UI.set_searchmod(this)" /> <span><roundcube:label name="bcc" /></span></label></li>
        <li role="menuitem"><label><input type="checkbox" name="s_mods[]" value="body" id="s_mod_body" onclick="UI.set_searchmod(this)" /> <span><roundcube:label name="body" /></span></label></li>
        <li role="menuitem"><label><input type="checkbox" name="s_mods[]" value="text" id="s_mod_text" onclick="UI.set_searchmod(this)" /> <span><roundcube:label name="msgtext" /></span></label></li>
        <li role="separator" class="separator"><label><roundcube:label name="searchscope" /></label></li>
        <li role="menuitem"><label><input type="radio" name="s_scope" value="base" id="s_scope_base" onclick="UI.set_searchscope(this)" /> <span><roundcube:label name="currentfolder" /></span></label></li>
        <li role="menuitem"><label><input type="radio" name="s_scope" value="sub" id="s_scope_sub" onclick="UI.set_searchscope(this)" /> <span><roundcube:label name="subfolders" /></span></label></li>
        <li role="menuitem"><label><input type="radio" name="s_scope" value="all" id="s_scope_all" onclick="UI.set_searchscope(this)" /> <span><roundcube:label name="allfolders" /></span></label></li>
    </ul>
</div>
</div>
</div>
@@ -43,13 +67,15 @@
<div id="mailview-left">
<!-- folders list -->
<div id="mailboxcontainer" class="uibox listbox">
<div id="mailboxcontainer" class="uibox listbox" role="navigation" aria-labelledby="aria-label-folderlist">
<h2 id="aria-label-folderlist" class="voice"><roundcube:label name="arialabelfolderlist" /></h2>
<div id="folderlist-content" class="scroller withfooter">
<roundcube:object name="mailboxlist" id="mailboxlist" class="treelist listing" folder_filter="mail" unreadwrap="%s" />
</div>
<div id="folderlist-footer" class="boxfooter">
    <roundcube:button name="mailboxmenulink" id="mailboxmenulink" type="link" title="folderactions" class="listbutton groupactions" onclick="UI.show_popup('mailboxmenu');return false" innerClass="inner" content="&#9881;" />
    <roundcube:button name="mailboxmenulink" id="mailboxmenulink" type="link" title="folderactions" class="listbutton groupactions" onclick="UI.toggle_popup('mailboxmenu',event);return false" innerClass="inner" content="&#9881;" aria-haspopup="true" aria-expanded="false" aria-owns="mailboxoptionsmenu" />
    <roundcube:if condition="env:quota" />
        <span class="voice"><roundcube:label name="quota"></span>
        <roundcube:object name="quotaDisplay" id="quotadisplay" class="countdisplay" display="text" />
    <roundcube:endif />
</div>
@@ -57,7 +83,7 @@
</div>
<div id="mailview-right">
<div id="mailview-right" role="main">
<roundcube:if condition="config:preview_pane == true" />
<div id="mailview-top" class="uibox">
@@ -67,10 +93,20 @@
<!-- messagelist -->
<div id="messagelistcontainer" class="boxlistcontent">
<h2 id="aria-label-messagelist" class="voice"><roundcube:label name="arialabelmessagelist" /></h2>
<roundcube:object name="messages"
    id="messagelist"
    class="records-table messagelist sortheader fixedheader"
    optionsmenuIcon="true" />
    optionsmenuIcon="true"
    aria-labelledby="aria-label-messagelist" />
</div>
<div class="voice" role="note">
<h3><roundcube:label name="helplistnavigation" /></h3>
<pre>
<roundcube:label name="helplistkeyboardnavigation" />
<roundcube:label name="helplistkeyboardnavmessages" />
</pre>
</div>
<!-- list footer -->
@@ -81,33 +117,34 @@
    </div>
    
    <div id="listselectors">
    <a href="#select" id="listselectmenulink" class="menuselector" onclick="UI.show_popup('listselectmenu');return false"><span class="handle"><roundcube:label name="select" /></span></a>
    <a href="#select" id="listselectmenulink" class="menuselector" onclick="UI.toggle_popup('listselectmenu', event);return false" aria-haspopup="true" aria-expanded="false" aria-owns="listselectmenu-menu"><span class="handle"><roundcube:label name="select" /></span></a>
    <roundcube:if condition="env:threads" />
        &nbsp; <a href="#threads" id="threadselectmenulink" class="menuselector" onclick="UI.show_popup('threadselectmenu');return false"><span class="handle"><roundcube:label name="threads" /></span></a>
        &nbsp; <a href="#threads" id="threadselectmenulink" class="menuselector" onclick="UI.toggle_popup('threadselectmenu', event);return false" aria-haspopup="true" aria-expanded="false" aria-owns="threadselectmenu-menu"><span class="handle"><roundcube:label name="threads" /></span></a>
    <roundcube:endif />
    </div>
    <div id="countcontrols" class="pagenav dark">
        <roundcube:object name="messageCountDisplay" class="countdisplay" />
        <roundcube:object name="messageCountDisplay" class="countdisplay" aria-live="polite" aria-relevant="text" />
        <span class="pagenavbuttons">
        <roundcube:button command="firstpage" type="link" class="button firstpage disabled" classAct="button firstpage" classSel="button firstpage pressed" innerClass="inner" title="firstpage" content="|&amp;lt;" />
        <roundcube:button command="previouspage" type="link" class="button prevpage disabled" classAct="button prevpage" classSel="button prevpage pressed" innerClass="inner" title="previouspage" content="&amp;lt;" />
        <roundcube:button command="nextpage" type="link" class="button nextpage disabled" classAct="button nextpage" classSel="button nextpage pressed" innerClass="inner" title="nextpage" content="&amp;gt;" />
        <roundcube:button command="lastpage" type="link" class="button lastpage disabled" classAct="button lastpage" classSel="button lastpage pressed" innerClass="inner" title="lastpage" content="&amp;gt;|" />
        <roundcube:button command="firstpage" type="link" class="button firstpage disabled" classAct="button firstpage" classSel="button firstpage pressed" innerClass="inner" title="firstpage" label="first" />
        <roundcube:button command="previouspage" type="link" class="button prevpage disabled" classAct="button prevpage" classSel="button prevpage pressed" innerClass="inner" title="previouspage" label="previous" />
        <roundcube:button command="nextpage" type="link" class="button nextpage disabled" classAct="button nextpage" classSel="button nextpage pressed" innerClass="inner" title="nextpage" label="next" />
        <roundcube:button command="lastpage" type="link" class="button lastpage disabled" classAct="button lastpage" classSel="button lastpage pressed" innerClass="inner" title="lastpage" label="last" />
        </span>
    </div>
    <roundcube:container name="listcontrols" id="listcontrols" />
    <a href="#preview" id="mailpreviewtoggle" title="<roundcube:label name='previewpane' />"></a>
    <a href="#preview" id="mailpreviewtoggle" class="iconbutton" title="<roundcube:label name='previewpane' />" role="button" tabindex="0"><roundcube:label name="previewpane" /></a>
</div>
</div><!-- end mailview-top -->
<div id="mailview-bottom" class="uibox">
<div id="mailpreviewframe" class="iframebox">
<roundcube:object name="messagecontentframe" id="messagecontframe" style="width:100%; height:100%" frameborder="0" src="/watermark.html" />
<div id="mailpreviewframe" class="iframebox" role="complementary" aria-labelledby="aria-label-mailpreviewframe">
<h2 id="aria-label-mailpreviewframe" class="voice"><roundcube:label name="arialabelmailpreviewframe" /></h2>
<roundcube:object name="messagecontentframe" id="messagecontframe" style="width:100%; height:100%" frameborder="0" src="/watermark.html" title="arialabelmailpreviewframe" />
</div>
</div><!-- end mailview-bottom -->
@@ -118,59 +155,47 @@
</div><!-- end mainscreen -->
<div id="searchmenu" class="popupmenu">
    <ul class="toolbarmenu">
        <li><label><input type="checkbox" name="s_mods[]" value="subject" id="s_mod_subject" onclick="UI.set_searchmod(this)" /> <span><roundcube:label name="subject" /></span></label></li>
        <li><label><input type="checkbox" name="s_mods[]" value="from" id="s_mod_from" onclick="UI.set_searchmod(this)" /> <span><roundcube:label name="from" /></span></label></li>
        <li><label><input type="checkbox" name="s_mods[]" value="to" id="s_mod_to" onclick="UI.set_searchmod(this)" /> <span><roundcube:label name="to" /></span></label></li>
        <li><label><input type="checkbox" name="s_mods[]" value="cc" id="s_mod_cc" onclick="UI.set_searchmod(this)" /> <span><roundcube:label name="cc" /></span></label></li>
        <li><label><input type="checkbox" name="s_mods[]" value="bcc" id="s_mod_bcc" onclick="UI.set_searchmod(this)" /> <span><roundcube:label name="bcc" /></span></label></li>
        <li><label><input type="checkbox" name="s_mods[]" value="body" id="s_mod_body" onclick="UI.set_searchmod(this)" /> <span><roundcube:label name="body" /></span></label></li>
        <li><label><input type="checkbox" name="s_mods[]" value="text" id="s_mod_text" onclick="UI.set_searchmod(this)" /> <span><roundcube:label name="msgtext" /></span></label></li>
        <li class="separator"><label><roundcube:label name="searchscope" /></label></li>
        <li><label><input type="radio" name="s_scope" value="base" id="s_scope_base" onclick="UI.set_searchscope(this)" /> <span><roundcube:label name="currentfolder" /></span></label></li>
        <li><label><input type="radio" name="s_scope" value="sub" id="s_scope_sub" onclick="UI.set_searchscope(this)" /> <span><roundcube:label name="subfolders" /></span></label></li>
        <li><label><input type="radio" name="s_scope" value="all" id="s_scope_all" onclick="UI.set_searchscope(this)" /> <span><roundcube:label name="allfolders" /></span></label></li>
<div id="dragmessagemenu" class="popupmenu" aria-hidden="true">
    <ul class="toolbarmenu" role="menu">
        <li role="menuitem"><roundcube:button command="move" onclick="return rcmail.drag_menu_action('move')" label="move" classAct="active" /></li>
        <li role="menuitem"><roundcube:button command="copy" onclick="return rcmail.drag_menu_action('copy')" label="copy" classAct="active" /></li>
    </ul>
</div>
<div id="dragmessagemenu" class="popupmenu">
    <ul class="toolbarmenu">
        <li><roundcube:button command="move" onclick="return rcmail.drag_menu_action('move')" label="move" classAct="active" /></li>
        <li><roundcube:button command="copy" onclick="return rcmail.drag_menu_action('copy')" label="copy" classAct="active" /></li>
    </ul>
</div>
<div id="mailboxmenu" class="popupmenu">
    <ul class="toolbarmenu" id="mailboxoptionsmenu">
        <li><roundcube:button command="expunge" type="link" label="compact" classAct="active" /></li>
        <li><roundcube:button command="purge" type="link" label="empty" classAct="active" /></li>
        <li><roundcube:button command="import-messages" name="messageimport" type="link" classAct="active" label="importmessages" onclick="if(rcmail.command_enabled('import-messages'))UI.show_uploadform();return false" /></li>
        <li><roundcube:button command="folders" task="settings" type="link" label="managefolders" classAct="active" /></li>
<div id="mailboxmenu" class="popupmenu" aria-hidden="true">
    <h3 id="aria-label-mailboxmenu" class="voice"><roundcube:label name="arialabelmailboxmenu" /></h3>
    <ul class="toolbarmenu" id="mailboxoptionsmenu" role="menu" aria-labelledby="aria-label-mailboxmenu">
        <li role="menuitem"><roundcube:button command="expunge" type="link" label="compact" classAct="active" /></li>
        <li role="menuitem"><roundcube:button command="purge" type="link" label="empty" classAct="active" /></li>
        <li role="menuitem"><roundcube:button command="import-messages" name="messageimport" type="link" classAct="active" label="importmessages" onclick="if(rcmail.command_enabled('import-messages'))UI.show_uploadform();return false" /></li>
        <li role="menuitem"><roundcube:button command="folders" task="settings" type="link" label="managefolders" classAct="active" /></li>
        <roundcube:container name="mailboxoptions" id="mailboxoptionsmenu" />
    </ul>
</div>
<div id="listselectmenu" class="popupmenu dropdown">
    <ul class="toolbarmenu iconized">
        <li><roundcube:button command="select-all" type="link" label="all" class="icon" classAct="icon active" innerclass="icon mail" /></li>
        <li><roundcube:button command="select-all" type="link" prop="page" label="currpage" class="icon" classAct="icon active" innerclass="icon list" /></li>
        <li><roundcube:button command="select-all" type="link" prop="unread" label="unread" class="icon" classAct="icon active" innerclass="icon unread" /></li>
        <li><roundcube:button command="select-all" type="link" prop="flagged" label="flagged" class="icon" classAct="icon active" innerclass="icon flagged" /></li>
        <li><roundcube:button command="select-all" type="link" prop="invert" label="invert" class="icon" classAct="icon active" innerclass="icon invert" /></li>
        <li><roundcube:button command="select-none" type="link" label="none" class="icon" classAct="icon active" innerclass="icon cross" /></li>
<div id="listselectmenu" class="popupmenu dropdown" aria-hidden="true">
    <h3 id="aria-label-listselectmenu" class="voice"><roundcube:label name="arialabellistselectmenu" /></h3>
    <ul id="listselectmenu-menu" class="toolbarmenu iconized" role="menu" aria-labelledby="aria-label-listselectmenu">
        <li role="menuitem"><roundcube:button command="select-all" type="link" label="all" class="icon" classAct="icon active" innerclass="icon mail" /></li>
        <li role="menuitem"><roundcube:button command="select-all" type="link" prop="page" label="currpage" class="icon" classAct="icon active" innerclass="icon list" /></li>
        <li role="menuitem"><roundcube:button command="select-all" type="link" prop="unread" label="unread" class="icon" classAct="icon active" innerclass="icon unread" /></li>
        <li role="menuitem"><roundcube:button command="select-all" type="link" prop="flagged" label="flagged" class="icon" classAct="icon active" innerclass="icon flagged" /></li>
        <li role="menuitem"><roundcube:button command="select-all" type="link" prop="invert" label="invert" class="icon" classAct="icon active" innerclass="icon invert" /></li>
        <li role="menuitem"><roundcube:button command="select-none" type="link" label="none" class="icon" classAct="icon active" innerclass="icon cross" /></li>
    </ul>
</div>
<div id="threadselectmenu" class="popupmenu dropdown">
    <ul class="toolbarmenu">
        <li><roundcube:button command="expand-all" type="link" label="expand-all" class="icon" classAct="icon active" innerclass="icon conversation" /></li>
        <li><roundcube:button command="expand-unread" type="link" label="expand-unread" class="icon" classAct="icon active" innerclass="icon conversation" /></li>
        <li><roundcube:button command="collapse-all" type="link" label="collapse-all" class="icon" classAct="icon active" innerclass="icon conversation" /></li>
<div id="threadselectmenu" class="popupmenu dropdown" aria-hidden="true">
    <h3 id="aria-label-threadselectmenu" class="voice"><roundcube:label name="arialabelthreadselectmenu" /></h3>
    <ul id="threadselectmenu-menu" class="toolbarmenu" role="menu" aria-labelledby="aria-label-threadselectmenu">
        <li role="menuitem"><roundcube:button command="expand-all" type="link" label="expand-all" class="icon" classAct="icon active" innerclass="icon conversation" /></li>
        <li role="menuitem"><roundcube:button command="expand-unread" type="link" label="expand-unread" class="icon" classAct="icon active" innerclass="icon conversation" /></li>
        <li role="menuitem"><roundcube:button command="collapse-all" type="link" label="collapse-all" class="icon" classAct="icon active" innerclass="icon conversation" /></li>
    </ul>
</div>
<div id="listoptions" class="propform popupdialog">
<div id="listoptions" class="propform popupdialog" role="dialog" aria-labelledby="aria-label-listoptions" aria-hidden="true">
<h2 id="aria-label-listoptions" class="voice"><roundcube:label name="arialabelmessagelistoptions" /></h2>
<roundcube:if condition="!in_array('list_cols', (array)config:dont_override)" />
    <fieldset class="floating">
        <legend><roundcube:label name="listcolumns" /></legend>
@@ -219,11 +244,12 @@
    <br style="clear:both" />
    <div class="formbuttons">
        <roundcube:button command="menu-save" id="listmenusave" type="input" class="button mainaction" label="save" />
        <roundcube:button command="menu-open" id="listmenucancel" type="input" class="button" label="cancel" />
        <roundcube:button command="menu-close" prop="messagelistmenu" id="listmenucancel" type="input" class="button" label="cancel" />
    </div>
</div>
<div id="upload-dialog" class="propform popupdialog" title="<roundcube:label name='importmessages' />">
<div id="upload-dialog" class="propform popupdialog" title="<roundcube:label name='importmessages' />" aria-hidden="true">
    <h2 id="aria-label-uploaddialog" class="voice"><roundcube:label name="arialabelmailimportdialog" /></h2>
    <roundcube:object name="messageimportform" id="uploadform" buttons="no" />
    <div class="formbuttons">
        <roundcube:button command="import-messages" type="input" class="button mainaction" label="upload" />
skins/larry/templates/message.html
@@ -10,8 +10,11 @@
<div id="mainscreen">
<h1 class="voice"><roundcube:object name="messageHeaders" valueOf="subject" /></h1>
<!-- toolbar -->
<div id="messagetoolbar" class="toolbar fullwidth">
<h2 id="aria-label-toolbar" class="voice"><roundcube:label name="arialabeltoolbar" /></h2>
<div id="messagetoolbar" class="toolbar fullwidth" role="toolbar" aria-labelledby="aria-label-toolbar">
<roundcube:if condition="!env:extwin" />
    <roundcube:button command="list" type="link" class="button back disabled" classAct="button back" classSel="button back pressed" label="back" />
<roundcube:endif />
@@ -25,7 +28,8 @@
<div id="mailview-left">
<!-- folders list -->
<div id="mailboxcontainer" class="uibox listbox">
<div id="mailboxcontainer" class="uibox listbox" role="navigation" aria-labelledby="aria-label-folderlist">
<h2 id="aria-label-folderlist" class="voice"><roundcube:label name="arialabelfolderlist" /></h2>
<div class="scroller">
<roundcube:object name="mailboxlist" id="mailboxlist" class="treelist listing" folder_filter="mail" unreadwrap="%s" />
</div>
@@ -33,27 +37,22 @@
</div>
<div id="mailview-right" class="uibox">
<div id="mailview-right" class="uibox" role="main">
<roundcube:else />
<roundcube:object name="mailboxlist" folder_filter="mail" type="js" />
<div id="mailview-right" class="offset fullwidth uibox">
<div id="mailview-right" class="offset fullwidth uibox" role="main">
<roundcube:endif />
<div id="messageheader">
<span class="moreheaderstoggle"></span>
<h2 class="subject"><roundcube:object name="messageHeaders" valueOf="subject" /></h2>
<div class="message-headers">
<roundcube:object name="messageHeaders" class="headers-table" addicon="/images/addcontact.png" exclude="subject" max="20" />
</div>
<roundcube:object name="messageFullHeaders" id="full-headers" />
<!-- record navigation -->
<div id="countcontrols" class="pagenav">
<div id="countcontrols" class="pagenav" role="navigation" aria-labelledby="aria-label-countcontrols">
    <h2 id="aria-label-countcontrols" class="voice"><roundcube:label name="arialabelmessagenav" /></h2>
    <roundcube:object name="messageCountDisplay" class="countdisplay" />
    <roundcube:button command="previousmessage" type="link" class="button prevpage disabled" classAct="button prevpage" classSel="button prevpage pressed" innerClass="inner" title="previousmessage" content="&amp;lt;" />
    <roundcube:button command="nextmessage" type="link" class="button nextpage disabled" classAct="button nextpage" classSel="button nextpage pressed" innerClass="inner" title="nextmessage" content="&amp;gt;" />
    <roundcube:button command="previousmessage" type="link" class="button prevpage disabled" classAct="button prevpage" classSel="button prevpage pressed" innerClass="inner" title="previousmessage" label="previous" />
    <roundcube:button command="nextmessage" type="link" class="button nextpage disabled" classAct="button nextpage" classSel="button nextpage pressed" innerClass="inner" title="nextmessage" label="next" />
</div>
<roundcube:if condition="env:optional_format=='text'" />
@@ -70,15 +69,22 @@
</div>
<roundcube:endif />
<h2 class="subject"><span class="voice"><roundcube:label name="subject" />: </span><roundcube:object name="messageHeaders" valueOf="subject" /></h2>
<div class="message-headers">
<roundcube:object name="messageHeaders" class="headers-table" addicon="/images/addcontact.png" exclude="subject" max="20" />
</div>
<roundcube:object name="messageFullHeaders" id="full-headers" />
<div id="contactphoto"><roundcube:object name="contactphoto" /></div>
</div>
<div id="messagecontent">
<div class="rightcol">
<div class="rightcol" role="region" aria-labelledby="aria-label-messageattachments">
<h2 id="aria-label-messageattachments" class="voice"><roundcube:label name="attachments" /></h2>
<roundcube:object name="messageAttachments" id="attachment-list" class="attachmentslist" />
</div>
<div class="leftcol">
<div class="leftcol" role="region" aria-labelledby="aria-label-messagebody">
<h2 id="aria-label-messagebody" class="voice"><roundcube:label name="arialabelmessagebody" /></h2>
<roundcube:object name="messageObjects" id="message-objects" />
<roundcube:object name="messageBody" id="messagebody" headertableclass="message-partheaders headers-table" />
</div>
@@ -92,11 +98,11 @@
</div><!-- end mainscreen -->
<div id="attachmentmenu" class="popupmenu">
    <ul class="toolbarmenu">
        <li><roundcube:button command="open-attachment" id="attachmenuopen" type="link" label="open" class="icon" classAct="icon active" innerclass="icon extwin" /></li>
        <li><roundcube:button command="download-attachment" id="attachmenudownload" type="link" label="download" class="icon" classAct="icon active" innerclass="icon download" /></li>
        <roundcube:container name="attachmentmenu" id="attachmentmenu" />
<div id="attachmentmenu" class="popupmenu" aria-hidden="true">
    <ul class="toolbarmenu" id="attachmentoptionsmenu" role="menu">
        <li role="menuitem"><roundcube:button command="open-attachment" id="attachmenuopen" type="link" label="open" class="icon" classAct="icon active" innerclass="icon extwin" /></li>
        <li role="menuitem"><roundcube:button command="download-attachment" id="attachmenudownload" type="link" label="download" class="icon" classAct="icon active" innerclass="icon download" /></li>
        <roundcube:container name="attachmentmenu" id="attachmentoptionsmenu" />
    </ul>
</div>
skins/larry/templates/messageerror.html
@@ -16,11 +16,12 @@
<div id="mainscreen">
<h1 class="voice"><roundcube:label name="messageopenerror" /></h1>
<!-- toolbar -->
<div id="messagetoolbar" class="fullwidth">
    <div id="mailtoolbar" class="toolbar">
        <roundcube:button command="list" type="link" class="button back disabled" classAct="button back" classSel="button back pressed" label="back" />
    </div>
<h2 id="aria-label-toolbar" class="voice"><roundcube:label name="arialabeltoolbar" /></h2>
<div id="messagetoolbar" class="toolbar fullwidth" role="toolbar" aria-labelledby="aria-label-toolbar">
    <roundcube:button command="list" type="link" class="button back disabled" classAct="button back" classSel="button back pressed" label="back" />
</div>
<div id="mainscreencontent">
@@ -28,7 +29,8 @@
<div id="mailview-left">
<!-- folders list -->
<div id="mailboxcontainer" class="uibox listbox">
<div id="mailboxcontainer" class="uibox listbox" role="navigation" aria-labelledby="aria-label-folderlist">
<h2 id="aria-label-folderlist" class="voice"><roundcube:label name="arialabelfolderlist" /></h2>
<div class="scroller">
    <roundcube:object name="mailboxlist" id="mailboxlist" class="treelist listing" folder_filter="mail" unreadwrap="%s" />
</div>
@@ -36,7 +38,7 @@
</div>
<div id="mailview-right" class="offset uibox">
<div id="mailview-right" class="uibox">
<div id="messagecontent" class="watermark"></div>
skins/larry/templates/messagepart.html
@@ -10,7 +10,10 @@
<div id="mainscreen">
<div id="messagetoolbar" class="toolbar fullwidth">
<h1 class="voice"><roundcube:label name="attachment" />: <roundcube:var name="env:filename" /></h1>
<h2 id="aria-label-toolbar" class="voice"><roundcube:label name="arialabeltoolbar" /></h2>
<div id="messagetoolbar" class="toolbar fullwidth" role="toolbar" aria-labelledby="aria-label-toolbar">
    <roundcube:button command="download" type="link" class="button download disabled" classAct="button download" classSel="button download pressed" label="download" />
    <roundcube:button command="print" type="link" class="button print disabled" classAct="button print" classSel="button print pressed" label="print" />
    <roundcube:container name="toolbar" id="messagetoolbar" />
@@ -18,16 +21,17 @@
<div id="mainscreencontent">
<div id="messagepartheader" class="uibox listbox">
    <h2 class="boxtitle"><roundcube:label name="properties" /></h2>
<div id="messagepartheader" class="uibox listbox" role="contentinfo" aria-labelledby="aria-label-contentinfo">
    <h2 class="boxtitle" id="aria-label-contentinfo"><roundcube:label name="properties" /></h2>
    <div class="scroller">
        <roundcube:object name="messagePartControls" class="listing" />
    </div>
</div>
<div id="messagepartcontainer" class="uibox">
<div id="messagepartcontainer" class="uibox" role="main" aria-labelledby="aria-label-messagepart">
    <h2 id="aria-label-messagepart" class="voice"><roundcube:label name="arialabelattachmentpreview" /></h2>
    <div class="iframebox">
    <roundcube:object name="messagePartFrame" id="messagepartframe" frameborder="0" />
    <roundcube:object name="messagePartFrame" id="messagepartframe" frameborder="0" title="arialabelattachmentpreview" />
    </div>
</div>
skins/larry/templates/messagepreview.html
@@ -7,9 +7,33 @@
<body class="iframe fullheight">
<div id="messageheader" class="previewheader">
<h3 class="subject"><roundcube:object name="messageHeaders" valueOf="subject" /></h3>
<a href="#details" id="previewheaderstoggle" class="moreheaderstoggle"><span class="iconlink" title="<roundcube:label name='togglemoreheaders' />"></span></a>
<!-- record navigation -->
<div id="countcontrols" role="toolbar" aria-labelledby="aria-label-messagetoolbar">
<h2 id="aria-label-messagetoolbar" class="voice"><roundcube:label name="arialabelmessageactions" /></h2>
<roundcube:if condition="env:optional_format=='text'" />
    <span class="buttongroup">
        <roundcube:button command="change-format" prop="html" type="link" class="button first changeformat html selected" innerClass="icon" title="changeformathtml" content="HTML" /><roundcube:button command="change-format" prop="text" type="link" class="button last changeformat text" classSel="button changeformat text pressed" innerClass="icon" title="changeformattext" content="Text" />
    </span>
    &nbsp;
<roundcube:elseif condition="env:optional_format=='html'" />
    <span class="buttongroup">
        <roundcube:button command="change-format" prop="html" type="link" class="button first changeformat html" classSel="button changeformat html pressed" innerClass="icon" title="changeformathtml" content="HTML" /><roundcube:button command="change-format" prop="text" type="link" class="button last changeformat text selected" innerClass="icon" title="changeformattext" content="Text" />
    </span>
    &nbsp;
<roundcube:endif />
<roundcube:if condition="env:mailbox != config:drafts_mbox">
    <roundcube:button command="reply" type="link" class="button reply" classSel="button reply pressed" innerClass="icon" title="replytomessage" label="replytomessage" />
    <roundcube:button command="reply-all" type="link" class="button replyall" classSel="button replyall pressed" innerClass="icon" title="replytoallmessage" label="replytoallmessage" />
    <roundcube:button command="forward" type="link" class="button forward" classSel="button forward pressed" innerClass="icon" title="forwardmessage" label="forwardmessage" />
    &nbsp;
<roundcube:endif />
    <roundcube:button command="extwin" type="link" class="button extwin" classSel="button extwin pressed" innerClass="icon" title="openinextwin" label="openinextwin" />
</div>
<h3 class="subject"><span class="voice"><roundcube:label name="subject" />: </span><roundcube:object name="messageHeaders" valueOf="subject" /></h3>
<a href="#details" id="previewheaderstoggle" class="moreheaderstoggle" aria-expanded="false"><span class="iconlink" title="<roundcube:label name='togglemoreheaders' />"></span></a>
<div id="contactphoto"><roundcube:object name="contactphoto" /></div>
<table class="headers-table" id="preview-shortheaders"><tbody><tr>
@@ -28,45 +52,25 @@
<roundcube:object name="messageFullHeaders" id="full-headers" />
<!-- record navigation -->
<div id="countcontrols">
<roundcube:if condition="env:optional_format=='text'" />
    <span class="buttongroup">
        <roundcube:button command="change-format" prop="html" type="link" class="button first changeformat html selected" innerClass="icon" title="changeformathtml" content="HTML" /><roundcube:button command="change-format" prop="text" type="link" class="button last changeformat text" classSel="button changeformat text pressed" innerClass="icon" title="changeformattext" content="Text" />
    </span>
    &nbsp;
<roundcube:elseif condition="env:optional_format=='html'" />
    <span class="buttongroup">
        <roundcube:button command="change-format" prop="html" type="link" class="button first changeformat html" classSel="button changeformat html pressed" innerClass="icon" title="changeformathtml" content="HTML" /><roundcube:button command="change-format" prop="text" type="link" class="button last changeformat text selected" innerClass="icon" title="changeformattext" content="Text" />
    </span>
    &nbsp;
<roundcube:endif />
<roundcube:if condition="env:mailbox != config:drafts_mbox">
    <roundcube:button command="reply" type="link" class="button reply" classSel="button reply pressed" innerClass="icon" title="replytomessage" content="&lt;-" />
    <roundcube:button command="reply-all" type="link" class="button replyall" classSel="button replyall pressed" innerClass="icon" title="replytoallmessage" content="&lt;&lt;-" />
    <roundcube:button command="forward" type="link" class="button forward" classSel="button forward pressed" innerClass="icon" title="forwardmessage" content="-&gt;" />
    &nbsp;
<roundcube:endif />
    <roundcube:button command="extwin" type="link" class="button extwin" classSel="button extwin pressed" innerClass="icon" title="openinextwin" content="[]" />
</div>
</div>
<div id="messagepreview">
<div class="rightcol">
<div id="messagepreview" role="main">
<div class="rightcol" role="region" aria-labelledby="aria-label-messageattachments">
<h2 id="aria-label-messageattachments" class="voice"><roundcube:label name="attachments" /></h2>
<roundcube:object name="messageAttachments" id="attachment-list" class="attachmentslist" />
</div>
<div class="leftcol">
<div class="leftcol" role="region" aria-labelledby="aria-label-messagebody">
<h2 id="aria-label-messagebody" class="voice"><roundcube:label name="arialabelmessagebody" /></h2>
<roundcube:object name="messageObjects" id="message-objects" />
<roundcube:object name="messageBody" id="messagebody" headertableclass="message-partheaders headers-table" />
</div>
</div>
<div id="attachmentmenu" class="popupmenu">
    <ul class="toolbarmenu">
        <li><roundcube:button command="open-attachment" id="attachmenuopen" type="link" label="open" class="icon" classAct="icon active" innerclass="icon extwin" /></li>
        <li><roundcube:button command="download-attachment" id="attachmenudownload" type="link" label="download" class="icon" classAct="icon active" innerclass="icon download" /></li>
        <roundcube:container name="attachmentmenu" id="attachmentmenu" />
<div id="attachmentmenu" class="popupmenu" aria-hidden="true">
    <ul class="toolbarmenu" id="attachmentoptionsmenu" role="menu">
        <li role="menuitem"><roundcube:button command="open-attachment" id="attachmenuopen" type="link" label="open" class="icon" classAct="icon active" innerclass="icon extwin" /></li>
        <li role="menuitem"><roundcube:button command="download-attachment" id="attachmenudownload" type="link" label="download" class="icon" classAct="icon active" innerclass="icon download" /></li>
        <roundcube:container name="attachmentmenu" id="attachmentoptionsmenu" />
    </ul>
</div>
skins/larry/templates/responses.html
@@ -10,23 +10,25 @@
<div id="mainscreen" class="offset">
<h1 class="voice"><roundcube:label name="settings" /> : <roundcube:label name="identities" /></h1>
<roundcube:include file="/includes/settingstabs.html" />
<div id="settings-right">
<div id="settings-right" role="main" aria-labelledby="aria-label-responseslist">
<div id="identitieslist" class="uibox listbox">
<h2 class="boxtitle"><roundcube:label name="responses" /></h2>
<h2 class="boxtitle" id="aria-label-responseslist"><roundcube:label name="responses" /></h2>
<div class="scroller withfooter">
<roundcube:object name="responsesList" id="identities-table" class="listing" cellspacing="0" summary="Responses list" noheader="true" />
<roundcube:object name="responsesList" id="identities-table" class="listing" cellspacing="0" noheader="true" role="listbox" />
</div>
<div class="boxfooter">
<roundcube:button command="add" type="link" title="savenewresponse" class="listbutton add disabled" classAct="listbutton add" innerClass="inner" content="+" /><roundcube:button command="delete" type="link" title="delete" class="listbutton delete disabled" classAct="listbutton delete" innerClass="inner" content="-" />
<roundcube:button command="add" type="link" title="savenewresponse" class="listbutton add disabled" classAct="listbutton add" innerClass="inner" label="savenewresponse" /><roundcube:button command="delete" type="link" title="delete" class="listbutton delete disabled" classAct="listbutton delete" innerClass="inner" label="delete" />
</div>
</div>
<div id="identity-details" class="uibox contentbox">
    <div class="iframebox">
        <roundcube:object name="responseframe" id="preferences-frame" style="width:100%; height:100%" frameborder="0" src="/watermark.html" />
        <roundcube:object name="responseframe" id="preferences-frame" style="width:100%; height:100%" frameborder="0" src="/watermark.html" title="arialabelresonseeditfrom" />
    </div>
</div>
skins/larry/templates/settings.html
@@ -10,19 +10,22 @@
<div id="mainscreen" class="offset">
<h1 class="voice"><roundcube:label name="settings" /> : <roundcube:label name="preferences" /></h1>
<roundcube:include file="/includes/settingstabs.html" />
<div id="settings-right">
<div id="sectionslist" class="uibox listbox">
<div id="sectionslist" class="uibox listbox" role="navigation" aria-labelledby="aria-label-pefsection">
<h2 id="aria-label-pefsection" class="boxtitle"><roundcube:label name="section" /></h2>
<div class="scroller">
    <roundcube:object name="sectionslist" id="sections-table" class="listing" />
    <roundcube:object name="sectionslist" id="sections-table" class="listing iconized" noheader="true" />
</div>
</div>
<div id="preferences-box" class="uibox contentbox">
<div id="preferences-box" class="uibox contentbox" role="main">
    <div class="iframebox">
        <roundcube:object name="prefsframe" id="preferences-frame" style="width:100%; height:100%" frameborder="0" src="/watermark.html" />
        <roundcube:object name="prefsframe" id="preferences-frame" style="width:100%; height:100%" frameborder="0" src="/watermark.html" title="arialabelpreferencesform" />
    </div>
</div>
skins/larry/ui.js
@@ -20,13 +20,10 @@
    searchmenu:         { editable:1, callback:searchmenu },
    attachmentmenu:     { },
    listoptions:        { editable:1 },
    dragmenu:           { sticky:1 },
    groupmenu:          { above:1 },
    mailboxmenu:        { above:1 },
    spellmenu:          { callback: spellmenu },
    // toggle: #1486823, #1486930
    'attachment-form':  { editable:1, above:1, toggle:!bw.ie&&!bw.linux },
    'upload-form':      { editable:1, toggle:!bw.ie&&!bw.linux }
    'folder-selector':  { iconized:1 }
  };
  var me = this;
@@ -40,6 +37,7 @@
  this.init_tabs = init_tabs;
  this.show_about = show_about;
  this.show_popup = show_popup;
  this.toggle_popup = toggle_popup;
  this.add_popup = add_popup;
  this.set_searchmod = set_searchmod;
  this.set_searchscope = set_searchscope;
@@ -138,8 +136,9 @@
    /***  mail task  ***/
    if (rcmail.env.task == 'mail') {
      rcmail.addEventListener('menu-open', menu_open)
        .addEventListener('menu-save', menu_save)
      rcmail.addEventListener('menu-open', menu_toggle)
        .addEventListener('menu-close', menu_toggle)
        .addEventListener('menu-save', save_listoptions)
        .addEventListener('responseafterlist', function(e){ switch_view_mode(rcmail.env.threading ? 'thread' : 'list', true) })
        .addEventListener('responseaftersearch', function(e){ switch_view_mode(rcmail.env.threading ? 'thread' : 'list', true) });
@@ -157,7 +156,14 @@
        // add menu link for each attachment
        $('#attachment-list > li').each(function() {
          $(this).append($('<a class="drop"></a>').click(function() { attachmentmenu(this); }));
          $(this).append($('<a class="drop" tabindex="0" aria-haspopup="true">Show options</a>')
              .bind('click keypress', function(e) {
                  if (e.type != 'keypress' || rcube_event.get_keycode(e) == 13) {
                      attachmentmenu(this, e);
                      return false;
                  }
              })
          );
        });
        if (get_pref('previewheaders') == '1') {
@@ -184,11 +190,13 @@
          }
        }
        $('#composeoptionstoggle').click(function(){
          $('#composeoptionstoggle').toggleClass('remove');
          $('#composeoptions').toggle();
        $('#composeoptionstoggle').click(function(e){
          var expanded = $('#composeoptions').toggle().is(':visible');
          $('#composeoptionstoggle').toggleClass('remove').attr('aria-expanded', expanded ? 'true' : 'false');
          layout_composeview();
          save_pref('composeoptions', $('#composeoptions').is(':visible') ? '1' : '0');
          save_pref('composeoptions', expanded ? '1' : '0');
          if (!rcube_event.is_keyboard(e))
            this.blur();
          return false;
        }).css('cursor', 'pointer');
@@ -210,7 +218,7 @@
      }
      else if (rcmail.env.action == 'list' || !rcmail.env.action) {
        var previewframe = $('#mailpreviewframe').is(':visible');
        $('#mailpreviewtoggle').addClass(previewframe ? 'enabled' : 'closed').click(function(e){ toggle_preview_pane(e); return false });
        $('#mailpreviewtoggle').addClass(previewframe ? 'enabled' : 'closed').attr('aria-expanded', previewframe ? 'true' : 'false').click(function(e){ toggle_preview_pane(e); return false });
        $('#maillistmode').addClass(rcmail.env.threading ? '' : 'selected').click(function(e){ switch_view_mode('list'); return false });
        $('#mailthreadmode').addClass(rcmail.env.threading ? 'selected' : '').click(function(e){ switch_view_mode('thread'); return false });
@@ -265,7 +273,9 @@
          orientation:'v', relative:true, start:266, min:180, size:12 }).init();
      }
      else if (rcmail.env.action == 'edit-prefs') {
        $('<a href="#toggle">&#9660;</a>')
        $('<a href="#toggle"></a>')
            .text(env.toggleoptions)
            .attr('title', env.toggleoptions)
            .addClass('advanced-toggle')
            .appendTo('#preferences-details fieldset.advanced legend');
@@ -333,6 +343,10 @@
          var val = $('option:selected', this).text();
          $(this).next().children().text(val);
        });
      select
        .on('focus', function(e){ overlay.addClass('focus'); })
        .on('blur', function(e){ overlay.removeClass('focus'); });
    });
    // set min-width to show all toolbar buttons
@@ -341,60 +355,9 @@
      screen.css('min-width', $('.toolbar').width() + $('#quicksearchbar').width() + $('#searchfilter').width() + 30);
    }
    $(document.body)
      .bind('mouseup', body_mouseup)
      .bind('keyup', function(e){
        if (e.keyCode == 27) {
          for (var id in popups) {
            if (popups[id].is(':visible'))
              show_popup(id, false);
          }
        }
      });
    $('iframe').load(function(e){
      // this = iframe
      try {
        var doc = this.contentDocument ? this.contentDocument : this.contentWindow ? this.contentWindow.document : null;
        $(doc).mouseup(body_mouseup);
      }
      catch (e) {
        // catch possible "Permission denied" error in IE
      };
    })
    .contents().mouseup(body_mouseup);
    // don't use $(window).resize() due to some unwanted side-effects
    window.onresize = resize;
    resize();
  }
  /**
   * Handler for mouse-up events on the document body.
   * This will close all open popup menus
   */
  function body_mouseup(e)
  {
    var config, obj, target = e.target;
    if (target.className == 'inner')
        target = e.target.parentNode;
    for (var id in popups) {
      obj = popups[id];
      config = popupconfig[id];
      if (obj.is(':visible')
        && target.id != id+'link'
        && target != obj.get(0)  // check if scroll bar was clicked (#1489832)
        && !config.toggle
        && (!config.editable || !target_overlaps(target, obj.get(0)))
        && (!config.sticky || !rcube_mouse_is_over(e, obj.get(0)))
        && !$(target).is('.folder-selector-link')
      ) {
        var myid = id+'';
        window.setTimeout(function() { show_popupmenu(myid, false); }, 10);
      }
    }
  }
  /**
@@ -475,6 +438,8 @@
          minHeight: 90
        }).show();
      me.messagedialog.closest('div[role=dialog]').attr('role', 'alertdialog');
      me.message_timer = window.setTimeout(dialog_close, p.timeout);
    }
  }
@@ -489,7 +454,7 @@
    $('#message-objects div a').addClass('button');
    if (!$('#attachment-list li').length) {
      $('div.rightcol').hide();
      $('div.rightcol').hide().attr('aria-hidden', 'true');
      $('div.leftcol').css('margin-right', '0');
    }
  }
@@ -586,75 +551,35 @@
  /**
   * Trigger for popup menus
   */
  function toggle_popup(popup, e, config)
  {
    // auto-register menu object
    if (config || !popupconfig[popup])
      add_popup(popup, config);
    return rcmail.command('menu-open', popup, e.target, e);
  }
  /**
   * (Deprecated) trigger for popup menus
   */
  function show_popup(popup, show, config)
  {
    // auto-register menu object
    if (config || !popupconfig[popup])
      add_popup(popup, config);
    var visible = show_popupmenu(popup, show),
      config = popupconfig[popup];
    if (typeof config.callback == 'function')
      config.callback(visible);
  }
  /**
   * Show/hide a specific popup menu
   */
  function show_popupmenu(popup, show)
  {
    var obj = popups[popup],
      config = popupconfig[popup],
      ref = $(config.link ? config.link : '#'+popup+'link'),
      above = config.above;
    if (!obj) {
      obj = popups[popup] = $('#'+popup);
      obj.appendTo(document.body);  // move them to top for proper absolute positioning
    }
    if (!obj || !obj.length)
      return false;
    if (typeof show == 'undefined')
      show = obj.is(':visible') ? false : true;
    else if (config.toggle && show && obj.is(':visible'))
      show = false;
    if (show && ref.length) {
      var parent = ref.parent(),
        win = $(window),
        pos;
      if (parent.hasClass('dropbutton'))
        ref = parent;
    config = popupconfig[popup] || {};
    var ref = $(config.link ? config.link : '#'+popup+'link'),
      pos = ref.offset();
      ref.offsetHeight = ref.outerHeight();
      if (!above && pos.top + ref.offsetHeight + obj.height() > win.height())
        above = true;
      if (pos.left + obj.width() > win.width())
        pos.left = win.width() - obj.width() - 12;
    if (ref.has('.inner'))
      ref = ref.children('.inner');
      obj.css({ left:pos.left, top:(pos.top + (above ? -obj.height() : ref.offsetHeight)) });
    }
    obj[show?'show':'hide']();
    return show;
  }
  /**
   *
   */
  function target_overlaps(target, elem)
  {
    while (target.parentNode) {
      if (target.parentNode == elem)
        return true;
      target = target.parentNode;
    }
    return false;
    // fire command with simulated mouse click event
    return rcmail.command('menu-open',
      { menu:popup, show:show },
      ref.get(0),
      $.Event('click', { target:ref.get(0), pageX:pos.left, pageY:pos.top, clientX:pos.left, clientY:pos.top }));
  }
@@ -670,7 +595,7 @@
      topstyles, bottomstyles, uid;
    frame.toggle();
    button.removeClass().addClass(visible ? 'enabled' : 'closed');
    button.removeClass().toggleClass('enabled closed').attr('aria-expanded', visible ? 'true' : 'false');
    if (visible) {
      $('#mailview-top').removeClass('fullheight').css({ bottom:'auto' });
@@ -720,9 +645,9 @@
    // add toggle button to full headers table
    if (full.is(':visible'))
      button.attr('href', '#hide').removeClass('add').addClass('remove')
      button.attr('href', '#hide').removeClass('add').addClass('remove').attr('aria-expanded', 'true');
    else
      button.attr('href', '#details').removeClass('remove').addClass('add')
      button.attr('href', '#details').removeClass('remove').addClass('add').attr('aria-expanded', 'false');
    save_pref('previewheaders', full.is(':visible') ? '1' : '0');
  }
@@ -734,25 +659,57 @@
  function switch_view_mode(mode, force)
  {
    if (force || !$('#mail'+mode+'mode').hasClass('disabled')) {
      $('#maillistmode, #mailthreadmode').removeClass('selected');
      $('#mail'+mode+'mode').addClass('selected');
      $('#maillistmode, #mailthreadmode').removeClass('selected').attr('tabindex', '0').attr('aria-disabled', 'false');
      $('#mail'+mode+'mode').addClass('selected').attr('tabindex', '-1').attr('aria-disabled', 'true');
    }
  }
  /**** popup callbacks ****/
  /**** popup menu callbacks ****/
  function menu_open(p)
  /**
   * Handler for menu-open and menu-close events
   */
  function menu_toggle(p)
  {
    if (p && p.props && p.props.menu == 'attachmentmenu')
      show_popupmenu('attachmentmenu');
    else
      show_listoptions();
  }
    if (p && p.name == 'messagelistmenu') {
      show_listoptions(p);
    }
    else if (p) {
      // adjust menu position according to config
      var config = popupconfig[p.name] || {},
        ref = $(config.link || '#'+p.name+'link'),
        visible = p.obj && p.obj.is(':visible'),
        above = config.above;
  function menu_save(prop)
  {
    save_listoptions();
      // fix position according to config
      if (p.obj && visible && ref.length) {
        var parent = ref.parent(),
          win = $(window), pos;
        if (parent.hasClass('dropbutton'))
          ref = parent;
        if (config.above || ref.hasClass('dropbutton')) {
          pos = ref.offset();
          p.obj.css({ left:pos.left+'px', top:(pos.top + (config.above ? -p.obj.height() : ref.outerHeight()))+'px' });
        }
      }
      // add the right classes
      if (p.obj && config.iconized) {
        p.obj.children('ul').addClass('iconized');
      }
      // apply some data-attributes from menu config
      if (p.obj && config.editable)
        p.obj.attr('data-editable', 'true');
      // trigger callback function
      if (typeof config.callback == 'function') {
        config.callback(visible, p);
      }
    }
  }
  function searchmenu(show)
@@ -789,7 +746,7 @@
    }
  }
  function attachmentmenu(elem)
  function attachmentmenu(elem, event)
  {
    var id = elem.parentNode.id.replace(/^attach/, '');
@@ -802,41 +759,44 @@
    });
    popupconfig.attachmentmenu.link = elem;
    rcmail.command('menu-open', {menu: 'attachmentmenu', id: id});
    rcmail.command('menu-open', {menu: 'attachmentmenu', id: id}, elem, event);
  }
  function spellmenu(show)
  function spellmenu(show, p)
  {
    var link, li,
    var k, link, li,
      lang = rcmail.spellcheck_lang(),
      menu = popups.spellmenu,
      ul = $('ul', menu);
      ul = $('ul', p.obj);
    if (!ul.length) {
      ul = $('<ul class="toolbarmenu selectable">');
      ul = $('<ul class="toolbarmenu selectable" role="menu">');
      for (i in rcmail.env.spell_langs) {
        li = $('<li>');
        link = $('<a href="#"></a>').text(rcmail.env.spell_langs[i])
          .addClass('active').data('lang', i)
          .click(function() {
            rcmail.spellcheck_lang_set($(this).data('lang'));
      for (k in rcmail.env.spell_langs) {
        li = $('<li role="menuitem">');
        link = $('<a href="#'+k+'" tabindex="0"></a>').text(rcmail.env.spell_langs[k])
          .addClass('active').data('lang', k)
          .bind('click keypress', function(e) {
              if (e.type != 'keypress' || rcube_event.get_keycode(e) == 13) {
                  rcmail.spellcheck_lang_set($(this).data('lang'));
                  rcmail.hide_menu('spellmenu', e);
                  return false;
              }
          });
        link.appendTo(li);
        li.appendTo(ul);
      }
      ul.appendTo(menu);
      ul.appendTo(p.obj);
    }
    // select current language
    $('li', ul).each(function() {
      var el = $('a', this);
      if (el.data('lang') == lang)
        el.addClass('selected');
        el.addClass('selected').attr('aria-selected', 'true');
      else if (el.hasClass('selected'))
        el.removeClass('selected');
        el.removeClass('selected').removeAttr('aria-selected');
    });
  }
@@ -844,13 +804,13 @@
  /**
   *
   */
  function show_listoptions()
  function show_listoptions(p)
  {
    var $dialog = $('#listoptions');
    // close the dialog
    if ($dialog.is(':visible')) {
      $dialog.dialog('close');
      $dialog.dialog('close', p.originalEvent);
      return;
    }
@@ -869,8 +829,13 @@
      resizable: false,
      closeOnEscape: true,
      title: null,
      close: function() {
      open: function(e) {
        setTimeout(function(){ $dialog.find('a, input:not(:disabled)').not('[aria-disabled=true]').first().focus(); }, 100);
      },
      close: function(e) {
        $dialog.dialog('destroy').hide();
        if (e.originalEvent && rcube_event.is_keyboard(e.originalEvent))
          $('#listmenulink').focus();
      },
      minWidth: 500,
      width: $dialog.width()+25
@@ -881,9 +846,12 @@
  /**
   *
   */
  function save_listoptions()
  function save_listoptions(p)
  {
    $('#listoptions').dialog('close');
    if (rcube_event.is_keyboard(p.originalEvent))
      $('#listmenulink').focus();
    var sort = $('input[name="sort_col"]:checked').val(),
      ord = $('input[name="sort_ord"]:checked').val(),
@@ -982,7 +950,7 @@
      });
  }
  function show_uploadform()
  function show_uploadform(e)
  {
    var $dialog = $('#upload-dialog');
@@ -1008,6 +976,10 @@
      resizable: false,
      closeOnEscape: true,
      title: $dialog.attr('title'),
      open: function(e) {
        if (!document.all)
          $('input[type=file]', $dialog).first().click();
      },
      close: function() {
        try { $('#upload-dialog form').get(0).reset(); }
        catch(e){ }  // ignore errors
@@ -1017,9 +989,6 @@
      },
      width: 480
    }).show();
    if (!document.all)
      $('input[type=file]', $dialog).first().click();
  }
  function add_uploadfile(e)
@@ -1086,47 +1055,35 @@
      content.attr('id', id);
    }
    // first hide not selected tabs
    current = current || 0;
    fs.each(function(idx) { if (idx != current) $(this).hide(); });
    // create tabs container
    var tabs = $('<div>').addClass('tabsbar').prependTo(content);
    var tabs = $('<ul>').addClass('tabsbar').prependTo(content);
    // convert fildsets into tabs
    fs.each(function(idx) {
      var tab, a, elm = $(this), legend = elm.children('legend');
      var tab, a, elm = $(this),
        legend = elm.children('legend'),
        tid = id + '-t' + idx;
      // create a tab
      a   = $('<a>').text(legend.text()).attr('href', '#');
      tab = $('<span>').attr({'id': 'tab'+idx, 'class': 'tablink'})
        .click(function() { show_tab(id, idx); return false })
      a   = $('<a>').text(legend.text()).attr('href', '#' + tid);
      tab = $('<li>').addClass('tablink');
      // remove legend
      legend.remove();
      // style fieldset
      elm.addClass('tab');
      // style selected tab
      if (idx == current)
        tab.addClass('selected');
      // link fieldset with tab item
      elm.attr('id', tid);
      // add the tab to container
      tab.append(a).appendTo(tabs);
    });
  }
  function show_tab(id, index)
  {
    var fs = $('#'+id).children('fieldset');
    fs.each(function(idx) {
      // Show/hide fieldset (tab content)
      $(this)[index==idx ? 'show' : 'hide']();
      // Select/unselect tab
      $('#tab'+idx).toggleClass('selected', idx==index);
    // use jquery UI tabs widget to do the interaction and styling
    content.tabs({
      active: current || 0,
      heightStyle: 'content',
      activate: function(e, ui) {resize(); }
    });
    resize();
  }
  /**
@@ -1237,6 +1194,7 @@
    this.handle = $('<div>')
      .attr('id', this.id)
      .attr('unselectable', 'on')
      .attr('role', 'presentation')
      .addClass('splitter ' + (this.horizontal ? 'splitter-h' : 'splitter-v'))
      .appendTo(this.parent)
      .bind('mousedown', onDragStart);