Merge branch 'dev/elastic'

pull/5578/merge
Aleksander Machniak 6 years ago
commit 70ffc252bf

@ -38,7 +38,7 @@ for file in $PWD/../plugins/*/localization/*.inc; do
done
# remove empty localization files
for file in $PWD/../program/localization/*/{labels,timezones}.inc; do grep -q -E '\$labels' $file || rm $file; done
for file in $PWD/../program/localization/*/labels.inc; do grep -q -E '\$labels' $file || rm $file; done
for file in $PWD/../program/localization/*/timezones.inc; do grep -q -E '\$labels' $file || rm $file; done
for file in $PWD/../program/localization/*/messages.inc; do grep -q -E '\$messages' $file || rm $file; done
for file in $PWD/../plugins/*/localization/*.inc; do grep -q -E '\$(labels|messages)' $file || rm $file; done

@ -313,6 +313,8 @@ class acl extends rcube_plugin
{
// Create username input
$attrib['name'] = 'acluser';
$class = $attrib['class'];
unset($attrib['class']);
$textfield = new html_inputfield($attrib);
@ -340,11 +342,11 @@ class acl extends rcube_plugin
. $val);
}
$out = html::tag('ul', array('id' => 'usertype', 'class' => $attrib['class']), $ul, html::$common_attrib);
$out = html::tag('ul', array('id' => 'usertype', 'class' => $class), $ul, html::$common_attrib);
}
// Display text input alone
else {
$out = $fields['user'];
$out = html::div($class, $fields['user']);
}
return $out;

@ -25,6 +25,7 @@ $labels['keyuserid'] = 'Benutzer ID';
$labels['keytype'] = 'Schlüsseltyp';
$labels['fingerprint'] = 'Fingerprint';
$labels['subkeys'] = 'Sub-Schlüssel';
$labels['keyprops'] = 'Schlüsseleigenschaften';
$labels['basicinfo'] = 'Allgemeine Informationen';
$labels['userids'] = 'Zusätzliche Benutzer';
$labels['typepublickey'] = 'Öffentlicher Schlüssel';
@ -63,18 +64,30 @@ $labels['keydisable'] = 'Deaktivieren';
$labels['keyrevoke'] = 'Widerrufen';
$labels['keysend'] = 'Öffentlichen Schlüssel versenden';
$labels['keychpass'] = 'Passwort ändern';
$labels['newkeyident'] = 'Identität';
$labels['newkeypass'] = 'Passwort';
$labels['newkeypassconfirm'] = 'Passwort bestätigen';
$labels['newkeysize'] = 'Schlüssellänge';
$labels['key2048'] = '2048 bits - standard';
$labels['key4096'] = '4096 bits - sicher';
$labels['keygenerating'] = 'Schlüssel generieren...';
$labels['encryptionoptions'] = 'Verschlüsselungsoptionen';
$labels['encryptmsg'] = 'Diese Nachricht verschlüsseln';
$labels['signmsg'] = 'Diese Nachricht digital signieren';
$labels['sendunencrypted'] = 'Unverschlüsselt senden';
$labels['enterkeypasstitle'] = 'Bitte Schlüssel Passwort eingeben';
$labels['enterkeypass'] = 'Ein Passwort wird benötigt um den privaten Schlüssel ($keyid) für Benutzer: $user zu entsperren';
$labels['arialabelkeyexportoptions'] = 'Optionen für Schlüsselexport';
$labels['attachpubkeymsg'] = 'Meinen öffentlichen Schlüssel anfügen';
$labels['keyexportprompt'] = 'Möchten Sie geheime Schlüssel in die gespeicherte OpenPGP-Schlüsseldatei mit aufnehmen?';
$labels['onlypubkeys'] = 'Nur öffentliche Schlüssel exportieren';
$labels['withprivkeys'] = 'Geheime Schlüssel exportieren';
$labels['findkey'] = 'Auf Schlüsselserver(n) suchen';
$labels['keyimportlabel'] = 'Aus Datei importieren';
$labels['keyimportsearchlabel'] = 'Auf Schlüsselserver(n) suchen';
$labels['managekeys'] = 'PGP-Schlüssel verwalten';
$labels['identitymatchingprivkeys'] = 'Für diesen Absender sind $nr private Schlüssel in Ihrem Schlüsselbund gespeichert:';
$labels['identitynoprivkeys'] = 'Für diesen Absender existiert noch kein PGP Schlüsselpaar in Ihrem Schlüsselbund.';
$messages['sigvalid'] = 'Signatur von $sender wurde erfolgreich überprüft.';
$messages['sigvalidpartial'] = 'Signatur von $sender wurde überprüft, aber ein Teil der Nachricht wurde nicht signiert.';
$messages['siginvalid'] = 'Ungültige Signatur von $sender.';
@ -84,10 +97,12 @@ $messages['sigerror'] = 'Unbestätigte Signatur. Interner Fehler.';
$messages['decryptok'] = 'Nachricht entschlüsselt.';
$messages['decrypterror'] = 'Entschlüsselung fehlgeschlagen.';
$messages['decryptnokey'] = 'Entschlüsselung fehlgeschlagen. Privater Schlüssel wurde nicht gefunden. Schlüssel-ID: $keyid.';
$messages['decryptbadpass'] = 'Entschlüsselung fehlgeschlagen. Passwort ungültig.';
$messages['decryptnopass'] = 'Entschlüsselung fehlgeschlagen. Schlüsselpasswort wird benötigt.';
$messages['decryptpartial'] = 'Nachricht entschlüsselt, aber ein Teil der Nachricht wurde nicht verschlüsselt.';
$messages['signerror'] = 'Signierung fehlgeschlagen.';
$messages['signnokey'] = 'Signierung fehlgeschlagen. Privater Schlüssel wurde nicht gefunden.';
$messages['signbadpass'] = 'Signierung fehlgeschlagen. Passwort ungültig.';
$messages['signnopass'] = 'Signierung fehlgeschlagen. Schlüsselpasswort wird benötigt.';
$messages['encrypterror'] = 'Verschlüsselung fehlgeschlagen.';
$messages['encryptnokey'] = 'Verschlüsselung fehlgeschlagen. Öffentlicher Schlüssel für $email nicht gefunden';
@ -102,10 +117,12 @@ $messages['keyremoveconfirm'] = 'Bist du dir sicher, dass du die ausgewählten S
$messages['keyremovesuccess'] = 'Schlüssel erfolgreich gelöscht.';
$messages['keyremoveerror'] = 'Löschung der Schlüssel nicht möglich.';
$messages['keyimporttext'] = 'Private und öffentliche Schlüssel sowie zurückgerufene Signaturen können im ASCII-Armor Format importiert werden.';
$messages['keyimportsearchtext'] = 'Sie können für öffentliche Schlüssel nach dem Schlüsselbezeichner, Benutzername oder der E-Mail-Adresse suchen und diese dann direkt importieren.';
$messages['formerror'] = 'Bitte, alle Eingabefelder ausfüllen. Alle Eingabefelder werden benötigt!';
$messages['passwordsdiffer'] = 'Passwörter stimmen nicht überein.';
$messages['keygenerateerror'] = 'Schlüsselgenerierung fehlgeschlagen.';
$messages['keygeneratesuccess'] = 'Schlüsselpaar erfolgreich generiert und importiert.';
$messages['keygennosupport'] = 'Dein Browser unterstützt keine Kryptopgraphiefunktionen. Konnte Schlüsselpaar nicht generieren!';
$messages['noidentselected'] = 'Sie müssen mindestens eine Identität für den Schlüssel auswählen!';
$messages['nonameident'] = 'Identität muss einen Benutzernamen definiert haben.';
?>

@ -85,6 +85,9 @@ $labels['withprivkeys'] = 'Geheime Schlüssel exportieren';
$labels['findkey'] = 'Auf Schlüsselserver(n) suchen';
$labels['keyimportlabel'] = 'Aus Datei importieren';
$labels['keyimportsearchlabel'] = 'Auf Schlüsselserver(n) suchen';
$labels['managekeys'] = 'PGP-Schlüssel verwalten';
$labels['identitymatchingprivkeys'] = 'Sie haben $nr passende private Schlüssel in Ihrem Schlüsselverzeichnis:';
$labels['identitynoprivkeys'] = 'Für diese Absender-Identität ist bis jetzt kein privater PGP-Schlüsselverzeichnis gespeichert.';
$messages['sigvalid'] = 'Signatur von $sender wurde erfolgreich überprüft.';
$messages['sigvalidpartial'] = 'Signatur von $sender wurde überprüft, aber ein Teil der Nachricht wurde nicht signiert.';
$messages['siginvalid'] = 'Ungültige Signatur von $sender.';

@ -7,14 +7,16 @@
<!-- keys list -->
<div class="list listbox selected" aria-labelledby="aria-label-enigmakeyslist">
<div class="header">
<a class="button icon menu-button" href="#menu"><span class="inner"><roundcube:label name="menu" /></span></a>
<a class="button icon back-sidebar-button" href="#sidebar"><span class="inner"><roundcube:label name="settings" /></span></a>
<span id="aria-label-enigmakeyslist" class="header-title"><roundcube:label name="enigma.enigmakeys" /></span>
<roundcube:object name="searchform" id="keysearch" wrapper="searchbar toolbar"
label="keysearchform" buttontitle="findkeys" ariatag="h2" />
<a class="button icon toolbar-menu-button" href="#list-menu"><span class="inner"><roundcube:label name="menu" /></span></a>
</div>
<div class="pagenav toolbar" role="toolbar">
<roundcube:object name="searchform" id="keysearch" wrapper="searchbar toolbar"
label="keysearchform" buttontitle="findkeys" ariatag="h2" />
<div class="scroller">
<roundcube:object name="keyslist" id="keys-table" class="listing" role="listbox" noheader="true" data-list="keys_list" />
</div>
<div class="pagenav footer toolbar small" role="toolbar">
<roundcube:button command="firstpage" type="link"
class="button firstpage disabled" classAct="button firstpage"
title="firstpage" label="first" innerclass="inner" />
@ -32,9 +34,6 @@
class="button lastpage disabled" classAct="button lastpage"
title="lastpage" label="last" innerclass="inner" />
</div>
<div class="scroller">
<roundcube:object name="keyslist" id="keys-table" class="listing" role="listbox" noheader="true" data-list="keys_list" />
</div>
</div>
<!-- key info frame -->

@ -18,5 +18,5 @@
$labels['help'] = 'Hilfe';
$labels['about'] = 'Über';
$labels['license'] = 'Lizenz';
$labels['csrfinfo'] = 'Erfahren Sie mehr über CSRF und wie wir Sie schützen';
$labels['csrfinfo'] = 'Mehr über CSRF und wie wir Sie schützen lesen';
?>

@ -15,8 +15,6 @@
For translation see https://www.transifex.com/projects/p/roundcube-webmail/resource/plugin-managesieve/
*/
$labels['filters'] = 'Filter';
$labels['managefilters'] = 'Verwalte eingehende Nachrichtenfilter';
$labels['filtername'] = 'Filtername';
@ -222,8 +220,6 @@ $labels['duplicate.header'] = 'Kopfzeile:';
$labels['duplicate.uniqueid'] = 'Bezeichner:';
$labels['duplicate.seconds'] = 'Zeitüberschreitung (Sekunden):';
$labels['duplicate.last'] = 'relativ zur letzten Ausführung';
$messages = array();
$messages['filterunknownerror'] = 'Unbekannter Serverfehler';
$messages['filterconnerror'] = 'Kann nicht zum Sieve-Server verbinden';
$messages['filterdeleteerror'] = 'Serverfehler beim Löschen des Filters.';
@ -264,5 +260,4 @@ $messages['forwardsaved'] = 'Weiterleitungsdaten erfolgreich gespeichert.';
$messages['emptyvacationbody'] = 'Mitteilungstext ist erforderlich!';
$messages['duplicate.conflict.err'] = 'Kopfzeile und eindeutiger Bezeichner sind nicht zusammen erlaubt.';
$messages['disabledaction'] = 'Aktion nicht erlaubt.';
?>

@ -15,8 +15,6 @@
For translation see https://www.transifex.com/projects/p/roundcube-webmail/resource/plugin-managesieve/
*/
$labels['filters'] = 'Filter';
$labels['managefilters'] = 'Filter für eingehende Nachrichten verwalten';
$labels['filtername'] = 'Filtername';
@ -183,8 +181,8 @@ $labels['vacation.advanced'] = 'Erweiterte Einstellungen';
$labels['vacation.from'] = 'Antwort E-Mail-Adresse:';
$labels['vacation.subject'] = 'Betreff';
$labels['vacation.body'] = 'Nachricht';
$labels['vacation.start'] = 'Beginn des Abwesenheit';
$labels['vacation.end'] = 'Ende des Abwesenheit';
$labels['vacation.start'] = 'Beginn der Abwesenheit';
$labels['vacation.end'] = 'Ende der Abwesenheit';
$labels['vacation.status'] = 'Status';
$labels['vacation.on'] = 'An';
$labels['vacation.off'] = 'Aus';
@ -222,8 +220,6 @@ $labels['duplicate.header'] = 'Kopfzeile:';
$labels['duplicate.uniqueid'] = 'Bezeichner:';
$labels['duplicate.seconds'] = 'Zeitüberschreitung (Sekunden):';
$labels['duplicate.last'] = 'relativ zur letzten Ausführung';
$messages = array();
$messages['filterunknownerror'] = 'Unbekannter Serverfehler';
$messages['filterconnerror'] = 'Kann keine Verbindung mit Managesieve-Server herstellen';
$messages['filterdeleteerror'] = 'Filter kann nicht gelöscht werden. Ein Serverfehler ist aufgetreten.';
@ -264,5 +260,4 @@ $messages['forwardsaved'] = 'Weiterleitungsdaten erfolgreich gespeichert.';
$messages['emptyvacationbody'] = 'Inhalt der Abwesenheitsbenachrichtigung wird benötigt!';
$messages['duplicate.conflict.err'] = 'Beides, Kopfzeilen und eindeutige Kennzeichner, sind nicht erlaubt.';
$messages['disabledaction'] = 'Aktion nicht erlaubt.';
?>

@ -20,3 +20,4 @@ $labels['download'] = 'Download...';
$labels['downloadmbox'] = 'Mbox Format (.zip)';
$labels['downloadmaildir'] = 'Maildir Format (.zip)';
$labels['downloademl'] = 'Source (.eml)';
$labels['sizelimiterror'] = 'Die gesamte Grösse der ausgewählten Nachrichten übersteigt das Limit ($size)';

@ -20,3 +20,4 @@ $labels['download'] = 'Herunterladen...';
$labels['downloadmbox'] = 'Mbox-Format (.zip)';
$labels['downloadmaildir'] = 'Maildir-Format (.zip)';
$labels['downloademl'] = 'Quelltext (.eml)';
$labels['sizelimiterror'] = 'Die gesamte Größe der ausgewählten Nachrichten übersteigt das Limit ($size)';

@ -94,6 +94,14 @@ class rcmail_output_html extends rcmail_output
$this->set_env('cookie_path', ini_get('session.cookie_path'));
$this->set_env('cookie_secure', filter_var(ini_get('session.cookie_secure'), FILTER_VALIDATE_BOOLEAN));
// Easy way to change skin via GET argument, for developers
if ($this->devel_mode && !empty($_GET['skin']) && preg_match('/^[a-z0-9-_]+$/i', $_GET['skin'])) {
if ($this->check_skin($_GET['skin'])) {
$this->set_skin($_GET['skin']);
$this->app->user->save_prefs(array('skin' => $_GET['skin']));
}
}
// load and setup the skin
$this->set_skin($this->config->get('skin'));
$this->set_assets_path($this->config->get('assets_path'), $this->config->get('assets_dir'));
@ -514,7 +522,7 @@ EOF;
/**
* Send the request output to the client.
* This will either parse a skin tempalte or send an AJAX response
* This will either parse a skin template.
*
* @param string $templ Template name
* @param boolean $exit True if script should terminate (default)
@ -2177,7 +2185,7 @@ EOF;
'title' => 'options',
'tabindex' => '0',
'innerclass' => 'inner',
'data-popup' => $attrib['options']
'data-target' => $attrib['options']
));
}
@ -2202,10 +2210,10 @@ EOF;
));
$out = html::div(array(
'role' => 'search',
'aria-labelledby' => $attrib['label'] ? 'aria-label-' . $attrib['label'] : null,
'class' => $attrib['wrapper'],
), "$header$out\n$options_button\n$reset_button\n$search_button");
'role' => 'search',
'aria-labelledby' => $attrib['label'] ? 'aria-label-' . $attrib['label'] : null,
'class' => $attrib['wrapper'],
), "$header$out\n$reset_button\n$options_button\n$search_button");
}
return $out;

@ -407,34 +407,7 @@ insert_row: function(row, before)
}
if (this.checkbox_selection) {
var key, cell = document.createElement(this.col_tagname()),
chbox = document.createElement('input');
chbox.type = 'checkbox';
chbox.tabIndex = -1;
chbox.onchange = function(e) {
self.select_row(row.uid, key || CONTROL_KEY, true);
e.stopPropagation();
key = null;
};
chbox.onmousedown = function(e) {
key = rcube_event.get_modifier(e);
};
cell.className = 'selection';
// make the whole cell "touchable" for touch devices
cell.onclick = function(e) {
if (!$(e.target).is('input')) {
key = rcube_event.get_modifier(e);
$(chbox).prop('checked', !chbox.checked).change();
}
e.stopPropagation();
};
cell.appendChild(chbox);
row.insertBefore(cell, row.firstChild);
this.insert_checkbox(row);
}
if (before && tbody.childNodes.length)
@ -451,7 +424,7 @@ insert_row: function(row, before)
},
/**
*
* Update existing record
*/
update_row: function(id, cols, newid, select)
{
@ -477,6 +450,60 @@ update_row: function(id, cols, newid, select)
}
},
/**
* Add selection checkbox to the list record
*/
insert_checkbox: function(row)
{
var key, self = this,
cell = document.createElement(this.col_tagname()),
chbox = document.createElement('input');
chbox.type = 'checkbox';
chbox.tabIndex = -1;
chbox.onchange = function(e) {
self.select_row(row.uid, key || CONTROL_KEY, true);
e.stopPropagation();
key = null;
};
chbox.onmousedown = function(e) {
key = rcube_event.get_modifier(e);
};
cell.className = 'selection';
// make the whole cell "touchable" for touch devices
cell.onclick = function(e) {
if (!$(e.target).is('input')) {
key = rcube_event.get_modifier(e);
$(chbox).prop('checked', !chbox.checked).change();
}
e.stopPropagation();
};
cell.appendChild(chbox);
row.insertBefore(cell, row.firstChild);
},
/**
* Enable checkbox selection
*/
enable_checkbox_selection: function()
{
this.checkbox_selection = true;
// Add checkbox to existing records if any
var r, len, cell, row_tag = this.row_tagname().toUpperCase(),
rows = this.tbody.childNodes;
for (r=0, len=rows.length; r<len; r++) {
if (rows[r].nodeName == row_tag && (cell = rows[r].firstChild)) {
if (cell.className == 'selection')
break;
this.insert_checkbox(rows[r]);
}
}
},
/**
* Set focus to the list

@ -425,7 +425,6 @@ $labels['importreplace'] = 'Bestehendes Adressbuch komplett ersetzen';
$labels['importgroups'] = 'Gruppenzuweisungen importieren';
$labels['importgroupsall'] = 'Alle (nicht vorhandene Gruppen erstellen)';
$labels['importgroupsexisting'] = 'Für existierende Gruppen';
$labels['importdesc'] = 'Sie können Kontakte aus einem bestehenden Adressbuch hochladen.rnEs können Adressbücher im <a href="http://de.wikipedia.org/wiki/VCard">vCard</a>- oder CSV-Format importiert werden.';
$labels['done'] = 'Fertig';
$labels['settingsfor'] = 'Einstellungen für';
$labels['about'] = 'Über';

@ -34,7 +34,6 @@ $messages['erroroverquotadelete'] = 'Kein freier Speicherplatz. Drücken Sie SHI
$messages['invalidrequest'] = 'Ungültige Anfrage! Es wurden keine Daten gespeichert.';
$messages['invalidhost'] = 'Ungültiger Servername';
$messages['nomessagesfound'] = 'Keine Nachrichten in diesem Ordner';
$messages['loggedout'] = 'Sie haben Ihre Session erfolgreich beendet. Auf Wiedersehen!';
$messages['mailboxempty'] = 'Ordner ist leer';
$messages['nomessages'] = 'Keine Nachrichten';
$messages['refreshing'] = 'Aktualisiere...';

@ -107,14 +107,14 @@ $labels['compose'] = 'Schreiben';
$labels['writenewmessage'] = 'Neue Nachricht schreiben';
$labels['reply'] = 'Antworten';
$labels['replytomessage'] = 'Antwort verfassen';
$labels['replytoallmessage'] = 'Antwort an Mailingliste oder an Absender und alle Empfänger verfassen';
$labels['replytoallmessage'] = 'Antwort an Liste oder an Absender und alle Empfänger verfassen';
$labels['replyall'] = 'Allen antworten';
$labels['replylist'] = 'Liste antworten';
$labels['forward'] = 'Weiterleiten';
$labels['forwardinline'] = 'innerhalb der Nachricht';
$labels['forwardattachment'] = 'Als Anhang weiterleiten';
$labels['forwardmessage'] = 'Nachricht weiterleiten';
$labels['bouncemsg'] = 'Resend (bounce)';
$labels['bouncemsg'] = 'Erneut senden (falls unzustellbar)';
$labels['bounce'] = 'Erneut senden';
$labels['deletemessage'] = 'Nachricht löschen';
$labels['movemessagetotrash'] = 'Nachricht in den Papierkorb verschieben';
@ -129,8 +129,8 @@ $labels['mark'] = 'Markieren';
$labels['markmessages'] = 'Nachrichten markieren';
$labels['markread'] = 'Als gelesen';
$labels['markunread'] = 'Als ungelesen';
$labels['markflagged'] = 'Markierung hinzufügen';
$labels['markunflagged'] = 'Markierung entfernen';
$labels['markflagged'] = 'Als wichtig';
$labels['markunflagged'] = 'Als unwichtig';
$labels['moreactions'] = 'Mehr …';
$labels['markallread'] = 'Alle als gelesen markieren';
$labels['folders-cur'] = 'Nur ausgewählten Ordner';
@ -152,8 +152,8 @@ $labels['none'] = 'Keine';
$labels['currpage'] = 'Aktuelle Seite';
$labels['isread'] = 'Gelesen';
$labels['unread'] = 'Ungelesene';
$labels['flagged'] = 'Markierte';
$labels['unflagged'] = 'Nicht gekennzeichnet';
$labels['flagged'] = 'Als wichtig markiert';
$labels['unflagged'] = 'Als unwichtig markiert';
$labels['unanswered'] = 'Unbeantwortete';
$labels['withattachment'] = 'Mit Anhang';
$labels['deleted'] = 'Gelöschte';
@ -180,21 +180,22 @@ $labels['arrival'] = 'Empfangsdatum';
$labels['asc'] = 'aufsteigend';
$labels['desc'] = 'absteigend';
$labels['listcolumns'] = 'Spalten';
$labels['listsorting'] = 'Sortierung';
$labels['listorder'] = 'Ordnung';
$labels['listsorting'] = 'Sortieren nach';
$labels['listorder'] = 'Sortierung';
$labels['listmode'] = 'Anzeigemodus';
$labels['lmode'] = 'Listen-Modus';
$labels['lmode'] = 'Listenmodus';
$labels['layout'] = 'Layout';
$labels['layoutwidescreen'] = 'Breitbildschirm';
$labels['layoutdesktop'] = 'Desktop';
$labels['layoutdesktop'] = 'Schreibtisch';
$labels['layoutlist'] = 'Liste';
$labels['layoutwidescreendesc'] = 'Breitbild (3-Spalten-Ansicht)';
$labels['layoutdesktopdesc'] = 'Desktop (breite Liste und Mail-Vorschau unten)';
$labels['layoutlistdesc'] = 'Liste (keine Mail-Vorschau)';
$labels['layoutdesktopdesc'] = 'Schreibtisch (breite Liste und Nachrichtenvorschau unten)';
$labels['layoutlistdesc'] = 'Liste (keine Nachrichtenvorschau)';
$labels['folderactions'] = 'Ordneraktionen …';
$labels['compact'] = 'Packen';
$labels['empty'] = 'Leeren';
$labels['importmessages'] = 'Nachrichten importieren';
$labels['mailimportzip'] = 'Mehrere Dateien können zu ZIP-Archiven komprimiert werden.';
$labels['quota'] = 'Speicherplatz';
$labels['unknown'] = 'unbekannt';
$labels['unlimited'] = 'unbegrenzt';
@ -204,8 +205,8 @@ $labels['quotaused'] = 'Verwendet';
$labels['quotastorage'] = 'Festplattenspeicher';
$labels['quotamessage'] = 'Nachrichtenanzahl';
$labels['shortheaderdate'] = 'Am $date';
$labels['shortheaderto'] = 'An $to vom $date';
$labels['shortheaderfrom'] = 'Von $from vom $date';
$labels['shortheaderto'] = 'An $to am $date';
$labels['shortheaderfrom'] = 'Von $from am $date';
$labels['quicksearch'] = 'Schnellsuche';
$labels['searchplaceholder'] = 'Suchen …';
$labels['resetsearch'] = 'Suche zurücksetzen';
@ -248,6 +249,7 @@ $labels['encryptmessage'] = 'Nachrichten verschlüsseln';
$labels['encryptmessagemailvelope'] = 'Nachricht mit Mailvelope verschlüsseln';
$labels['importpubkeys'] = 'Öffentliche Schlüssel importieren';
$labels['encryptedsendialog'] = 'Verschlüsselte Nachricht wird gesendet';
$labels['encryptandsign'] = 'Verschlüsseln und unterschreiben';
$labels['keyid'] = 'Schlüsselkennung';
$labels['keylength'] = 'Bits';
$labels['keyexpired'] = 'Abgelaufen';
@ -255,6 +257,7 @@ $labels['keyrevoked'] = 'Widerrufen';
$labels['bccinstead'] = 'Blindkopie verwenden';
$labels['addheader'] = 'Empfänger hinzufügen (Kopfzeile)';
$labels['recipient'] = 'Empfänger';
$labels['recipientedit'] = 'Empfänger bearbeiten';
$labels['editidents'] = 'Identitäten bearbeiten';
$labels['spellcheck'] = 'Rechtschreibung';
$labels['checkspelling'] = 'Rechtschreibung prüfen';
@ -272,7 +275,7 @@ $labels['editresponse'] = 'Schnellantwort bearbeiten';
$labels['editresponses'] = 'Schnellantworten bearbeiten';
$labels['responsename'] = 'Name';
$labels['responsetext'] = 'Text der Antwort';
$labels['attach'] = 'Anhängen';
$labels['attach'] = 'Anhang';
$labels['attachments'] = 'Anhänge';
$labels['upload'] = 'Hochladen';
$labels['uploadprogress'] = '$percent ($current von $total)';
@ -309,6 +312,14 @@ $labels['mdnrequest'] = 'Der Sender dieser Nachricht möchte gerne eine Lesebest
$labels['receiptread'] = 'Empfangsbestätigung (gelesen)';
$labels['yourmessage'] = 'Dies ist eine Empfangsbestätigung für Ihre Nachricht';
$labels['receiptnote'] = 'Hinweis: Der Empfänger hat den Empfang der Nachricht bestätigt. Dies ist keine Garantie, dass die Nachricht gelesen und verstanden wurde.';
$labels['zoomin'] = 'Vergrößern';
$labels['zoomout'] = 'Verkleinern';
$labels['rotate'] = 'Drehen';
$labels['increaseimage'] = 'Bild vergrößern';
$labels['decreaseimage'] = 'Bild verkleinern';
$labels['rotateimage'] = 'Bild drehen';
$labels['showtools'] = 'Bild-Tools anzeigen';
$labels['hidetools'] = 'Bild-Tools ausblenden';
$labels['name'] = 'Angezeigter Name';
$labels['firstname'] = 'Vorname';
$labels['surname'] = 'Nachname';
@ -393,7 +404,7 @@ $labels['newgroup'] = 'Neue Gruppe erstellen';
$labels['addgroup'] = 'Gruppe hinzufügen';
$labels['grouprename'] = 'Gruppe umbenennen';
$labels['groupdelete'] = 'Gruppe löschen';
$labels['groupassign'] = 'Zur Gruppe hinzufügen...';
$labels['groupassign'] = 'Zu Gruppe hinzufügen...';
$labels['groupremove'] = 'Aus Gruppe entfernen';
$labels['groupremoveselected'] = 'Gewählte Kontakte aus Gruppe entfernen';
$labels['uponelevel'] = 'Eine Ebene nach oben';
@ -415,7 +426,6 @@ $labels['importreplace'] = 'Bestehendes Adressbuch komplett ersetzen';
$labels['importgroups'] = 'Gruppenzuordnungen importieren';
$labels['importgroupsall'] = 'Alle (Gruppen erstellen wenn nötig)';
$labels['importgroupsexisting'] = 'Nur für existierende Gruppen';
$labels['importdesc'] = 'Sie können Kontakte von einem vorhandenen Adressbuch hochladen.<br/>Zur Zeit wird der Import von Adressen im <a href="http://de.wikipedia.org/wiki/VCard">vCard</a> oder <a href="http://de.wikipedia.org/wiki/CSV_(Dateiformat)">CSV</a>Format unterstützt.';
$labels['done'] = 'Fertig';
$labels['settingsfor'] = 'Einstellungen für';
$labels['about'] = 'Über';
@ -562,7 +572,11 @@ $labels['namespace.shared'] = 'Geteilt';
$labels['dualuselabel'] = 'Kann nur enthalten';
$labels['dualusemail'] = 'Nachrichten';
$labels['dualusefolder'] = 'Ordner';
$labels['generate'] = 'Generieren';
$labels['encryptioncreatekey'] = 'Neues Schlüsselpaar erstellen';
$labels['openmailvelopesettings'] = 'Mailvelope-Einstellungen öffnen';
$labels['encryptionprivkeysinmailvelope'] = 'Sie haben $nr passende private Schlüssel in Ihrem Mailvelope-Schlüsselverzeichnis:';
$labels['encryptionnoprivkeysinmailvelope'] = 'Für diese Absender-Identität ist bis jetzt kein privater PGP-Schlüssel in Ihrer Mailvelope gespeichert. Wollen Sie einen Schlüssel erstellen, damit eine verschlüsselte Kommunikation möglich ist?';
$labels['sortby'] = 'Sortieren nach';
$labels['sortasc'] = 'Aufsteigend sortieren';
$labels['sortdesc'] = 'Absteigend sortieren';
@ -630,6 +644,7 @@ $labels['arialabelmessageheaders'] = 'Nachrichtenkopfzeilen';
$labels['arialabelforwardingoptions'] = 'Weiterleitungsoptionen';
$labels['arialabelreplyalloptions'] = 'Allen antworten-Optionen';
$labels['arialabelmoremessageactions'] = 'Weitere Nachrichtenaktionen';
$labels['arialabelmorecontactactions'] = 'Weitere Kontakt-Aktionen';
$labels['arialabelmarkmessagesas'] = 'Ausgewählte Nachricht markieren als …';
$labels['arialabelcomposeoptions'] = 'Erstellungsoptionen';
$labels['arialabelresponsesmenu'] = 'Schnellantworten Menü';
@ -646,6 +661,7 @@ $labels['arialabelresonseeditfrom'] = 'Antwortbearbeitungsformular';
$labels['arialabelsearchterms'] = 'Suchbegriffe';
$labels['arialabeldropactionmenu'] = 'Aktionsmenü für das Ziehen und Loslassen';
$labels['arialabelheadersmenu'] = 'Menü zum Hinzufügen der Empfänger (Kopfzeile) ';
$labels['arialabelimagetools'] = 'Bild-Tools';
$labels['helplistnavigation'] = 'Tastaturnavigation auflisten';
$labels['helplistkeyboardnavigation'] = "Pfeil hoch/runter: Zeilenfokus/Zeilenselektion verschieben
Leerzeichen: Selektiere ausgewählte Zeile

@ -83,6 +83,7 @@ $messages['deletecontactconfirm'] = 'Wollen Sie die ausgewählten Kontakte wirk
$messages['deletegroupconfirm'] = 'Wollen Sie die gewählte Gruppe wirklich löschen?';
$messages['deletemessagesconfirm'] = 'Wollen Sie die ausgewählten Nachrichten wirklich löschen?';
$messages['deletefolderconfirm'] = 'Wollen Sie diesen Ordner wirklich löschen?';
$messages['movefolderconfirm'] = 'Wollen Sie diesen Ordner wirklich verschieben?';
$messages['purgefolderconfirm'] = 'Wollen Sie diesen Ordner wirklich leeren?';
$messages['contactdeleting'] = 'Kontakt(e) werden gelöscht …';
$messages['groupdeleting'] = 'Gruppe wird gelöscht …';
@ -164,7 +165,8 @@ $messages['smtpconnerror'] = 'SMTP Fehler ($code): Die Verbindung ist fehlgeschl
$messages['smtpautherror'] = 'SMTP Fehler ($code): Die Authentisierung ist fehlgeschlagen.';
$messages['smtpfromerror'] = 'SMTP Fehler ($code): Der Absender "$from" konnte nicht gesetzt werden ($msg).';
$messages['smtptoerror'] = 'SMTP Fehler ($code): Der Empfänger "$to" konnte nicht gesetzt werden ($msg).';
$messages['smtprecipientserror'] = 'SMTP Fehler: Die Empfängerliste konnte nicht verarbeitet werden.';
$messages['smtprecipientserror'] = 'SMTP-Fehler: die Empfängerliste konnte nicht verarbeitet werden.';
$messages['smtputf8error'] = 'SMTP-Fehler: Der Server unterstützt Unicode in der E-Mail-Adresse nicht.';
$messages['smtpsizeerror'] = 'SMTP-Fehler: Nachrichtengröße übersteigt die Servergrenze ($limit)';
$messages['smtperror'] = 'SMTP Fehler: $msg';
$messages['emailformaterror'] = 'Ungültige E-Mail-Adresse: $email';
@ -214,3 +216,8 @@ $messages['errcomposesession'] = 'Verfasssitzungsfehler';
$messages['errcomposesessionexplain'] = 'Angeforderte Verfasssitzung nicht gefunden.';
$messages['clicktocompose'] = 'Klicken Sie hier, um eine neue Nachricht zu verfassen';
$messages['nosupporterror'] = 'Diese Funktion wird von Ihrem Webbrowser nicht unterstützt.';
$messages['siginserted'] = 'Signatur erfolgreich eingefügt.';
$messages['responseinserted'] = 'Antwort erfolgreich eingefügt.';
$messages['listempty'] = 'Die Liste ist leer.';
$messages['listusebutton'] = 'Um einen neuen Datensatz hinzufügen, verwenden Sie bitte die Schaltfläche \'Erstellen\'.';
$messages['keypaircreatesuccess'] = 'En neues Schlüsselpaar wurde erfolgreich für $identity erstellt.';

@ -173,6 +173,7 @@ $labels['last'] = 'Last';
$labels['previous'] = 'Previous';
$labels['next'] = 'Next';
$labels['select'] = 'Select';
$labels['selection'] = 'Selection';
$labels['all'] = 'All';
$labels['none'] = 'None';
$labels['currpage'] = 'Current page';
@ -335,8 +336,9 @@ $labels['alwaysshow'] = 'Always show images from $sender';
$labels['alwaysallow'] = 'Always allow from $sender';
$labels['isdraft'] = 'This is a draft message.';
$labels['andnmore'] = '$nr more...';
$labels['details'] = 'Details';
$labels['headers'] = 'Headers';
$labels['envelope'] = 'Envelope';
$labels['allheaders'] = 'All headers...';
$labels['togglemoreheaders'] = 'Show more message headers';
$labels['togglefullheaders'] = 'Toggle raw message headers';

@ -157,7 +157,7 @@ function rcmail_user_prefs($current = null)
$no_override = array_flip((array)$RCMAIL->config->get('dont_override'));
foreach ($sections as $idx => $sect) {
$sections[$idx]['class'] = $idx;
$sections[$idx]['class'] = $sect['class'] ?: $idx;
if ($current && $sect['id'] != $current) {
continue;

@ -93,7 +93,7 @@ FOR DEVELOPERS
Can be used for example for functionality not implemented or that has no sense
on phones or touch devices. Contains a comma-separated list following values:
`large` (width > 1200px), `big` (width > 768px), `small` (width =< 768px),
`phone` (width =< 480px).
`phone` (width =< 480px), `lbs` (width > 480px).
- `data-content-button`: Makes the action button with this attribute to be copied
to the content frame header on small/phone screens.

@ -0,0 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 960 560">
<path fill="#d4dbde" d="M690 245c0 9.2-3.5 17.9-10.1 24.9l-175 175c-6.6 6.6-15.3 10.1-24.9 10.1-9.2 0-18.4-3.5-24.9-10.1l-175-175c-6.6-7-10.1-15.8-10.1-24.9 0-4.4.9-9.2 2.6-13.6C277.9 218.3 291 210 305 210h87.5V35c0-19.2 15.8-35 35-35h105c19.2 0 35 15.8 35 35v175H655c14 0 27.1 8.3 32.4 21.4 1.7 4.4 2.6 9.2 2.6 13.6zm0 245H270V350h-70v140c0 38.5 31.5 70 70 70h420c38.5 0 70-31.5 70-70V350h-70v140z"/>
</svg>

After

Width:  |  Height:  |  Size: 472 B

@ -32,9 +32,11 @@
@color-layout-sidebar-background: #fff;
@color-layout-list-background: #fff;
@color-layout-content-background: #fff;
@color-layout-header-background: #fff;
@color-layout-header-background: #f4f4f4;
@color-layout-footer-background: #fff;
@color-layout-mobile-header-background: @color-layout-header-background;
@color-layout-mobile-footer-background: @color-layout-header-background;
// Task menu
@color-taskmenu-background: #414e54;
@ -60,10 +62,10 @@
// Toolbar
@color-toolbar-button: @color-font;
@color-toolbar-button-background-hover: tint(@color-main, 96%);
@color-toolbar-button-background-hover: darken(@color-layout-header-background, 3%);
@color-searchbar-icon-active: green;
@color-searchbar-background: #fbfbfb;
// Toolbar menu
@color-toolbarmenu-hover: #fff;
@ -91,7 +93,6 @@
@color-list-icon: fadeout(@color-list-secondary, 25%);
// Drag-n-drop layer
@color-drag-layer: #fff;
@color-drag-layer-background: @color-taskmenu-background;
@ -163,7 +164,7 @@
@color-btn-danger: #fff;
@color-btn-danger-background: @color-error;
@color-quota-background: @color-black-shade-bg;
@color-quota-background: #fff;
@color-quota-text: @color-black-shade-text;
@color-quota-value: @color-main;
@color-quota-value-warning: @color-error;

@ -55,13 +55,6 @@ body > #layout {
flex-direction: column;
max-width: 30%;
border-right: 1px solid @color-layout-border;
& > .header {
a.button {
margin: 0;
padding: 0 .5rem;
}
}
}
&.content {
@ -105,6 +98,7 @@ body > #layout {
min-width: 300px;
background-color: @color-layout-list-background;
}
& > .scroller {
flex: 1;
position: relative; // for .listing-info positioning
@ -141,11 +135,25 @@ body > #layout {
text-align: center;
margin: 0 -20rem;
}
a.toolbar-list-button,
a.toolbar-menu-button {
order: 99; // always the last button
}
}
& > .footer {
border-top: 1px solid @color-layout-border;
background-color: @color-layout-footer-background;
height: @layout-footer-height;
min-height: @layout-footer-height;
line-height: @layout-footer-height;
&.small {
height: @layout-footer-small-height;
min-height: @layout-footer-small-height;
line-height: @layout-footer-small-height;
}
&:empty {
display: none;
@ -171,6 +179,11 @@ html.iframe {
min-width: 260px;
flex: 3;
}
body > #layout > div.list > .header > a.button {
padding: 0 .25rem;
margin: 0 .25rem;
}
}
@media screen and (max-width: @screen-width-medium) {
@ -184,6 +197,8 @@ html.iframe {
}
body > #layout > div > .header {
background-color: @color-layout-mobile-header-background;
a.button {
// make the button active area smaller on touch devices
margin: 0 .3rem !important;
@ -205,16 +220,12 @@ html.iframe {
}
}
body > #layout > div > .header {
&.with-search:not(.no-toolbar) {
.searchbar {
right: @layout-touch-icon-width;
}
body > #layout > div > .footer {
background-color: @color-layout-mobile-footer-background;
}
.searchfilterbar {
right: (@layout-touch-icon-width * 2);
}
}
a.toolbar-list-button {
display: none;
}
}
@ -229,7 +240,7 @@ html.iframe {
}
@media screen and (min-width: (@screen-width-xs + 1px)) {
body > #layout > div > .header > a.menu-button {
a.menu-button {
display: none;
}
@ -244,7 +255,7 @@ html.iframe {
.floating-action-buttons,
body > #layout > .content > .header > .header-title,
body > #layout > div > .header > .buttons,
body > #layout > div > .header > a.toolbar-menu-button {
a.toolbar-menu-button {
display: none;
}
@ -260,8 +271,10 @@ html.iframe {
}
@media screen and (min-width: (@screen-width-large + 1px)) {
body > #layout > div > .header > a.back-list-button,
body > #layout > div > .header > a.back-sidebar-button {
body > #layout > .list > .header > .header-title:not(.all-sizes),
a.toolbar-list-button,
a.back-list-button,
a.back-sidebar-button {
display: none;
}
}
@ -279,8 +292,15 @@ html.layout-small {
}
}
html.layout-small {
.hidden-lbs {
display: none !important;
}
}
html.layout-large,
html.layout-normal {
.hidden-lbs,
.hidden-big {
display: none !important;
}

@ -124,7 +124,6 @@ a {
@import "widgets/taskmenu";
@import "widgets/messages";
@import "widgets/toolbar";
@import "widgets/searchbar";
@import "widgets/lists";
@import "widgets/forms";
@import "widgets/editor";

@ -26,8 +26,10 @@
@layout-menu-width: 5rem;
@layout-header-height: 4.2rem;
@layout-footer-height: @layout-header-height;
@layout-footer-small-height: 2.5rem;
@layout-header-font-size: 1rem;
@layout-pagenav-height: 2rem;
@layout-searchbar-height: 2.6rem;
@layout-touch-header-height: @layout-header-height;
@layout-touch-header-font-size: 1.2rem;
@ -45,4 +47,5 @@
@listing-treetoggle-width: 1.5em;
// Additional icons
@icon-resize-corner: data-uri("image/svg+xml;charset=utf-8", "../images/corner-handle.svg"); // size: 512x512
@icon-resize-corner: data-uri("image/svg+xml;charset=utf-8", "../images/corner-handle.svg"); // size: 512x512
@icon-file-drop: data-uri("image/svg+xml;charset=utf-8", "../images/download.svg");

@ -36,8 +36,11 @@ button.btn {
&:before {
&:extend(.font-icon-class);
}
&.toolbar-menu-button:before {
&.sidebar-menu:before,
&.toolbar-menu-button:before,
&.toolbar-list-button:before {
content: @fa-var-ellipsis-v;
width: 1em;
}
&.menu-button:before {
content: @fa-var-bars;
@ -47,6 +50,9 @@ button.btn {
&.back-list-button:before {
content: @fa-var-chevron-left;
}
&.refresh:before {
content: @fa-var-sync;
}
&.generate:before,
&.yes:before,
&.submit:before,
@ -113,9 +119,6 @@ button.btn {
&.help:before {
.font-icon-regular(@fa-var-life-ring);
}
&.toggleselect:before {
.font-icon-regular(@fa-var-check-square);
}
&.folders:before {
content: @fa-var-folder-open;
}
@ -123,10 +126,12 @@ button.btn {
&.settings:before {
content: @fa-var-wrench;
}
&.properties:before {
content: @fa-var-info-circle;
}
&.select:before {
.font-icon-regular(@fa-var-check-circle);
}
}
a.btn,
@ -164,7 +169,7 @@ html.touch {
bottom: 0;
.footer:not(:empty) + & {
bottom: @layout-touch-header-height;
bottom: @layout-footer-small-height;
}
a.button {

@ -72,10 +72,6 @@ font.bold {
}
}
.pagenav.expanded + .navlist {
border-bottom: 1px solid @color-layout-border;
}
.contact-header {
display: flex;
margin-bottom: 1rem;
@ -271,35 +267,39 @@ fieldset.image-attachment {
}
.quota-widget {
width: 5rem;
max-width: 8rem;
padding: .5rem;
text-align: center;
position: relative;
width: 100%;
max-width: 15em;
padding: .5rem 1rem;
display: flex;
align-items: center;
color: @color-quota-text;
&:before {
&:extend(.font-icon-class);
content: @fa-var-hdd;
line-height: 1;
}
.count {
display: block;
color: @color-quota-text;
font-size: 1.1rem;
line-height: 2;
font-size: 80%;
order: 2;
}
.bar {
display: block;
flex: 1;
height: .5rem;
position: absolute;
bottom: .85rem;
left: .5rem;
right: .5rem;
margin: 0 1rem;
background-color: @color-quota-background;
border: 1px solid @color-layout-border;
border-radius: .25rem;
overflow: hidden;
}
.value {
display: block;
background-color: @color-quota-value;
border-radius: .25rem;
height: .5rem;
height: 1rem;
opacity: .75;
&.warning {
@ -373,6 +373,7 @@ fieldset.image-attachment {
& > .footer {
height: 3.5rem;
border-top: 1px solid @color-table-border;
text-align: left;
a.button {
padding: 0;

@ -72,6 +72,7 @@ html.layout-phone {
margin: 0 !important;
padding: 0;
right: 0;
left: initial !important;
bottom: 0;
top: 0;
width: @layout-mobile-menu-width;
@ -80,6 +81,7 @@ html.layout-phone {
border: 0;
display: flex;
flex-direction: column;
box-shadow: none;
div.arrow {
display: none;
@ -90,8 +92,8 @@ html.layout-phone {
}
}
.popover:not(#rcmKSearchpane) {
left: initial !important;
.popover.menu {
left: 0 !important;
}
.popover-overlay {
@ -106,7 +108,6 @@ html.layout-phone {
#rcmKSearchpane {
bottom: auto;
border: 1px solid @color-input-border;
box-shadow: none;
}
.popover-header {
@ -115,6 +116,7 @@ html.layout-phone {
border: 0;
padding: 0 .5em;
height: @layout-touch-header-height;
min-height: @layout-touch-header-height; // for when it's a flex item
line-height: @layout-touch-header-height;
font-size: @layout-touch-header-font-size;
color: @color-popover-mobile-header;

@ -35,6 +35,12 @@
box-shadow: none !important;
}
.mce-btn {
&.mce-active {
background: @color-btn-secondary-background !important;
}
}
.mce-window {
&.mce-container {
border: 0;
@ -140,6 +146,28 @@
}
}
.mce-btn {
.btn-secondary;
border-radius: .3rem;
border-color: transparent;
&:focus {
border-color: transparent !important;
color: @color-btn-secondary;
background: @color-btn-secondary-background;
}
&.mce-primary {
.btn-primary;
}
button:hover,
button {
color: @color-btn-secondary;
padding: .5rem .75rem;
}
}
.mce-btn:last-child button:before {
content: @fa-var-times;
}
@ -408,6 +436,10 @@
border-bottom-color: transparent;
border-bottom: 0;
}
&:focus {
outline: unset !important;
}
}
}
@ -417,33 +449,6 @@
}
}
.mce-btn {
&.mce-active {
background: @color-btn-secondary-background !important;
}
.mce-window .mce-foot & {
.btn-secondary;
border-radius: .3rem;
border-color: transparent;
&:focus {
border-color: transparent !important;
color: @color-btn-secondary;
background: @color-btn-secondary-background;
}
&.mce-primary {
.btn-primary;
}
button:hover,
button {
color: @color-btn-secondary;
padding: .5rem .75rem;
}
}
}
// Menus and popovers, e.g. color selector, emoticons selector, font selector
.mce-menu,
@ -489,7 +494,23 @@
width: 100% !important;
}
.mce-window-head {
background-color: @color-layout-mobile-header-background;
.mce-title {
font-size: 1rem;
text-align: center;
padding: 0 1rem;
}
.mce-close {
display: none;
}
}
.mce-foot {
background-color: @color-layout-mobile-footer-background;
.mce-container-body {
justify-content: space-evenly;
@ -508,6 +529,10 @@
background: transparent;
}
&:last-child {
margin: 0;
}
button {
color: @color-font;
padding: .45rem;
@ -658,6 +683,10 @@ html.touch .mce-grid td {
&.droptarget {
border: .2rem dashed @color-table-border;
&:after {
margin-top: 2rem;
}
}
button {

@ -92,7 +92,6 @@ input.smart-upload {
td.rowactions {
width: 1%;
.custom-select,
.form-control {
width: auto;
}
@ -620,20 +619,25 @@ html.ms .propform {
td.editfield { width: 99%; /* TODO */ }
ul.proplist {
@proplist-record-height: 2rem;
.proplist {
margin-bottom: 0;
@media screen and (min-width: (@screen-width-bs-phone + 1px)) {
.formcontent > &,
fieldset > & {
padding-left: 0;
}
li {
list-style-type: none;
line-height: 2.4rem;
line-height: @proplist-record-height;
margin-bottom: .25rem;
display: flex;
&:last-child {
margin-bottom: 0;
}
input[type=radio] {
vertical-align: middle;
margin-right: .5em;
@ -645,16 +649,22 @@ ul.proplist {
label {
margin: 0;
line-height: @proplist-record-height;
}
.icon-checkbox {
height: 2.4rem !important;
height: @proplist-record-height;
margin-left: -1.2em;
& + label {
height: 2rem;
height: @proplist-record-height;
margin-right: .5rem;
padding: 0;
padding: 0 !important;
line-height: 1.25;
html.touch &:before {
line-height: 1.1;
}
}
}
@ -665,7 +675,6 @@ ul.proplist {
}
}
.checklist {
.form-check-input + label {
margin-right: .25rem;
@ -818,8 +827,6 @@ html.touch .popupmenu.form {
margin: 0;
}
// TODO background image
.upload-form {
text-align: center;
padding-bottom: 1em;
@ -864,6 +871,15 @@ html.touch .popupmenu.form {
}
&.droptarget {
padding-bottom: .5rem !important;
&:after {
content: @icon-file-drop;
width: 10rem;
margin: 5rem auto 0 auto;
display: block;
}
&.active {
border-color: darken(@color-toolbar-button-background-hover, 20%);
}
@ -1260,4 +1276,9 @@ td.input-group input {
.input-group-text {
color: @color-input;
background-color: @color-input-addon-background;
input:focus {
z-index: 1;
border-color: @color-input-border-focus !important;
}
}

@ -79,6 +79,7 @@
position: absolute;
height: (@layout-header-height - .7rem);
margin: .25rem;
padding-bottom: .375rem;
cursor: pointer;
&:before {
@ -171,6 +172,7 @@
.ui-dialog-titlebar {
height: @layout-touch-header-height;
text-align: center;
background-color: @color-layout-mobile-header-background;
}
.ui-dialog-title {
@ -191,6 +193,7 @@
text-align: center !important;
border-top: 1px solid @color-dialog-header-border;
height: @layout-header-height !important;
background-color: @color-layout-mobile-footer-background;
.ui-dialog-buttonset {
justify-content: space-around;
@ -284,6 +287,10 @@
transform: translate(-50%, -50%);
box-shadow: 10px 10px 10px 1000px @color-dialog-overlay-background;
&:not(.ui-datepicker-inline) {
z-index: 120 !important; // fixes datepicker over input-group and dialogs
}
.ui-datepicker-header,
.ui-datepicker-title {
line-height: 4rem;
@ -367,6 +374,12 @@ html.touch {
}
}
// Fixes datepicker z-index issue on input-group inputs in dialogs
// With non-relative position the input's z-index is ignored
.input-group > .form-control.hasDatepicker {
position: initial;
}
.minicolors-panel {
border: 1px solid @color-datepicker-border;
box-shadow: 3px 3px 5px @color-popover-shadow;

@ -335,6 +335,9 @@ html.ie11 .listing.iconized li a:before {
&.calendar > td.section:before {
content: @fa-var-calendar;
}
&.chat > td.section:before {
content: @fa-var-comments;
}
}
/* selecatable list: e.g. spellcheck language selection */
@ -638,53 +641,52 @@ table.fixedcopy {
cursor: pointer;
width: 1em;
}
tr.thread.expanded td.threads div:before {
content: @fa-var-angle-down;
}
td.subject span.msgicon.status:before {
&:extend(.font-icon-class);
content: @fa-var-circle;
cursor: pointer;
font-size: .4em;
width: 3em;
height: 2rem;
}
td.subject span.msgicon.status.unread:before {
content: @fa-var-star;
font-size: 1.1em;
width: 1.1em;
line-height: 1.75;
color: @color-warning;
}
td.subject span.msgicon.status.unreadchildren:before {
.font-icon-regular(@fa-var-star);
font-size: 1.1em;
width: 1.1em;
line-height: 1.75;
}
td.subject span.msgicon.status.replied:before {
content: @fa-var-reply;
font-size: 1.1em;
line-height: 1.75;
width: 1.1em;
}
td.subject span.msgicon.status.forwarded:before {
.font-icon-solid(@fa-var-share);
font-size: 1.1em;
line-height: 1.75;
width: 1.1em;
}
td.subject span.msgicon.status.replied.forwarded:before {
content: @fa-var-reply; // TODO
font-size: 1.1em;
line-height: 1.75;
width: 1.1em;
}
tr.deleted td.subject span.msgicon.status:before {
content: @fa-var-ban;
font-size: 1.1em;
line-height: 1.75;
width: 1.1em;
td.subject span.msgicon.status {
&:before {
&:extend(.font-icon-class);
content: @fa-var-circle;
cursor: pointer;
font-size: .4em;
width: 1.1rem;
height: 2rem;
line-height: 2rem;
}
&.unread:before {
content: @fa-var-circle;
color: @color-warning;
font-size: .5em;
}
&.unreadchildren:before {
.font-icon-regular(@fa-var-circle);
font-size: .5em;
}
&.replied:before {
.font-icon-solid(@fa-var-reply);
font-size: 1.1em;
}
&.forwarded:before {
.font-icon-solid(@fa-var-share);
font-size: 1.1em;
}
&.replied.forwarded:before {
.font-icon-solid(@fa-var-reply); // TODO
font-size: 1.1em;
}
tr.deleted &:before {
.font-icon-solid(@fa-var-ban);
font-size: 1.1em;
}
}
span.attachment span {

@ -19,7 +19,7 @@
margin-bottom: 1rem;
.subject {
.overflow-ellipsis;
display: flex;
font-size: 1.5rem;
font-weight: bold;
white-space: nowrap;
@ -32,6 +32,26 @@
font-size: 1em;
color: @color-error;
}
a.extwin {
margin-left: .25rem;
&:before {
&:extend(.font-icon-class);
font-size: 75%;
line-height: 1.5;
margin: 0;
content: @fa-var-external-link-square-alt;
}
}
& > span {
.overflow-ellipsis;
}
span.inner {
display: none;
}
}
.short-header {
@ -65,25 +85,16 @@
margin-right: .5rem;
text-decoration: none;
white-space: nowrap;
line-height: 1.5;
display: inline-block;
&:before {
&:extend(.font-icon-class);
display: inline-block;
float: none;
}
&.extwin:before {
content: @fa-var-external-link-square-alt;
}
&.headers:before {
content: @fa-var-wrench;
height: 1.5rem;
line-height: 1.3;
}
&.envelope:before {
.font-icon-regular(@fa-var-envelope);
content: @fa-var-envelope;
}
&.html:before {
@ -105,6 +116,11 @@
padding: .25rem 0 !important;
}
}
a.extwin,
a.headers {
text-decoration: none;
}
}
#message-content {

@ -1,113 +0,0 @@
/**
* Roundcube webmail styles for the Elastic skin
*
* Copyright (c) 2017-2018, The Roundcube Dev Team
*
* The contents are subject to the Creative Commons Attribution-ShareAlike
* License. It is allowed to copy, distribute, transmit and to adapt the work
* by keeping credits to the original authors in the README.md file.
* See http://creativecommons.org/licenses/by-sa/3.0/ for details.
*/
/*** Searchbar and searchfilterbar widgets ***/
.searchbar {
position: absolute;
background-color: @color-layout-header-background;
right: .25rem;
height: @layout-header-height;
a.button {
min-width: auto;
padding: 0;
display: block;
&:before {
line-height: @layout-header-height;
}
span.inner {
display: none;
}
}
.input-group {
margin-top: calc(@layout-header-height/2 - 2.25rem/2);
display: none;
padding: 0 .5rem;
.icon:before {
font-size: 1em;
line-height: 1.1;
}
.icon.filter,
.icon.search {
color: #888;
}
}
form {
display: none;
}
a.icon {
&:before {
&:extend(.font-icon-class);
margin: 0;
}
&.reset:before {
content: @fa-var-trash-alt;
}
&.options:before {
content: @fa-var-angle-down;
}
}
&.active a.button.search {
color: @color-searchbar-icon-active;
}
&.open {
z-index: 10;
left: 0 !important;
right: 0 !important;
.input-group {
display: flex;
}
form {
display: flex;
}
a.button.filter,
a.button.search {
display: none;
}
}
a.button.search {
padding: 0 .5rem;
}
}
.searchfilterbar {
right: @layout-touch-icon-width + .25rem;
&.active a.button.filter {
color: @color-searchbar-icon-active;
}
}
html.ie11 {
.searchbar {
a.button.filter:before,
a.button.search:before {
line-height: 3.2;
font-size: 1.25rem;
}
}
}

@ -59,6 +59,9 @@
&.notes:before {
content: @fa-var-sticky-note;
}
&.chat:before {
content: @fa-var-comments;
}
}
@media screen and (max-width: @screen-width-xs) {

@ -14,6 +14,7 @@
.toolbar {
margin: 0;
font-size: 1rem;
text-align: center;
&.listing a,
a {
@ -46,7 +47,6 @@
&:before {
&:extend(.font-icon-class);
display: inline;
float: none;
margin: 0;
line-height: 1.75;
@ -112,23 +112,23 @@
&.encrypt:before {
content: @fa-var-lock;
}
&.firstpage:before {
content: @fa-var-fast-backward;
}
&.prev:before {
content: @fa-var-arrow-left;
}
&.next:before {
content: @fa-var-arrow-right;
}
&.firstpage:before {
content: @fa-var-angle-double-left;
}
&.prevpage:before {
content: @fa-var-backward;
content: @fa-var-angle-left;
}
&.nextpage:before {
content: @fa-var-forward;
content: @fa-var-angle-right;
}
&.lastpage:before {
content: @fa-var-fast-forward;
content: @fa-var-angle-double-right;
}
&.send:before {
content: @fa-var-paper-plane;
@ -156,7 +156,7 @@
content: @fa-var-comment;
}
&.select:before {
.font-icon-regular(@fa-var-check-square);
.font-icon-regular(@fa-var-check-circle);
}
&.threads:before {
content: @fa-var-comments;
@ -180,10 +180,10 @@
content: @fa-var-user;
}
&.expand:before {
content: @fa-var-caret-down;
content: @fa-var-angle-right;
}
&.collapse:before {
content: @fa-var-caret-up;
content: @fa-var-angle-down;
}
&.submit:before {
content: @fa-var-check;
@ -233,42 +233,38 @@
}
&.pagenav {
text-align: center;
display: flex;
border-bottom: 1px solid @color-layout-border;
height: @layout-pagenav-height;
overflow: hidden;
justify-content: normal !important;
align-items: center;
a.button {
flex-grow: 1;
font-size: 80%;
min-width: 2rem !important;
height: @layout-pagenav-height !important;
color: @color-list-pagenav;
overflow: hidden;
height: @layout-footer-small-height;
&:before {
line-height: 1 !important;
line-height: 1.25;
}
}
.pagenav-text {
.overflow-ellipsis;
color: @color-list-pagenav;
flex-grow: 4;
line-height: @layout-pagenav-height;
font-size: 80%;
color: @color-list-pagenav;
white-space: nowrap;
}
input {
width: 3rem;
max-width: 5rem;
font-size: 90%;
line-height: 1;
padding: .25rem;
margin: .15rem;
display: inline;
text-align: center;
max-height: 1.6rem;
html.layout-phone & {
display: none;
}
}
span.inner {
@ -277,18 +273,25 @@
&.pagenav-list {
cursor: pointer;
background-color: @color-searchbar-background;
border-bottom: 1px solid @color-list-border;
a.button {
flex-grow: initial;
flex-grow: unset;
}
.pagenav-text {
text-align: left;
font-size: 100%;
}
& + .navlist {
background-color: #fbfbfb;
}
&.expanded + .navlist {
border-bottom: 1px solid @color-layout-border;
}
}
}
@ -301,6 +304,12 @@
}
}
&.footer.small {
a.button:before {
height: auto; // for Chrome
}
}
&.content-frame-navigation.hide-nav-buttons {
a.next,
a.prev {
@ -489,10 +498,10 @@
content: @fa-var-pencil-alt;
}
a.read:before {
.font-icon-regular(@fa-var-star);
.font-icon-regular(@fa-var-circle);
}
a.unread:before {
content: @fa-var-star;
content: @fa-var-circle;
}
a.flag:before {
content: @fa-var-flag;
@ -522,6 +531,15 @@
a.export.all:before {
content: @fa-var-download;
}
a.select:before {
content: @fa-var-check-circle;
}
a.threads:before {
content: @fa-var-comments;
}
a.selection:before {
content: @fa-var-mouse-pointer;
}
a.select.all:before {
.font-icon-regular(@fa-var-check-square);
}
@ -619,17 +637,6 @@
}
}
#layout > .sidebar > .header,
#layout > .list > .header {
span.inner {
display: none;
}
}
#layout > .content > * > .toolbar {
text-align: center;
}
html.touch {
.toolbarmenu.listing td,
.toolbarmenu.listing li,
@ -655,11 +662,11 @@ html.ie11 .toolbar .dropbutton a.dropdown:before {
}
@media screen and (min-width: (@screen-width-small + 1px)) {
ul.toolbar {
flex: 1;
}
.toolbar {
.header > & {
display: flex; // for Safari on desktop
}
a.button {
&:not(.disabled):focus,
&:not(.disabled):hover {
@ -743,3 +750,140 @@ html.ie11 .toolbar .dropbutton a.dropdown:before {
color: @color-font;
}
}
a.button.icon.toolbar-button {
order: 8;
@media screen and (min-width: (@screen-width-large + 1px)) {
height: @layout-header-height;
line-height: 1.5;
padding: .45rem;
&:before {
float: none;
height: 1.75rem;
line-height: 1.75;
width: auto;
}
span.inner {
display: inline;
font-weight: normal;
font-size: 90%;
}
}
}
/*** Searchbar and searchoptions widgets ***/
.searchbar {
height: @layout-searchbar-height;
min-height: @layout-searchbar-height; // because of Flexbox
line-height: @layout-searchbar-height;
background-color: @color-searchbar-background;
border-bottom: 1px solid @color-list-border;
display: flex;
align-items: center;
white-space: nowrap;
overflow: hidden;
position: relative;
padding-right: .5rem;
form {
flex: 1;
display: flex;
&:before {
&:extend(.font-icon-class);
content: @fa-var-search;
height: @layout-searchbar-height;
color: @color-list-pagenav;
margin: 0 0 0 .75rem;
}
}
input {
width: 100%;
border: 0;
background: transparent;
padding: .5rem;
}
a.button {
height: @layout-searchbar-height;
min-width: auto;
color: @color-toolbar-button;
&:before {
&:extend(.font-icon-class);
}
&.options {
&:before {
content: @fa-var-angle-down;
line-height: 1.25;
width: 1em;
}
}
&.reset {
display: none;
&:before {
content: @fa-var-times;
font-size: 1em;
}
}
&.search {
display: none;
}
}
span.inner {
display: none;
}
&.active {
a.button.reset {
display: inline;
}
}
&.open a.button.options:before {
content: @fa-var-angle-up;
}
}
.searchoptions {
button.search {
width: 100%;
}
ul.proplist {
& + div {
margin-top: 1rem;
}
}
.input-group {
&:not(:last-child) {
margin-bottom: .5rem;
}
.input-group-prepend {
width: 30%;
}
label {
width: 100%;
}
}
.formbuttons {
// this is needed because we hide .formbuttons on small devices
// we don't want it for search options form
display: block !important;
}
}

@ -8,18 +8,14 @@
<div class="header">
<a class="button icon back-list-button" href="#back"><span class="inner"><roundcube:label name="back" /></span></a>
<span id="directorylist-header" class="header-title"><roundcube:label name="groups" /></span>
<roundcube:button name="groupoptions" type="link" title="arialabelabookgroupoptions" label="actions"
class="button icon sidebar-menu" innerClass="inner" data-popup="groupoptions-menu" />
</div>
<div class="scroller">
<roundcube:object name="directorylist" id="directorylist" class="treelist listing iconized" />
<h3 class="voice"><roundcube:label name="savedsearches" /></h3>
<roundcube:object name="savedsearchlist" id="savedsearchlist" class="treelist listing iconized" />
</div>
<div class="footer toolbar" role="toolbar">
<roundcube:button command="group-create" type="link" title="newgroup" label="addgroup"
class="button create disabled" classAct="button create" innerClass="inner" />
<roundcube:button name="groupoptions" type="link" title="arialabelabookgroupoptions" label="actions"
class="button actions" innerClass="inner" data-popup="groupoptions-menu" />
</div>
</div>
<!-- contacts list -->
@ -28,17 +24,32 @@
<a class="button icon menu-button" href="#menu"><span class="inner"><roundcube:label name="menu" /></span></a>
<a class="button icon back-sidebar-button folders" href="#sidebar"><span class="inner"><roundcube:label name="groups" /></span></a>
<roundcube:object name="addresslisttitle" label="contacts" tag="span" class="header-title" />
<roundcube:object name="searchform" id="searchform" wrapper="searchbar toolbar"
label="contactsearchform" buttontitle="findcontacts" options="search-menu" ariatag="h2" />
<a class="button icon toolbar-menu-button" href="#list-menu"><span class="inner"><roundcube:label name="menu" /></span></a>
</div>
<roundcube:include file="includes/pagenav.html" />
<roundcube:object name="searchform" id="searchform" wrapper="searchbar toolbar"
label="contactsearchform" buttontitle="findcontacts" options="searchmenu" ariatag="h2" />
<div id="searchmenu" class="hidden searchoptions scroller propform formcontainer" aria-labelledby="aria-label-search-menu">
<h3 id="aria-label-search-menu" class="voice"><roundcube:label name="searchmod" /></h3>
<div class="formcontent">
<ul class="proplist">
<li><label><input type="checkbox" name="s_mods[]" value="name" /><roundcube:label name="name" /></label></li>
<li><label><input type="checkbox" name="s_mods[]" value="firstname" /><roundcube:label name="firstname" /></label></li>
<li><label><input type="checkbox" name="s_mods[]" value="surname" /><roundcube:label name="surname" /></label></li>
<li><label><input type="checkbox" name="s_mods[]" value="email" /><roundcube:label name="email" /></label></li>
<li><label><input type="checkbox" name="s_mods[]" value="*" /><roundcube:label name="allfields" /></label></li>
</ul>
</div>
<div class="formbuttons">
<button class="btn btn-primary icon search" href="#" onclick="return rcmail.command('search')"><roundcube:label name="search" /></button>
</div>
</div>
<div class="scroller">
<h2 id="aria-label-contactslist" class="voice"><roundcube:label name="contacts" /></h2>
<roundcube:object name="addresslist" id="contacts-table" class="listing iconized contactlist"
noheader="true" role="listbox" data-list="contact_list"
data-label-msg="listempty" data-label-ext="listusebutton" data-create-command="add" />
</div>
<roundcube:include file="includes/pagenav.html" />
</div>
<!-- contact details frame -->
@ -59,11 +70,6 @@
class="button delete disabled" classAct="button delete"
label="delete" title="deletecontact" innerClass="inner" />
<span class="spacer"></span>
<!--
<roundcube:button command="compose" type="link"
class="button compose disabled" classAct="button compose"
label="compose" title="writenewmessage" innerclass="inner" />
-->
<roundcube:button command="advanced-search" type="link"
class="button search disabled" classAct="button search"
label="search" title="advsearch" innerclass="inner" />
@ -103,6 +109,7 @@
<div id="groupoptions-menu" class="popupmenu">
<h3 id="aria-label-groupoptions-menu" class="voice"><roundcube:label name="arialabelabookgroupoptions" /></h3>
<ul class="toolbarmenu listing" role="menu" aria-labelledby="aria-label-groupoptions-menu">
<roundcube:button type="link-menuitem" command="group-create" title="newgroup" label="addgroup" class="create" classAct="create active" />
<roundcube:button type="link-menuitem" command="group-rename" label="grouprename" class="group rename" classAct="group rename active" />
<roundcube:button type="link-menuitem" command="group-delete" label="groupdelete" class="group delete" classAct="group delete active" />
<roundcube:button type="link-menuitem" command="search-create" label="searchsave" class="search" classAct="search active" />
@ -111,18 +118,6 @@
</ul>
</div>
<div id="search-menu" class="popupmenu form" data-editable="true" data-popup-init="searchmenu">
<h3 id="aria-label-search-menu" class="voice"><roundcube:label name="searchmod" /></h3>
<ul class="toolbarmenu" role="menu" aria-labelledby="aria-label-search-menu">
<li role="menuitem" class="checkbox"><label><input type="checkbox" name="s_mods[]" value="name" id="s_mod_name" /><roundcube:label name="name" /></label></li>
<li role="menuitem" class="checkbox"><label><input type="checkbox" name="s_mods[]" value="firstname" id="s_mod_firstname" /><roundcube:label name="firstname" /></label></li>
<li role="menuitem" class="checkbox"><label><input type="checkbox" name="s_mods[]" value="surname" id="s_mod_surname" /><roundcube:label name="surname" /></label></li>
<li role="menuitem" class="checkbox"><label><input type="checkbox" name="s_mods[]" value="email" id="s_mod_email" /><roundcube:label name="email" /></label></li>
<li role="menuitem" class="checkbox"><label><input type="checkbox" name="s_mods[]" value="*" id="s_mod_all" /><roundcube:label name="allfields" /></label></li>
</ul>
<div class="buttons"><button class="btn btn-primary icon search" href="#" onclick="if (rcmail.command('search')) UI.menu_hide('search-menu')"><roundcube:label name="search" /></button></div>
</div>
<div id="dragcontact-menu" class="popupmenu">
<h3 id="aria-label-dragcontact-menu" class="voice"><roundcube:label name="arialabeldropactionmenu" /></h3>
<ul class="toolbarmenu listing" role="menu" aria-labelledby="aria-label-dragcontact-menu">

@ -12,10 +12,9 @@
<div class="header no-toolbar">
<a class="button icon back-content-button" href="#content" data-hidden="big"><span class="inner"><roundcube:label name="back" /></span></a>
<span id="aria-label-composecontacts" class="header-title"><roundcube:label name="contacts" /></span>
<roundcube:object name="searchform" id="searchform" wrapper="searchbar toolbar"
label="contactsearchform" buttontitle="findcontacts" ariatag="h2" />
</div>
<roundcube:include file="includes/pagenav.html" />
<roundcube:object name="searchform" id="searchform" wrapper="searchbar toolbar"
label="contactsearchform" buttontitle="findcontacts" ariatag="h2" />
<div class="scroller" tabindex="-1">
<roundcube:object name="addressbooks" id="directorylist" class="treelist listing iconized"
summary="ariasummarycomposecontacts" />
@ -31,13 +30,14 @@
class="button addbcc disabled" classAct="button addbcc" innerClass="inner" content="Bcc+" />
<roundcube:container name="compose-contacts-toolbar" id="compose-contacts-toolbar" />
</div>
<roundcube:include file="includes/pagenav.html" />
</div>
<!-- compose options and attachments list -->
<div class="list listbox">
<div class="header">
<a class="button icon back-content-button" href="#content" data-hidden="big"><span class="inner"><roundcube:label name="back" /></span></a>
<span class="header-title"><roundcube:label name="optionsandattachments" /></span>
<span class="header-title all-sizes"><roundcube:label name="optionsandattachments" /></span>
</div>
<div class="scroller">
<!-- compose options -->

@ -9,16 +9,25 @@
<div class="header">
<a class="button icon back-sidebar-button" href="#sidebar"><span class="inner"><roundcube:label name="settings" /></span></a>
<span id="aria-label-folderslist" class="header-title"><roundcube:label name="folders" /></span>
<roundcube:object name="searchform" id="foldersearch" wrapper="searchbar toolbar"
label="foldersearchform" buttontitle="findfolders" options="search-filter" ariatag="h2" />
<a class="button icon toolbar-menu-button" href="#list-menu"><span class="inner"><roundcube:label name="menu" /></span></a>
</div>
<roundcube:object name="searchform" id="foldersearch" wrapper="searchbar toolbar" ariatag="h2"
label="foldersearchform" buttontitle="findfolders" options="foldersearchmenu" />
<div id="foldersearchmenu" class="hidden searchoptions scroller propform formcontainer" aria-labelledby="aria-label-search-menu" aria-controls="subscription-table">
<h3 id="aria-label-search-menu" class="voice"><roundcube:label name="searchmod" /></h3>
<div class="formcontent">
<roundcube:object name="folderfilter" id="folderlist-filter" noheader="true" />
</div>
<div class="formbuttons">
<button class="btn btn-primary icon search" href="#" onclick="return rcmail.command('search')"><roundcube:label name="search" /></button>
</div>
</div>
<div class="scroller" tabindex="-1">
<roundcube:object name="foldersubscription" id="subscription-table"
class="treelist listing folderlist iconized" role="listbox" data-list="subscription_list"
data-label-msg="listempty" data-label-ext="listusebutton" data-create-command="folder-create" />
</div>
<div class="footer">
<div class="footer small">
<roundcube:if condition="env:quota" />
<div id="quotadisplay" class="quota-widget">
<span class="voice"><roundcube:label name="quota"></span>
@ -52,8 +61,4 @@
</div>
</div>
<div id="search-filter" class="popupmenu form nolist toolbarmenu" data-editable="true">
<roundcube:object name="folderfilter" id="folderlist-filter" noheader="true" />
</div>
<roundcube:include file="includes/footer.html" />

@ -5,6 +5,7 @@
<roundcube:add_label name="htmltoggle" />
<roundcube:add_label name="previous" />
<roundcube:add_label name="next" />
<roundcube:add_label name="select" />
<roundcube:object name="doctype" value="html5" />
<roundcube:if condition="!env:framed || env:extwin" />
<html>

@ -1,5 +1,7 @@
<roundcube:add_label name="viewsource" />
<div id="mailtoolbar" class="toolbar" role="toolbar">
<roundcube:button command="compose" type="link" class="button compose hidden"
label="compose" title="writenewmessage" innerclass="inner" />
<roundcube:button command="reply" type="link"
class="button reply disabled" classAct="button reply"
label="reply" title="replytomessage" innerclass="inner" data-content-button="true" />

@ -1,4 +1,4 @@
<div class="pagenav toolbar" role="toolbar">
<div class="pagenav toolbar footer small" role="toolbar">
<roundcube:button command="firstpage" type="link"
class="button firstpage disabled" classAct="button firstpage"
title="firstpage" label="first" innerclass="inner" />

@ -8,14 +8,14 @@
<div class="header">
<a class="button icon back-list-button" href="#back"><span class="inner"><roundcube:label name="back" /></span></a>
<span class="header-title username"><roundcube:object name="username" /></span>
<roundcube:button name="folderactions" type="link" title="folderactions" label="actions"
class="button icon sidebar-menu" innerclass="inner" data-popup="mailboxoptions-menu" />
</div>
<h2 id="aria-label-folderlist" class="voice"><roundcube:label name="arialabelfolderlist" /></h2>
<div id="folderlist-content" class="scroller">
<roundcube:object name="mailboxlist" id="mailboxlist" class="treelist listing folderlist" folder_filter="mail" unreadwrap="%s" />
</div>
<div id="folderlist-footer" class="footer toolbar">
<roundcube:button name="folderactions" type="link" title="folderactions" label="actions"
class="button actions" innerclass="inner" data-popup="mailboxoptions-menu" />
<div class="footer toolbar small">
<roundcube:if condition="env:quota" />
<div id="quotadisplay" class="quota-widget">
<span class="voice"><roundcube:label name="quota"></span>
@ -31,13 +31,59 @@
<a class="button icon menu-button" href="#menu"><span class="inner"><roundcube:label name="menu" /></span></a>
<a class="button icon back-sidebar-button folders" href="#sidebar"><span class="inner"><roundcube:label name="mailboxlist" /></span></a>
<span class="header-title"></span>
<roundcube:object name="searchfilter" id="mailsearchfilter" class="searchfilterbar hidden" aria-controls="messagelist" />
<roundcube:add_label name="filter" />
<roundcube:object name="searchform" id="mailsearchform" wrapper="searchbar toolbar"
label="mailquicksearchbox" buttontitle="findmail" options="search-menu" ariatag="h2" />
<div class="toolbar" role="toolbar">
<a href="#select" class="button select active" data-popup="listselect-menu" data-toggle-button="list-toggle-button" title="<roundcube:label name="select" />"><span class="inner"><roundcube:label name="select" /></span></a>
<roundcube:if condition="env:threads" />
<a href="#threads" class="button threads active" data-popup="threadselect-menu" title="<roundcube:label name="threads" />"><span class="inner"><roundcube:label name="threads" /></span></a>
<roundcube:endif />
<roundcube:object name="listmenulink" class="button settings active" label="options" innerclass="inner" />
<roundcube:container name="listcontrols" id="listcontrols" />
</div>
<roundcube:button command="checkmail" type="link" class="button icon toolbar-button refresh"
label="refresh" title="checkmail" innerclass="inner" />
<a class="button icon toolbar-menu-button" href="#list-menu"><span class="inner"><roundcube:label name="menu" /></span></a>
</div>
<roundcube:include file="includes/pagenav.html" />
<roundcube:object name="searchform" id="mailsearchform" wrapper="searchbar toolbar"
label="mailquicksearchbox" buttontitle="findmail" options="searchmenu" ariatag="h2" />
<div id="searchmenu" class="hidden searchoptions scroller propform formcontainer" aria-labelledby="aria-label-search-menu" aria-controls="messagelist">
<h3 id="aria-label-search-menu" class="voice"><roundcube:label name="searchmod" /></h3>
<div class="formcontent">
<ul class="proplist">
<li><label><input type="checkbox" name="s_mods[]" value="subject" /><roundcube:label name="subject" /></label></li>
<li><label><input type="checkbox" name="s_mods[]" value="from" /><roundcube:label name="from" /></label></li>
<li><label><input type="checkbox" name="s_mods[]" value="to" /><roundcube:label name="to" /></label></li>
<li><label><input type="checkbox" name="s_mods[]" value="cc" /><roundcube:label name="cc" /></label></li>
<li><label><input type="checkbox" name="s_mods[]" value="bcc" /><roundcube:label name="bcc" /></label></li>
<li><label><input type="checkbox" name="s_mods[]" value="body" /><roundcube:label name="body" /></label></li>
<li><label><input type="checkbox" name="s_mods[]" value="text" /><roundcube:label name="msgtext" /></label></li>
</ul>
<div class="input-group">
<div class="input-group-prepend">
<label for="searchfilter" class="input-group-text"><roundcube:label name="type" /></label>
</div>
<roundcube:object name="searchfilter" id="searchfilter" />
</div>
<div class="input-group">
<div class="input-group-prepend">
<label for="s_interval" class="input-group-text"><roundcube:label name="date" /></label>
</div>
<roundcube:object name="searchinterval" id="s_interval" onchange="rcmail.set_searchinterval($(this).val())" />
</div>
<div class="input-group">
<div class="input-group-prepend">
<label for="s_scope" class="input-group-text"><roundcube:label name="searchscope" /></label>
</div>
<select name="s_scope" id="s_scope">
<option value="base"><roundcube:label name="currentfolder" /></option>
<option value="sub"><roundcube:label name="subfolders" /></option>
<option value="all"><roundcube:label name="allfolders" /></option>
</select>
</div>
</div>
<div class="formbuttons">
<button class="btn btn-primary icon search" href="#" onclick="return rcmail.command('search')"><roundcube:label name="search" /></button>
</div>
</div>
<div id="messagelist-content" class="scroller" tabindex="-1">
<h2 id="aria-label-messagelist" class="voice"><roundcube:label name="arialabelmessagelist" /></h2>
<roundcube:object name="messages" id="messagelist" optionsmenuIcon="true"
@ -46,17 +92,7 @@
data-list="message_list" data-label-msg="listempty"
/>
</div>
<div id="messagelist-footer" class="footer toolbar" role="toolbar">
<div id="listcontrols" class="listselectors">
<a href="#select" class="button select" data-popup="listselect-menu" title="<roundcube:label name="select" />"><span class="inner"><roundcube:label name="select" /></span></a>
<roundcube:if condition="env:threads" />
<a href="#threads" class="button threads" data-popup="threadselect-menu" title="<roundcube:label name="threads" />"><span class="inner"><roundcube:label name="threads" /></span></a>
<roundcube:endif />
<roundcube:object name="listmenulink" class="button settings" label="options" innerclass="inner" />
<roundcube:button command="checkmail" type="link" class="button refresh" label="refresh" title="checkmail" innerclass="inner" />
<roundcube:container name="listcontrols" id="listcontrols" />
</div>
</div>
<roundcube:include file="includes/pagenav.html" />
</div>
<!-- message preview -->
@ -79,25 +115,6 @@
</div>
<!-- popup menus -->
<div id="search-menu" class="popupmenu form" data-editable="true" data-popup-init="searchmenu">
<h3 id="aria-label-search-menu" class="voice"><roundcube:label name="searchmod" /></h3>
<ul class="toolbarmenu" role="menu" aria-labelledby="aria-label-search-menu">
<li role="menuitem" class="checkbox"><label><input type="checkbox" name="s_mods[]" value="subject" id="s_mod_subject" /><roundcube:label name="subject" /></label></li>
<li role="menuitem" class="checkbox"><label><input type="checkbox" name="s_mods[]" value="from" id="s_mod_from" /><roundcube:label name="from" /></label></li>
<li role="menuitem" class="checkbox"><label><input type="checkbox" name="s_mods[]" value="to" id="s_mod_to" /><roundcube:label name="to" /></label></li>
<li role="menuitem" class="checkbox"><label><input type="checkbox" name="s_mods[]" value="cc" id="s_mod_cc" /><roundcube:label name="cc" /></label></li>
<li role="menuitem" class="checkbox"><label><input type="checkbox" name="s_mods[]" value="bcc" id="s_mod_bcc" /><roundcube:label name="bcc" /></label></li>
<li role="menuitem" class="checkbox"><label><input type="checkbox" name="s_mods[]" value="body" id="s_mod_body" /><roundcube:label name="body" /></label></li>
<li role="menuitem" class="checkbox"><label><input type="checkbox" name="s_mods[]" value="text" id="s_mod_text" /><roundcube:label name="msgtext" /></label></li>
<li role="separator" class="separator"><label><roundcube:label name="date" /></label></li>
<li role="menuitem"><roundcube:object name="searchinterval" id="s_interval" onchange="rcmail.set_searchinterval($(this).val())" /></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" /> <span><roundcube:label name="currentfolder" /></span></label></li>
<li role="menuitem"><label><input type="radio" name="s_scope" value="sub" id="s_scope_sub" /> <span><roundcube:label name="subfolders" /></span></label></li>
<li role="menuitem"><label><input type="radio" name="s_scope" value="all" id="s_scope_all" /> <span><roundcube:label name="allfolders" /></span></label></li>
</ul>
<div class="buttons"><button class="btn btn-primary icon search" href="#" onclick="if (rcmail.command('search')) UI.menu_hide('search-menu')"><roundcube:label name="search" /></button></div>
</div>
<div id="dragmessage-menu" class="popupmenu">
<h3 id="aria-label-dragmessage-menu" class="voice"><roundcube:label name="arialabeldropactionmenu" /></h3>
@ -121,6 +138,9 @@
<div id="listselect-menu" class="popupmenu">
<h3 id="aria-label-listselect-menu" class="voice"><roundcube:label name="arialabellistselectmenu" /></h3>
<ul class="toolbarmenu listing" role="menu" aria-labelledby="aria-label-listselect-menu">
<roundcube:button type="link-menuitem" label="selection" class="selection" classAct="selection active"
name="list-toggle-button" id="list-toggle-button"
onclick="if ($(this).is('.active')) $('#messagelist').toggleClass('withselection');" />
<roundcube:button command="select-all" type="link-menuitem" label="all" class="select all" classAct="select all active" />
<roundcube:button command="select-all" type="link-menuitem" prop="page" label="currpage" class="select page" classAct="select page active" />
<roundcube:button command="select-all" type="link-menuitem" prop="unread" label="unread" class="select unread" classAct="select unread active" />

@ -21,6 +21,10 @@
<span class="voice"><roundcube:label name="subject" />: </span>
<roundcube:object name="messageHeaders" valueOf="subject" />
</span>
<roundcube:if condition="!env:message_context && !env:extwin">
<roundcube:button command="extwin" type="link" class="extwin" innerClass="inner"
label="openinextwin" data-hidden="small" />
<roundcube:endif />
</h2>
<div class="short-header">
<roundcube:object name="contactphoto" class="contactphoto" placeholder="/images/contactpic.png" />
@ -28,15 +32,11 @@
<roundcube:object name="messageSummary" addicon="virtual" class="header-subject" />
<div class="message-partheaders hidden">
<roundcube:object name="messageHeaders" class="headers-table" addicon="virtual" exclude="subject" max="10" />
<a href="#all-headers" class="headers" onclick="return UI.headers_dialog()"><roundcube:label name="allheaders" /></a>
</div>
<div class="header-links">
<a href="#headers" class="envelope" onclick="return UI.headers_show(this)"><roundcube:label name="envelope" /></a>
<a href="#all-headers" class="headers" onclick="return UI.headers_dialog()"><roundcube:label name="headers" /></a>
<a href="#headers" class="envelope" onclick="return UI.headers_show(this)"><roundcube:label name="details" /></a>
<roundcube:add_label name="arialabelmessageheaders" />
<roundcube:if condition="!env:message_context && !env:extwin">
<roundcube:button command="extwin" type="link" class="extwin" innerClass="inner"
label="openinextwin" data-hidden="small" />
<roundcube:endif />
<roundcube:if condition="env:optional_format=='text'" />
<roundcube:button command="change-format" prop="text" type="link" class="plain" innerClass="inner"
title="changeformattext" label="plaintoggle" />

@ -6,7 +6,6 @@
<div class="list listbox<roundcube:exp expression="!request:_action ? '' : ' selected'"/>" aria-labelledby="aria-label-prefsection">
<div class="header">
<a class="button icon menu-button" href="#menu"><span class="inner"><roundcube:label name="menu" /></span></a>
<a class="button icon back-sidebar-button" href="#sidebar"><span class="inner"><roundcube:label name="settings" /></span></a>
<span id="aria-label-prefsection" class="header-title"><roundcube:label name="preferences" /></span>
</div>

@ -78,6 +78,9 @@ function rcube_elastic_ui()
this.pretty_select = pretty_select;
// Detect screen size/mode
screen_mode();
// Initialize layout
layout_init();
@ -107,10 +110,6 @@ function rcube_elastic_ui()
{
var title, form, content_buttons = [];
// Initialize search forms (in list headers)
$('.header > .searchbar').each(function() { searchbar_init(this); });
$('.header > .searchfilterbar').each(function() { searchfilterbar_init(this); });
// Intercept jQuery-UI dialogs...
$.ui && $.widget('ui.dialog', $.ui.dialog, {
open: function() {
@ -137,6 +136,9 @@ function rcube_elastic_ui()
buttons.back_list.on('click', function() { show_list(); return false; });
buttons.back_content.on('click', function() { show_content(true); return false; });
// Initialize search forms
$('.searchbar').each(function() { searchbar_init(this); });
// Set content frame title in parent window (exclude ext-windows and dialog frames)
if (is_framed && !rcmail.env.extwin && !parent.$('.ui-dialog:visible').length) {
if (title = $('h1.voice:first').text()) {
@ -174,7 +176,7 @@ function rcube_elastic_ui()
});
// Move form buttons from the content frame into the frame footer (on parent window)
$('.formbuttons').children().each(function() {
$('.formbuttons').filter(function() { return !$(this).parent('.searchoptions').length; }).children().each(function() {
var target = $(this);
// skip non-content buttons
@ -281,7 +283,7 @@ function rcube_elastic_ui()
$('[data-hidden]').each(function() {
var m, v = $(this).data('hidden'),
parent = $(this).parent('li'),
re = /(large|big|small|phone)/g;
re = /(large|big|small|phone|lbs)/g;
while (m = re.exec(v)) {
$(parent.length ? parent : this).addClass('hidden-' + m[1]);
@ -367,21 +369,32 @@ function rcube_elastic_ui()
/**
* Create a button clone for use in toolbar
*/
function create_cloned_button(target)
function create_cloned_button(target, menu_button, add_class)
{
var button = $('<a>'),
target_id = target.attr('id'),
var popup, click = true,
button = $('<a>'),
target_id = target.attr('id') || new Date().getTime(),
button_id = target_id + '-clone',
btn_class = target[0].className;
btn_class = target[0].className + (add_class ? ' ' + add_class : '');
btn_class = $.trim(btn_class.replace('btn-primary', 'primary').replace(/(btn[a-z-]*|button|disabled)/g, ''))
btn_class += ' button disabled';
if (!menu_button) {
btn_class = $.trim(btn_class.replace('btn-primary', 'primary').replace(/(btn[a-z-]*|button|disabled)/g, ''))
btn_class += ' button disabled';
}
else if (popup = target.data('popup')) {
button.data('popup', popup).data('toggle-button', target.data('toggle-button'));
popup_init(button[0]);
click = false;
}
button.attr({'onclick': '', id: button_id, href: '#', 'class': btn_class})
.append($('<span class="inner">').text(target.text()))
.on('click', function(e) { target.click(); });
button.attr({id: button_id, href: '#', 'class': btn_class})
.append($('<span class="inner">').text(target.text()));
if (is_framed) {
if (click) {
button.on('click', function(e) { target.click(); });
}
if (is_framed && !menu_button) {
button.data('target', target);
frame_buttons.push($.extend({button_id: button_id}, find_button(target[0].id)));
}
@ -479,14 +492,36 @@ function rcube_elastic_ui()
list = table.data('list');
if (rcmail[list] && rcmail[list].multiselect) {
var button, parent = table.parents('.sidebar,.list,.content').last(),
header = parent.find('.header'),
toolbar = header.find('ul');
if (!toolbar.length) {
toolbar = header;
}
else if (button = toolbar.find('a.button.select').data('toggle-button')) {
button = $('#' + button);
}
// Enable checkbox selection on list widgets
rcmail[list].checkbox_selection = true;
rcmail[list].enable_checkbox_selection();
// Add Select button to the list navigation bar
button = $('<a>').attr({'class': 'button icon toggleselect disabled', role: 'button'})
.on('click', function() { if ($(this).is('.active')) table.toggleClass('withselection'); })
.append($('<span class="inner">').text(rcmail.gettext('select')))
.insertBefore(table.parents('.sidebar,.list,.content').find('.header-title'));
if (!button) {
button = $('<a>').attr({'class': 'button select disabled', role: 'button', title: rcmail.gettext('select')})
.on('click', function() { if ($(this).is('.active')) table.toggleClass('withselection'); })
.append($('<span class="inner">').text(rcmail.gettext('select')));
if (toolbar.is('.toolbar')) {
button.prependTo(toolbar).wrap('<li role="menuitem">');
}
else {
button.appendTo(toolbar).addClass('icon');
if (!parent.is('.sidebar')) {
button.addClass('toolbar-button');
}
}
}
// Update Select button state on list update
rcmail.addEventListener('listupdate', function(prop) {
@ -718,7 +753,10 @@ function rcube_elastic_ui()
var supported_controls = 'input:not(.button,[type=button],[type=file],[type=radio],[type=checkbox]),textarea';
$(supported_controls, $('.propform', context)).addClass('form-control');
$('[type=checkbox]', $('.propform', context)).addClass('form-check-input');
$('select', context).addClass('custom-select');
// Note: On selects we add form-control to get consistent focus
// and to not have to create separate rules for selects and inputs
$('select', context).addClass('form-control custom-select');
if (context != document) {
$(supported_controls, context).addClass('form-control');
@ -1037,14 +1075,11 @@ function rcube_elastic_ui()
env.content_lock = false;
};
// display the list widget after 'list' and 'listgroup' commands
var common_list_handler = function(e) {
if (mode != 'large' && !env.content_lock && e.list) {
if (mode != 'large' && !env.content_lock && e.force) {
show_list();
}
env.content_lock = false;
// display current folder name in list header
if (e.title) {
$('.header > .header-title', layout.list).text(e.title);
@ -1054,10 +1089,6 @@ function rcube_elastic_ui()
var list_handler = function(e) {
var args = {};
if (rcmail.env.task == 'addressbook' || (rcmail.env.task == 'mail' && !rcmail.env.action)) {
args.list = true;
}
// display current folder name in list header
if (rcmail.env.task == 'mail' && !rcmail.env.action) {
var name = $.type(e) == 'string' ? e : rcmail.env.mailbox,
@ -1093,7 +1124,6 @@ function rcube_elastic_ui()
.addEventListener('afterlistsearch', list_handler)
// plugins
.addEventListener('show-list', function(e) {
e.list = true;
common_list_handler(e);
})
.addEventListener('show-content', function(e) {
@ -1284,12 +1314,11 @@ function rcube_elastic_ui()
};
/**
* Window resize handler
* Does layout reflows e.g. on screen orientation change
* screen mode
*/
function resize()
function screen_mode()
{
var size, mobile, width = $(window).width();
var size, width = $(window).width();
if (width <= 480)
size = 'phone';
@ -1302,6 +1331,17 @@ function rcube_elastic_ui()
touch = width <= 1024;
mode = size;
};
/**
* Window resize handler
* Does layout reflows e.g. on screen orientation change
*/
function resize()
{
var mobile;
screen_mode();
screen_resize();
screen_resize_html();
@ -1402,12 +1442,7 @@ function rcube_elastic_ui()
return;
}
if ($(this).is('.searchbar')) {
padding += this.offsetWidth;
}
else {
sizes[title ? 'right' : 'left'] += this.offsetWidth;
}
sizes[title ? 'right' : 'left'] += this.offsetWidth;
});
if (padding + sizes.right >= sizes.left) {
@ -1455,6 +1490,10 @@ function rcube_elastic_ui()
layout.content.removeClass('hidden');
app_menu(true);
screen_resize_small_none();
if (layout.list) {
$('.header > ul.toolbar', layout.list).addClass('popupmenu toolbarmenu').removeClass('toolbar');
}
};
function screen_resize_large()
@ -1462,6 +1501,10 @@ function rcube_elastic_ui()
$.each(layout, function(name, item) { item.removeClass('hidden'); });
screen_resize_small_none();
if (layout.list) {
$('.header > ul.toolbarmenu.popupmenu', layout.list).removeClass('popupmenu toolbarmenu').addClass('toolbar');
}
};
function screen_resize_small_all()
@ -1471,11 +1514,13 @@ function rcube_elastic_ui()
if (layout.content.length) {
show = got_content = layout.content.is(env.last_selected);
layout.content[show ? 'removeClass' : 'addClass']('hidden');
$('.header > ul.toolbar', layout.content).addClass('popupmenu');
}
if (layout.list.length) {
show = !got_content && layout.list.is(env.last_selected);
layout.list[show ? 'removeClass' : 'addClass']('hidden');
$('.header > ul.toolbar', layout.list).addClass('popupmenu');
}
if (layout.sidebar.length) {
@ -1486,8 +1531,6 @@ function rcube_elastic_ui()
if (got_content) {
buttons.back_list.show();
}
$('.header > ul.toolbar', layout.content).addClass('popupmenu');
};
function screen_resize_small_none()
@ -1581,7 +1624,9 @@ function rcube_elastic_ui()
{
if (show) {
if (mode == 'phone') {
$('<div id="menu-overlay" class="popover-overlay">').appendTo('body');
$('<div id="menu-overlay" class="popover-overlay">')
.on('click', function() { app_menu(false); })
.appendTo('body');
if (!env.menu_initialized) {
env.menu_initialized = true;
@ -1672,6 +1717,9 @@ function rcube_elastic_ui()
}
}
// Close all popovers
$(document).click();
// Display loader when the dialog has an iframe
iframe_loader($('div.popup > iframe', me));
@ -1684,139 +1732,84 @@ function rcube_elastic_ui()
*/
function searchbar_init(bar)
{
var parent_class = 'with-search',
input = $('input:not([type=hidden])', bar).addClass('form-control'),
button = $('a.button.search', bar),
var options_button = $('a.button.options', bar),
input = $('input:not([type=hidden])', bar),
placeholder = input.attr('placeholder'),
form = $('form', bar),
is_search_pending = function() {
// TODO: This have to be improved to detect real searching state
// There are cases when search is active but the input is empty
return input.val();
},
hide_func = function(event, focus) {
if (button.is(':visible')) {
return;
if (input.val()) {
return true;
}
$(bar).removeClass('open')[is_search_pending() ? 'addClass' : 'removeClass']('active');
if (rcmail.gui_objects.search_filter && $(rcmail.gui_objects.search_filter).val() != 'ALL') {
return true;
}
if (focus && rcube_event.is_keyboard(event)) {
button.focus();
if (rcmail.gui_objects.foldersfilter && $(rcmail.gui_objects.foldersfilter).val() != '---') {
return true;
}
},
update_func = function() {
$(bar)[is_search_pending() ? 'addClass' : 'removeClass']('active');
};
if (!$(bar).next().length) {
parent_class += ' no-toolbar';
}
$(bar).parent().addClass(parent_class);
options_button.on('click', function(e) {
var id = $(this).data('target'),
options = $('#' + id),
open = options.is(':visible');
if (is_search_pending()) {
$(bar).addClass('active');
}
if (options.length) {
if (!open) {
if (ref[id]) {
ref[id](options.get(0), this, e);
}
else if (typeof window[id] == 'function') {
window[id](options.get(0), this, e);
}
}
// make the input pretty
form.addClass('input-group')
.prepend($('<span class="input-group-prepend">').append('<i class="input-group-text icon search">'))
.append($('<span class="input-group-append">')
.append($('a.options', bar).detach().removeClass('button').addClass('icon input-group-text'))
.append($('a.reset', bar).detach().removeClass('button').addClass('icon input-group-text'))
.append($('<a class="icon cancel input-group-text" href="#">')));
options.next()[open ? 'show' : 'hide']();
options.toggleClass('hidden');
$('.floating-action-buttons').toggleClass('hidden');
$(bar).toggleClass('open');
// Display search form
button.on('click', function() {
$(bar).addClass('open');
input.focus();
$('button.search', options).off('click.search').on('click.search', function() {
options_button.trigger('click');
});
}
});
input.on('input change', update_func)
.on('focus', function() { input.attr('placeholder', ''); })
.on('blur', function() { input.attr('placeholder', placeholder); });
// Search reset action
$('a.reset', bar).on('click', function(e) {
// for treelist widget's search setting val and keyup.treelist is needed
// in normal search form reset-search command will do the trick
// TODO: This calls for some generalization, what about two searchboxes on a page?
input.val('').change().trigger('keyup.treelist', {keyCode: 27});
// we have to de-activate filter
// TODO: Probably that should not reset filter, but that's current Roundcube bahavior
$(bar).prev('.searchfilterbar').removeClass('active');
hide_func(e, true);
});
$('a.cancel', bar).attr('title', rcmail.gettext('close')).on('click', function(e) { hide_func(e, true); });
// These will hide the form, but not reset it
rcube_webmail.set_iframe_events({mousedown: hide_func});
$('body').on('mousedown', function(e) {
// close searchbar on mousedown anywhere, but not inside the searchbar or dialogs
if (!$(e.target).parents('.popover,.searchbar').length) {
hide_func(e);
// Reset filter
if (rcmail.gui_objects.search_filter) {
$(rcmail.gui_objects.search_filter).val('ALL');
}
});
rcmail.addEventListener('init', function() { if (input.val()) $(bar).addClass('active'); });
};
/**
* Initializes searchfilterbar widget
*/
function searchfilterbar_init(bar)
{
bar = $('<div class="searchfilterbar searchbar toolbar">')
.insertAfter(bar)
.append($(bar).detach())
.append($('<a class="button icon filter">').attr({title: rcmail.gettext('filter'), tabindex: 0}));
$('select', bar).wrap($('<div class="input-group">'))
.parent().prepend($('<span class="input-group-prepend">').append('<i class="input-group-text icon filter">'))
.append($('<span class="input-group-append">').append($('<a class="icon cancel input-group-text">')
.attr({title: rcmail.gettext('close'), href: '#'})));
var select = $('select', bar),
button = $('a.button.filter', bar),
form = $('.input-group', bar),
is_filter_enabled = function() {
var value = select.val();
return value && value != 'ALL';
},
hide_func = function(event, focus) {
bar[is_filter_enabled() ? 'addClass' : 'removeClass']('active');
if (button.is(':visible')) {
return;
}
bar.removeClass('open');
if (focus && rcube_event.is_keyboard(event)) {
button.focus();
}
};
bar.parent().addClass('with-filter');
if (is_filter_enabled()) {
bar.addClass('active');
}
select.removeClass('hidden searchfilterbar').addClass('form-control')
.on('change', function(e) { hide_func(e, true); });
if (rcmail.gui_objects.foldersfilter) {
$(rcmail.gui_objects.foldersfilter).val('---').change();
}
// Display filter selection (with animation effect)
button.on('click', function() {
bar.addClass('open');
select.focus();
update_func();
});
// Filter close button
$('a.cancel', bar).on('click', function(e) { hide_func(e, true); });
rcmail.addEventListener('init', function() {
update_func();
if (rcmail.gui_objects.search_filter) {
$(rcmail.gui_objects.search_filter).on('change', update_func);
}
// These will hide the form, but not reset it
rcube_webmail.set_iframe_events({mousedown: hide_func});
$('body').on('mousedown', function(e) {
// close searchbar on mousedown anywhere, but not inside the searchbar or dialogs
if (!$(e.target).parents('.searchfilterbar').length) {
hide_func(e);
if (rcmail.gui_objects.foldersfilter) {
$(rcmail.gui_objects.foldersfilter).on('change', update_func);
}
});
};
@ -1832,15 +1825,12 @@ function rcube_elastic_ui()
env.got_smart_toolbar = true;
var items = [];
// convert toolbar to a popup list
$('.header > .toolbar:not(.searchbar)', layout.content).each(function() {
var toolbar = $(this);
toolbar.children().each(function() {
var list_mark, items = [],
list_items = [],
meta = layout_metadata(),
button_func = function(button, items, cloned) {
var item = $('<li role="menuitem">'),
button = $(this).detach();
button = cloned ? create_cloned_button($(button), true, 'hidden-big hidden-large') : $(button).detach();
// Remove empty text nodes that break alignment of text of the menu item
button.contents().filter(function() { if (this.nodeType == 3 && !$.trim(this.nodeValue).length) $(this).remove(); });
@ -1853,10 +1843,40 @@ function rcube_elastic_ui()
}
items.push(item);
};
// convert content toolbar to a popup list
if (layout.content) {
$('.header > .toolbar', layout.content).each(function() {
var toolbar = $(this);
toolbar.children().each(function() { button_func(this, items); });
toolbar.remove();
});
}
toolbar.remove();
});
// convert list toolbar to a popup list
if (layout.list) {
$('.header > .toolbar', layout.list).each(function() {
var toolbar = $(this);
list_mark = toolbar.next();
toolbar.children().each(function() {
if (meta.mode != 'large') {
// TODO: Would be better to set this automatically on submenu display
// i.e. in show/shown event (see popup_init()), if possible
$(this).data('popup-pos', 'right');
}
// add items to the content menu too
button_func(this, items, true);
button_func(this, list_items);
});
toolbar.remove();
});
}
// special elements to clone and add to the toolbar (mobile only)
$('ul[data-menu="toolbar-small"] > li > a').each(function() {
@ -1869,6 +1889,24 @@ function rcube_elastic_ui()
items.push($('<li role="menuitem">').addClass('hidden-big').append(button));
});
// append the new list toolbar and menu button
if (list_items.length) {
var container = layout.list.children('.header'),
menu_attrs = {'class': 'toolbar popupmenu listing iconized', id: 'toolbar-list-menu'},
menu_button = $('<a class="button icon toolbar-list-button" href="#list-menu">')
.attr({'data-popup': 'toolbar-list-menu'}),
// TODO: copy original toolbar attributes (class, role, aria-*)
toolbar = $('<ul>').attr(menu_attrs).data('popup-parent', container).append(list_items);
if (list_mark.length) {
toolbar.insertBefore(list_mark);
}
else {
container.append(toolbar);
}
container.append(menu_button);
}
// append the new toolbar and menu button
if (items.length) {
var container = layout.content.children('.header'),
@ -1902,7 +1940,6 @@ function rcube_elastic_ui()
}
if (!win) win = window;
var level,
popup_id = $(item).data('popup'),
popup = $(win.$('#' + popup_id).get(0)), // a "hack" to support elements in frames
@ -2399,14 +2436,14 @@ function rcube_elastic_ui()
{
var n, all,
list = $('input[name="s_mods[]"]', obj),
scope_list = $('input[name="s_scope"]', obj),
scope_select = $('select[name=s_scope]', obj),
mbox = rcmail.env.mailbox,
mods = rcmail.env.search_mods,
scope = rcmail.env.search_scope || 'base';
if (!$(obj).data('initialized')) {
list.on('click', function() { set_searchmod(this, obj); });
scope_list.on('click', function() { rcmail.set_searchscope(this.value); });
scope_select.on('click', function() { rcmail.set_searchscope($(this).val()); });
$(obj).data('initialized', true);
}
@ -2418,7 +2455,7 @@ function rcube_elastic_ui()
mods = mods[mbox] ? mods[mbox] : mods['*'];
all = 'text';
scope_list.prop('checked', false).filter('#s_scope_' + scope).prop('checked', true);
scope_select.val(scope);
}
else {
all = '*';
@ -2433,7 +2470,7 @@ function rcube_elastic_ui()
else {
list.prop('disabled', false).prop('checked', false);
for (n in mods) {
$('#s_mod_' + n, obj).prop('checked', true);
list.filter('[value="' + n + '"]').prop('checked', true);
}
}
}
@ -2444,7 +2481,7 @@ function rcube_elastic_ui()
var all, m, task = rcmail.env.task,
mods = rcmail.env.search_mods,
mbox = rcmail.env.mailbox,
scope = $('input[name="s_scope"]:checked', menu).val();
scope = $('select[name=s_scope]', menu).val();
if (scope == 'all') {
mbox = '*';
@ -2678,6 +2715,9 @@ function rcube_elastic_ui()
rcmail.simple_dialog(p.table, 'quota', null, {cancel_button: 'close'});
});
}
else {
element.tooltip('dispose').tooltip({trigger: is_mobile() ? 'click' : 'hover'});
}
};
/**
@ -3002,15 +3042,31 @@ function rcube_elastic_ui()
select = $(select);
if (select.is('.pretty-select')) {
return;
}
var select_ident = 'select' + select.attr('id') + select.attr('name');
var is_menu_open = function() {
// Use proper window in cases when the select element intialized
// inside an iframe is then used in a dialog inside a parent's window
// For some reason we can't access data-button property in cross-window
// case, we use data-ident attribute instead
var win = select[0].ownerDocument.defaultView;
if (win.$('.select-menu .listing').data('ident') == select_ident) {
return true;
}
};
var close_func = function() {
var open = $('.select-menu').length;
var open = is_menu_open();
select.popover('dispose').focus();
return !open;
};
var open_func = function(e) {
var items = [],
dialog = select.parents('.ui-dialog')[0],
dialog = select.closest('.ui-dialog')[0],
min_width = select.outerWidth(),
max_height = $(document.body).height() - 75,
max_width = $(document.body).width() - 20,
@ -3037,11 +3093,14 @@ function rcube_elastic_ui()
});
var list = $('<ul class="toolbarmenu listing selectable iconized">')
.attr('data-ident', select_ident)
.append(items)
.data('button', select[0]) // needed for dropdown closing code
.on('click', 'a.active', function() {
select.val($(this).data('value')).change();
return close_func();
// first close the list, then update the select, the order is important
//for cases when the select might be removed in change event (datepicker)
var val = $(this).data('value'), ret = close_func();
select.val(val).change();
return ret;
})
.on('keydown', 'a.active', function(e) {
var item, node, mode = 'next';
@ -3089,7 +3148,7 @@ function rcube_elastic_ui()
})
.on('shown.bs.popover', function() {
// Set popup Close title
$('#' + select.attr('aria-describedby') + ' > .popover-header')
list.parent().prev()
.empty()
.append($('<a class="button icon cancel">').text(rcmail.gettext('close'))
.on('click', function(e) {
@ -3106,36 +3165,44 @@ function rcube_elastic_ui()
.popover('show');
};
select.on('mousedown keydown', function(e) {
// Do nothing on disabled select or on TAB key
if (select.prop('disabled') || e.which == 9) {
return;
}
select.addClass('pretty-select')
.on('mousedown keydown', function(e) {
select = $(e.target); // so it works after clone
// Close popup on ESC key
if (e.which == 27) {
return close_func();
}
// Do nothing on disabled select or on TAB key
if (select.prop('disabled')) {
return;
}
// Close popup on click if already open
if (e.type == 'mousedown' && $('.select-menu:visible .listing').data('button') == select[0]) {
return close_func();
}
if (e.which == 9) {
close_func();
return true;
}
select.focus();
// Close popup on ESC key or on click if already open
if (e.which == 27 || (e.type == 'mousedown' && is_menu_open())) {
return close_func();
}
// prevent displaying browser-default select dropdown
select.prop('disabled', true);
setTimeout(function() { select.prop('disabled', false); }, 0);
e.stopPropagation();
select.focus();
// display options in our way (on SPACE, ENTER, ARROW-DOWN or mousedown)
if (e.type == 'mousedown' || e.which == 13 || e.which == 32 || e.which == 40 || e.which == 63233) {
open_func(e);
}
// prevent displaying browser-default select dropdown
select.prop('disabled', true);
setTimeout(function() { select.prop('disabled', false); }, 0);
e.stopPropagation();
return false;
});
// display options in our way (on SPACE, ENTER, ARROW-DOWN or mousedown)
if (e.type == 'mousedown' || e.which == 13 || e.which == 32 || e.which == 40 || e.which == 63233) {
open_func(e);
return false;
}
})
.on('click', function(e) {
// Stop propagation of click event to prevent from
// disposing the menu by general popover closing handler (popups_close())
e.stopPropagation();
return false;
});
};
/**
@ -3421,7 +3488,8 @@ function rcube_elastic_ui()
*/
function window_open(url)
{
if (!is_mobile()) {
// Use 4th argument to bypass the dialog-mode e.g. for external windows
if (!is_mobile() || arguments[3] === true) {
return env.open_window.apply(rcmail, arguments);
}

Loading…
Cancel
Save