Page MenuHomePhorge

No OneTemporary

Size
43 KB
Referenced Files
None
Subscribers
None
diff --git a/skins/elastic/includes/menu.html b/skins/elastic/includes/menu.html
index b25a31539..14f2568a6 100644
--- a/skins/elastic/includes/menu.html
+++ b/skins/elastic/includes/menu.html
@@ -1,10 +1,13 @@
<div id="menu" class="menu">
<h2 id="aria-label-tasknav" class="voice"><roundcube:label name="arialabeltasknav" /></h2>
<div id="taskmenu" role="navigation" aria-labelledby="aria-label-tasknav">
<roundcube:button command="mail" label="mail" type="link" class="button-mail" classSel="button-mail button-selected" innerClass="button-inner" />
<roundcube:button command="addressbook" label="contacts" type="link" class="button-addressbook" classSel="button-addressbook button-selected" innerClass="button-inner" />
<roundcube:container name="taskbar" id="taskmenu" />
<roundcube:button command="settings" label="settings" type="link" class="button-settings" classSel="button-settings button-selected" innerClass="button-inner" />
- <roundcube:button command="logout" label="logout" type="link" class="button-logout" classSel="button-logout" innerClass="button-inner" />
+ <span class="special-buttons">
+ <roundcube:button name="about" label="about" type="link" class="button-about" classSel="button-about" innerClass="button-about" onclick="UI.about_dialog(this)" />
+ <roundcube:button command="logout" label="logout" type="link" class="button-logout" classSel="button-logout" innerClass="button-inner" />
+ <span>
</div>
</div>
diff --git a/skins/elastic/styles/colors.less b/skins/elastic/styles/colors.less
index 29caef7e5..82e9fc4f5 100644
--- a/skins/elastic/styles/colors.less
+++ b/skins/elastic/styles/colors.less
@@ -1,17 +1,18 @@
// Left menu
@taskmenu-background-color: #222;
+@taskmenu-special-button-color: grey;
@taskmenu-logout-button-color: grey;
@taskmenu-logout-button-hover-color: red;
// Layout elements
@layout-border-color: #ddd;
@layout-sidebar-background-color: #fff;
@layout-list-background-color: #fff;
@layout-content-background-color: #fff;
@layout-header-background-color: #f9f9f9;
@badge-font-color: #fff;
@searchbar-icon-active-color: green;
diff --git a/skins/elastic/styles/layout.less b/skins/elastic/styles/layout.less
index e76dd2796..4fb15536a 100644
--- a/skins/elastic/styles/layout.less
+++ b/skins/elastic/styles/layout.less
@@ -1,232 +1,235 @@
@page-font-size: 1em;
@page-min-width: 240px;
/*** Responsive design - Layout ***/
/*
- Desktop - Big screen (width > 1200px)
-----------------------------------------------------------------------------------------------------
| menu | sidebar | list | content |
-----------------------------------------------------------------------------------------------------
- Desktop - Normal screen (1200px => width => 768px)
-------------------------------------------------------------------
|menu| sidebar/list | content |
-------------------------------------------------------------------
- Tablet (480px < width < 768px) - typical: 768x1024 (iPad Mini/Air)
------------------------------------------
|menu| sidebar/list/content |
------------------------------------------
- Phone (width <= 480px) - typical: 320x480 (iPhone 5), 375x667 (iPhone 6-7), 360x564 (Galaxy S6)
------------------------
| sidebar/list/content |
------------------------
NOTE: below 1024px we do some UI elements bigger, as this is good (imho)
assumption that in this size we're dealing with touch device. Is it?
should we rather feature detect tables/phones?
*/
body {
font-size: @page-font-size;
min-width: @page-min-width; /* overwrite semantic-ui's limit of 320px */
}
body > #layout {
overflow: hidden;
display: flex;
flex-direction: row;
flex-wrap: nowrap;
height: 100%;
width: 100%;
}
body > #layout > div.sidebar,
body > #layout > div.list {
display: flex;
flex-grow: 2;
flex-direction: column;
min-width: 300px;
max-width: 30%;
border-right: 1px solid @layout-border-color;
}
body > #layout > div.content {
display: flex;
flex-grow: 6;
flex-direction: column;
min-width: 50%;
background-color: @layout-content-background-color;
}
body > #layout > div.sidebar {
min-width: 220px;
background-color: @layout-sidebar-background-color;
}
body > #layout > div.list {
min-width: 300px;
background-color: @layout-list-background-color;
}
body > #layout > div.menu {
width: 60px;
background-color: @taskmenu-background-color;
}
body > #layout > div.menu a,
body > #layout > div.menu a:before {
display: block;
width: 60px;
}
body:not(.iframe) > *:not(#layout),
body > #layout > div > .header > .buttons,
body > #layout > div > .header > a.back-list-button,
body > #layout > div > .header > a.back-sidebar-button,
body > #layout > div > .header > a.toolbar-menu-button,
body > #layout > div > .header > a.menu-button {
display: none;
}
#layout > div .toolbar {
float: right;
}
#layout > div.content > iframe,
#layout > div.content > .content,
#layout > div.content > .content > iframe {
height: 100%;
width: 100%;
overflow: auto;
border: 0;
flex: 1;
}
#layout > div > .scroller {
flex: 1;
}
#layout > .content.only > .scroller {
overflow: auto;
}
#layout > div > .header,
#layout > div > .footer {
background-color: @layout-header-background-color;
font-size: 1.2em;
font-weight: bold;
line-height: 2.4em;
height: 2.4em;
padding: 0 0.5em;
margin: 0;
position: relative; /* for absolute positioning of searchbar */
/* overflow: hidden; breaks semantic-ui popups */
}
#layout > div > .header {
border-bottom: 1px solid #ddd;
}
#layout > div > .footer {
border-top: 1px solid #ddd;
}
-#taskmenu a.button-logout {
+#taskmenu .special-buttons {
position: absolute;
bottom: 0;
- color: @taskmenu-logout-button-color;
+}
+
+#taskmenu .special-buttons a {
+ color: @taskmenu-special-button-color;
}
@media screen and (max-width: 1200px) { /* small */
body > #layout > div.sidebar,
body > #layout > div.list {
min-width: 260px;
}
body > #layout > div:not(.selected),
body > #layout > div.menu span.button-inner {
display: none;
}
body > #layout > div > .header > a.back-sidebar-button {
display: inline;
}
body > #layout > div.menu,
body > #layout > div.content {
display: flex;
}
body > #layout > div.menu a,
body > #layout > div.menu a:before,
body > #layout > div.menu {
width: 45px;
}
body > #layout > div.menu a:before {
margin: 0.4em 0;
}
}
@media screen and (max-width: 768px) { /* tablet */
body {
font-size: 1.2em;
}
#layout > div > .header > .toolbar:not(.searchbar),
body > #layout > div:not(.selected) {
display: none;
}
body > #layout > div.menu {
display: flex;
}
body > #layout > div.sidebar,
body > #layout > div.list {
max-width: 100%;
}
body > #layout > div > .header > a.toolbar-menu-button,
body > #layout > div > .header > .buttons {
display: block;
float: right;
}
body > #layout > div > .header > a.back-list-button {
display: block;
float: left;
}
}
@media screen and (max-width: 480px) { /* phone */
body > #layout > div > .header > a.menu-button {
display: inline;
}
body > #layout > div.menu span.button-inner {
display: block;
}
body > #layout > div.menu {
display: none;
position: absolute;
z-index: 2;
top: 0;
left: 0;
right: 0;
width: auto;
margin: 38pt 3pt 3pt 3pt;
padding-bottom: 8pt;
opacity: 0.96;
text-align:center;
border-radius: 4pt;
}
body > #layout > div.menu a,
body > #layout > div.menu a:before {
display: inline-block;
width: 100px;
}
#taskmenu a.button-logout {
position: relative;
}
}
@media screen and (max-width: 319px) {
#layout > div > .header > .buttons > button:before {
content: "" !important;
float: none !important;
}
body > #layout > div.sidebar,
body > #layout > div.list {
min-width: @page-min-width;
}
}
diff --git a/skins/elastic/styles/styles.less b/skins/elastic/styles/styles.less
index 915e26c0d..8b0ab9e9a 100644
--- a/skins/elastic/styles/styles.less
+++ b/skins/elastic/styles/styles.less
@@ -1,659 +1,662 @@
@import (reference) "fontawesome.less";
@import (reference) "colors.less";
@import "layout.less";
/*** Login form ***/
.task-login #content {
text-align: center;
width: 100%;
background: url(images/watermark.jpg) center -20px no-repeat;
}
#login-form {
margin: auto;
width: 95%;
max-width: 320px;
}
#login-form table {
display: none;
}
#login-form div.ui.input {
width: 100%;
margin-bottom: 1em;
}
/*** Common UI elements ***/
#uploadform,
.ui.modal,
.voice {
display: none;
}
body.iframe .formcontent {
padding: 1em;
}
body.iframe .formbuttons {
padding: 0 1em 1em 1em;
}
#messagestack {
position: absolute;
bottom: 0.5em;
right: 0.5em;
z-index: 50000;
width: 300px;
height: auto;
max-height: 85%;
overflow-y: auto;
}
#messagestack div.voice {
position: absolute;
top: -1000px;
}
#messagestack div a {
color: #94c0da; /* TODO: less'ify this color */
}
#messagestack div i.icon {
font-size: 2em !important;
}
#messagestack div a:hover {
text-decoration: underline;
cursor: pointer;
}
.ui.message {
margin-top: 0.5em;
}
.ui-dialog iframe {
width: 100%;
height: 100%;
border: 0;
}
.ui-dialog-content.iframe {
padding: 0 !important;
overflow: hidden !important;
}
.ui.popup {
padding: 0;
min-width: 180px;
}
.button.disabled,
.listing li a.disabled {
opacity: 0.5;
}
.listbox .scroller {
width: 100%;
overflow-x: hidden;
overflow-y: auto;
}
.listing tbody td,
.listing li {
display: block;
border-bottom: 1px solid #f4f4f4;
cursor: default;
font-weight: normal;
}
.listbox .listitem a,
.listbox .listitem span,
.listbox .tablink a,
.listing tbody td,
.listing li a {
display: block;
text-decoration: none;
cursor: default;
padding: 0 0.5em;
white-space: nowrap;
vertical-align: middle;
line-height: 2.4em;
}
.listing tbody td {
display: table-cell;
outline: none;
}
table.listing {
width: 100%;
}
ul.listing {
display: block;
list-style: none;
margin: 0;
padding: 0;
}
ul.listing li {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
position: relative;
}
ul.listing li ul {
border-top: 1px solid #f4f4f4;
padding-left: 1.5em;
}
ul.listing li ul li:last-child {
border-bottom: none;
}
ul.treelist li div.treetoggle {
position: absolute;
top: 7px;
left: 4px;
width: 13px;
height: 13px;
background: /* TODO */ no-repeat;
cursor: pointer;
}
.folderlist li.mailbox .unreadcount {
position: absolute;
top: 0;
right: 0;
min-width: 2em;
line-height: 1.4em;
margin: 0.5em 0.2em;
padding: 0 0.3em;
background: /* todo */ #1e70bf;
border-radius: 0.4em;
color: @badge-font-color;
text-align: center;
font-weight: bold;
}
ul.listing li input[type=checkbox] {
position: absolute;
top: 0;
right: 0.2em;
height: 2.4em;
vertical-align: middle;
}
.folderlist li.mailbox.selected > a .unreadcount {
background: /* todo */;
}
.folderlist li.mailbox.recent > a .unreadcount {
background: /* todo */;
}
.toolbar {
height: 2.4em;
}
.toolbar .ui.popup,
.toolbar.ui.popup {
height: auto;
}
.toolbar > .spacer {
display: inline-block;
width: 1.2em;
}
.toolbar a.button span.inner {
display: none;
}
.searchbar {
display: table;
text-align: right;
position: absolute;
background-color: @layout-header-background-color;
z-index: 10;
top: 0;
right: 0;
}
.searchbar > * {
height: 2.4em;
}
.searchbar > form,
.searchbar > a.button.options,
.searchbar > a.button.reset {
display: none;
width: 1%;
}
.searchbar > form,
.searchbar > form > input {
width: 98%;
}
.searchbar input {
border: none;
border-bottom: 1px solid #ddd;
background: transparent;
}
.searchbar > a.button.search.active {
color: @searchbar-icon-active-color;
}
.header > .buttons > input.button {
padding: 0.3em 0.8em;
font-size: 1em;
}
/* fixes border set by accordion widget */
.propform.ui.accordion td.title {
border: none;
}
/* make some elements bigger on tablets/phones */
/* TODO: we should/could maybe do this more globally? */
@media screen and (max-width: 1024px) {
}
@media screen and (min-width: 769px) {
ul.toolbar {
margin: 0;
}
ul.toolbar > li {
display: inline-block;
}
}
@media screen and (max-width: 768px) {
ul.toolbar a.button .inner {
display: inline;
}
}
@media screen and (max-width: 480px) {
#messagestack {
left: 0.5em;
width: auto;
}
}
/* font-icons */
button.ui.button.icon:before,
.toolbar a.button:before,
.toolbarmenu li a:before,
.folderlist li a:before,
.listing.iconized tr td:before,
.listing.iconized li a:before,
#taskmenu a:before {
font-size: 1.25em;
/*display: inline-block;*/
/* FIXME: with inline-block we have a problem with icon alignment,
use display:block; float: left;
*/
display: block;
float: left;
margin: 0em 0.25rem 0em 0em;
width: 1.18em;
height: 1em;
font-family: 'Icons';
font-style: normal;
font-weight: normal;
text-decoration: inherit;
text-align: center;
speak: none;
font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
-webkit-font-smoothing: antialiased;
-webkit-backface-visibility: hidden;
backface-visibility: hidden;
}
button.ui.button.icon:before {
height: auto;
}
.toolbar a.button:before {
display: inline;
float: initial;
}
.toolbar a.button {
padding: 0 0.3em;
}
.toolbar .dropbutton > a.button:first-child {
padding-right: 0;
}
.toolbar .dropbutton > a.button.dropdown {
font-size: 70%;
padding-left: 0;
}
#taskmenu a {
padding: 0.4em 0;
}
#taskmenu a,
#taskmenu a:before {
display: block;
width: 60px;
text-align: center;
}
#taskmenu a:before {
font-size: 1.5em;
margin-bottom: 0.1em;
}
#taskmenu a.button-mail:before {
content: @fa-var-envelope;
}
#taskmenu a.button-addressbook:before {
content: @fa-var-user;
}
#taskmenu a.button-settings:before {
content: @fa-var-cog;
}
#taskmenu a.button-help:before {
content: @fa-var-life-bouy;
}
#taskmenu a.button-logout:before {
content: @fa-var-power-off;
}
+#taskmenu a.button-about:before {
+ content: @fa-var-question;
+}
#taskmenu a.button-logout:hover {
color: @taskmenu-logout-button-hover-color;
}
.listing.iconized li.preferences > a:before {
content: @fa-var-sliders;
}
.listing.iconized li.folders > a:before {
content: @fa-var-folder;
}
.listing.iconized li.responses > a:before {
content: @fa-var-comment;
}
.listing.iconized li.identities > a:before {
content: @fa-var-at;
}
.listing.iconized li.password > a:before {
content: @fa-var-lock;
}
.listing.iconized li.addressbook a:before {
content: @fa-var-book;
}
.listing.iconized li.contactgroup a:before {
content: @fa-var-group;
}
.listing.iconized li.contactsearch a:before {
content: @fa-var-search;
}
.listing.iconized tr.contact.person td.name:before {
content: @fa-var-user;
}
.listing.iconized tr.general > td.section:before {
content: @fa-var-desktop;
}
.listing.iconized tr.mailbox > td.section:before {
content: @fa-var-envelope-o;
}
.listing.iconized tr.mailview > td.section:before {
content: @fa-var-inbox;
}
.listing.iconized tr.compose > td.section:before {
content: @fa-var-paper-plane;
}
.listing.iconized tr.addressbook > td.section:before {
content: @fa-var-user;
}
.listing.iconized tr.folders > td.section:before {
content: @fa-var-folder-o;
}
.listing.iconized tr.server > td.section:before {
content: @fa-var-server;
}
.folderlist li a:before {
content: @fa-var-folder-o;
}
.folderlist li.inbox a:before {
content: @fa-var-inbox;
}
.folderlist li.trash a:before {
content: @fa-var-trash;
}
.folderlist li.trash.empty a:before {
content: @fa-var-trash-o;
}
.folderlist li.drafts a:before {
content: @fa-var-edit;
}
.folderlist li.sent a:before {
content: @fa-var-paper-plane;
}
.folderlist li.junk a:before {
content: ""; /* TODO */
}
.folderlist li.archive a:before {
content: @fa-var-archive;
}
.toolbarmenu li a.print:before {
content: @fa-var-print;
}
.toolbarmenu li a.copy:before {
content: @fa-var-copy;
}
.toolbarmenu li a.move:before {
content: @fa-var-arrows;
}
.toolbarmenu li a.source:before {
content: @fa-var-flask;
}
.toolbarmenu li a.download:before {
content: @fa-var-download;
}
.toolbarmenu li a.extwin:before {
content: @fa-var-external-link;
}
.toolbarmenu li a.edit:before {
content: @fa-var-edit; /* TODO: edit.asnew */
}
.toolbarmenu li a.read:before {
content: @fa-var-star-o;
}
.toolbarmenu li a.unread:before {
content: @fa-var-star;
}
.toolbarmenu li a.flag:before {
content: @fa-var-flag;
}
.toolbarmenu li a.unflag:before {
content: @fa-var-flag-o;
}
.toolbar a.button.reply:before {
content: @fa-var-mail-reply;
}
.toolbar a.button.reply-all:before {
content: @fa-var-mail-reply-all;
}
.toolbar a.button.forward:before {
content: @fa-var-mail-forward;
}
.toolbar a.button.delete:before {
content: @fa-var-trash-o;
}
.toolbar a.button.markmessage:before {
content: @fa-var-tag;
}
.toolbar a.button.more:before {
content: @fa-var-ellipsis-h;
}
.toolbar a.button.dropdown:before {
content: @fa-var-caret-down;
}
.toolbar a.button.settings:before {
content: @fa-var-cog;
}
.toolbar a.button.print:before {
content: @fa-var-print;
}
.toolbar a.button.search:before {
content: @fa-var-search;
}
.toolbar a.button.upload:before,
.toolbar a.button.import:before {
content: @fa-var-upload;
}
.toolbar a.button.download:before,
.toolbar a.button.export:before {
content: @fa-var-download;
}
.toolbar a.button.compose:before {
content: @fa-var-edit;
}
.toolbar a.button.refresh:before {
content: @fa-var-refresh;
}
.toolbar a.button.archive:before {
content: @fa-var-archive;
}
.toolbar a.button.encrypt:before {
content: @fa-var-lock;
}
.toolbar a.button.firstpage:before {
content: @fa-var-fast-backward;
}
.toolbar a.button.prevpage:before {
content: @fa-var-backward;
}
.toolbar a.button.nextpage:before {
content: @fa-var-forward;
}
.toolbar a.button.lastpage:before {
content: @fa-var-fast-forward;
}
.searchbar > a.button.reset:before {
content: @fa-var-remove;
}
.searchbar > a.button.options:before {
content: @fa-var-angle-down;
}
button.icon.save:before {
content: @fa-var-check;
}
button.icon.edit:before {
content: @fa-var-pencil;
}
button.icon.qrcode:before {
content: @fa-var-qrcode;
}
button.icon.search:before {
content: @fa-var-search;
}
/**** Styles for widescreen (3-column) view ****/
/* copied from larry removing .widescreen prefix */
.messagelist > thead,
.messagelist .branch,
table.fixedcopy {
display: none;
}
.messagelist td {
border-left: 0;
vertical-align: top;
padding: 3px 2px !important;
}
.messagelist td.subject {
width: 99%;
white-space: wrap;
position: relative; /* for span.date positioning in Firefox */
}
.messagelist td.threads {
width: 20px;
vertical-align: bottom;
}
.messagelist td.threads div {
padding-bottom: 1px;
}
.messagelist td.flags {
width: 22px;
}
.messagelist td.subject span {
line-height: 2em;
}
.messagelist td.subject span.date {
right: 2px;
top: 3px;
position: absolute;
color: #666; /* TODO */
}
.messagelist td.subject span.fromto {
padding-left: 1.5em;
display: block;
margin-right: 10em;
overflow: hidden;
text-overflow: ellipsis;
color: #666; /* TODO */
}
.messagelist tr.flagged td.subject span.date,
.messagelist tr.flagged td.subject span.fromto {
color: #ff5c33; /* TODO */
}
.messagelist tr.deleted td.subject span.date,
.messagelist tr.deleted td.subject span.fromto {
color: #ccc; /* TODO */
}
.messagelist td.subject span.subject {
clear: both;
display: block;
font-size: 1em;
overflow: hidden;
text-overflow: ellipsis;
}
.messagelist td.flags span {
width: 20px;
height: 20px;
display: block;
margin-left: 1px;
}
.messagelist td.flags span.flag {
cursor: pointer;
}
.messagelist tr td.subject span.msgicon,
.messagelist tr td.subject span.unreadchildren {
width: 20px;
height: 20px;
}
diff --git a/skins/elastic/templates/about.html b/skins/elastic/templates/about.html
new file mode 100644
index 000000000..5d0126372
--- /dev/null
+++ b/skins/elastic/templates/about.html
@@ -0,0 +1,20 @@
+<roundcube:include file="/includes/layout.html" />
+
+<roundcube:object name="aboutcontent" />
+
+<div>
+ <h2 class="sysname">Roundcube Webmail <roundcube:object name="version" /></h2>
+ <p class="copyright">Copyright &copy; 2005-2016, The Roundcube Dev Team</p>
+ <p class="license">This program is free software;
+ you can redistribute it and/or modify it under the terms of the
+ <a href="http://www.gnu.org/licenses/gpl.html" target="_blank">GNU General Public License</a>
+ as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.<br/>
+ Some <a href="https://roundcube.net/license" target="_blank">exceptions</a> for skins &amp; plugins apply.
+ </p>
+ <div class="readtext">
+ <h3><roundcube:label name="installedplugins" /></h3>
+ <roundcube:object name="pluginlist" id="pluginlist" class="records-table" />
+ </div>
+</div>
+
+<roundcube:include file="/includes/footer.html" />
diff --git a/skins/elastic/ui.js b/skins/elastic/ui.js
index 901507b7c..eee7e86f1 100644
--- a/skins/elastic/ui.js
+++ b/skins/elastic/ui.js
@@ -1,634 +1,654 @@
"use strict";
function rcube_elastic_ui()
{
var mode = 'normal', // one of: wide, normal, tablet, phone
env = {},
content_buttons = [];
var layout = {
menu: $('#layout > .menu'),
sidebar: $('#layout > .sidebar'),
list: $('#layout > .list'),
content: $('#layout > .content'),
};
var buttons = {
menu: $('a.menu-button'),
back_sidebar: $('a.back-sidebar-button'),
back_list: $('a.back-list-button'),
};
// public methods
this.register_frame_buttons = register_frame_buttons;
+ this.about_dialog = about_dialog;
env.last_selected = $('#layout > div.selected')[0];
$(window).on('resize', function() {
clearTimeout(env.resize_timeout);
env.resize_timeout = setTimeout(function() { resize(); }, 25);
}).resize();
$('body').on('click', function() { if (mode == 'phone') layout.menu.hide(); });
// when loading content-frame in small-screen mode display it
layout.content.find('iframe').on('load', function(e) {
var show = !e.target.contentWindow.location.href.endsWith(rcmail.env.blankpage);
if (show && !layout.content.is(':visible')) {
env.last_selected = layout.content[0];
screen_resize();
}
});
// display the list widget after 'list' and 'listgroup' commands
// @TODO: plugins should be able to do the same
var list_handler = function(e) {
if (mode != 'wide') {
if (rcmail.env.task == 'addressbook' || (rcmail.env.task == 'mail' && !rcmail.env.action)) {
show_list();
}
}
// display current folder name in list header
if (rcmail.env.task == 'mail' && !rcmail.env.action) {
var name = $.type(e) == 'string' ? e : rcmail.env.mailbox;
var folder = rcmail.env.mailboxes[name];
$('#folder-name').text(folder ? folder.name : '');
}
};
rcmail
.addEventListener('afterlist', list_handler)
.addEventListener('afterlistgroup', list_handler)
.addEventListener('afterlistsearch', list_handler)
.addEventListener('message', message_displayed)
.addEventListener('menu-open', menu_toggle)
.addEventListener('menu-close', menu_toggle);
// menu/sidebar button
buttons.menu.on('click', function() { show_menu(); return false; });
buttons.back_sidebar.on('click', function() { show_sidebar(); return false; });
buttons.back_list.on('click', function() {
if (!layout.list.length && !layout.sidebar.length) {
history.back();
}
else {
hide_content();
}
return false;
});
// Semantic-UI style
$('input.button').addClass('ui');
$('input.button.mainaction').addClass('primary');
// TODO: Most of this style-related code should not be needed
// We should implement some features in the core that would
// allow as to tell the engine to add additional html code/attribs
$('select').dropdown();
// Make forms pretty with semantic-ui's accordion widget
// TODO: Consider using tabs when the page width is big enough
$('form.propform,.tabbed').each(function() {
var form = $(this), fieldsets = form.children('fieldset');
if (fieldsets.length) {
$(this).addClass('ui styled fluid accordion');
fieldsets.each(function(i, fieldset) {
var title = $('<div>').attr('class', 'title' + (i ? '' : ' active'))
.html('<i class="dropdown icon"></i>')
.append($('<span>').text($('legend', fieldset).text()));
var content = $('<div>').attr('class', 'content' + (i ? '' : ' active'))
.append($(fieldset).children().not('legend'));
form.append(title).append(content);
$(fieldset).remove();
});
form.accordion({animateChildren: false});
}
});
// Initialize responsive toolbars (have to be before popups init)
toolbar_init();
// Initialize menu dropdowns
$('*[data-popup]').each(function() { popup_init(this); });
// close popups on click in an iframe on the page
var close_all_popups = function() {
$('.ui.popup:visible').each(function() {
$($(this).data('button')).popup('hide');
});
};
rcube_webmail.set_iframe_events({mousedown: close_all_popups});
// Move form buttons from the content frame into the frame header (on parent window)
// TODO: Active button state
var form_buttons = [];
$('.formbuttons').children(':not(.cancel)').each(function() {
var target = $(this);
// skip non-content buttons
if (!rcmail.is_framed() && !target.parents('.content').length) {
return;
}
var button = target.clone();
form_buttons.push(
button.attr({'onclick': '', disabled: false, id: button.attr('id') + '-clone'})
.data('target', target)
.on('click', function(e) { target.click(); })
);
});
if (form_buttons.length) {
if (rcmail.is_framed()) {
if (parent.UI) {
parent.UI.register_frame_buttons(form_buttons);
}
}
else
register_frame_buttons(form_buttons);
}
function register_frame_buttons(buttons)
{
// we need these buttons really only in phone mode
if (/*mode == 'phone' && */layout.content.length && buttons && buttons.length) {
var header = layout.content.children('.header');
if (header.length) {
var toolbar = header.children('.buttons');
if (!toolbar.length)
toolbar = $('<span class="buttons">').appendTo(header);
content_buttons = [];
toolbar.html('');
$.each(buttons, function() {
toolbar.append(this);
content_buttons.push(this.data('target'));
});
resize();
}
}
}
// Initialize search forms (in list headers)
$('.header > .searchbar').each(function() { searchbar_init(this); });
// Make login form pretty
if (rcmail.env.task == 'login') {
var inputs = [],
icon_map = {user: 'user', pass: 'lock', host: 'home'},
table = $('#login-form table');
$('tr', table).each(function() {
var input = $('input', this).detach(),
input_name = input.attr('name').replace('_', ''),
icon = $('<i>').attr('class', 'icon ' + icon_map[input_name]);
input.attr('placeholder', $('label', this).text());
inputs.push($('<div>').attr('class', 'ui left icon input').append([input, icon]));
});
table.after(inputs);
}
// Intercept jQuery-UI dialogs to re-style them
$.widget('ui.dialog', $.ui.dialog, {
open: function() {
this._super();
dialog_open(this);
return this;
}
});
// window resize handler
function resize()
{
var size, width = $(window).width();
if (width <= 480)
size = 'phone';
else if (width > 1200)
size = 'wide';
else if (width <= 768)
size = 'tablet';
else
size = 'normal';
mode = size;
screen_resize();
display_screen_size(); // debug info
};
// for development only
function display_screen_size()
{
if ($('body.iframe').length)
return;
var div = $('#screen-size'), win = $(window);
if (!div.length) {
div = $('<div>').attr({
id: 'screen-size',
style: 'position:absolute;display:block;right:0;bottom:0;z-index:100;'
+ 'opacity:0.5;color:white;background-color:black;white-space:nowrap'
}).appendTo(document.body);
}
div.text(win.width() + ' x ' + win.height() + ' (' + mode + ')');
};
function screen_resize()
{
switch (mode) {
case 'phone': screen_resize_phone(); break;
case 'tablet': screen_resize_tablet(); break;
case 'normal': screen_resize_normal(); break;
case 'wide': screen_resize_wide(); break;
}
};
function screen_resize_phone()
{
screen_resize_small();
layout.menu.hide();
};
function screen_resize_tablet()
{
screen_resize_small();
layout.menu.css('display', 'flex');
};
function screen_resize_small()
{
var show, got_content = false;
if (layout.content.length) {
show = got_content = layout.content.is(env.last_selected);
layout.content.css('display', show ? 'flex' : 'none');
}
if (layout.list.length) {
show = !got_content && layout.list.is(env.last_selected);
layout.list.css('display', show ? 'flex' : 'none');
}
if (layout.sidebar.length) {
show = !got_content && (layout.sidebar.is(env.last_selected) || !layout.list.length);
layout.sidebar.css('display', show ? 'flex' : 'none');
}
if (got_content) {
buttons.back_list.show();
}
$('.header > ul.toolbar', layout.content).addClass('hidden ui popup');
$.each(content_buttons, function() { $(this).hide(); });
};
function screen_resize_normal()
{
var show;
if (layout.list.length) {
show = layout.list.is(env.last_selected) || !layout.sidebar.is(env.last_selected);
layout.list.css('display', show ? 'flex' : 'none');
}
if (layout.sidebar.length) {
show = !layout.list.length || layout.sidebar.is(env.last_selected);
layout.sidebar.css('display', show ? 'flex' : 'none');
}
layout.content.css('display', 'flex');
layout.menu.css('display', 'flex');
buttons.back_list.hide();
$.each(content_buttons, function() { $(this).show(); });
$('ul.toolbar.ui.popup').removeClass('hidden ui popup');
};
function screen_resize_wide()
{
$.each(layout, function(name, item) { item.css('display', 'flex'); });
buttons.back_list.hide();
$.each(content_buttons, function() { $(this).show(); });
$('ul.toolbar.ui.popup').removeClass('hidden ui popup');
};
function show_sidebar()
{
// show sidebar and hide list
layout.list.hide();
layout.sidebar.css('display', 'flex');
};
function show_list()
{
// show list and hide sidebar
layout.sidebar.hide();
layout.list.css('display', 'flex');
};
function hide_content()
{
// show sidebar or list, hide content frame
//$(layout.content).hide();
env.last_selected = layout.list[0] || layout.sidebar[0];
screen_resize();
// reset content frame, so we can load it again
rcmail.show_contentframe(false);
// or env.content_window.location.href = rcmail.env.blankpage; ?
// now we have to unselect selected row on the list
// TODO: do this with some magic, so it works for plugins UI
// e.g. we could store list widget reference in list container data
if (rcmail.env.task == 'settings' && !rcmail.env.action) {
rcmail.sections_list.clear_selection();
}
else if (rcmail.env.task == 'addressbook' && !rcmail.env.action) {
rcmail.contact_list.clear_selection();
}
};
// show menu widget
function show_menu()
{
var display = 'flex';
if (mode == 'phone') {
display = layout.menu.is(':visible') ? 'none' : 'block';
}
layout.menu.css('display', display);
};
/**
* Triggered when a UI message is displayed
*/
function message_displayed(p)
{
var icon, classes = 'ui icon message',
map = {
information: ['success', 'info circle icon'],
confirmation: ['success', 'info circle icon'],
notice: ['', 'info circle icon'],
error: ['negative', 'warning circle icon'],
warning: ['negative', 'warning sign icon'],
loading: ['', 'notched circle loading icon']
};
if (icon = map[p.type]) {
if (icon[0])
classes += ' ' + icon[0];
$('<i>').attr('class', icon[1]).prependTo(p.object);
}
$(p.object).addClass(classes);
/*
var siblings = $(p.object).siblings('div');
if (siblings.length)
$(p.object).insertBefore(siblings.first());
// show a popup dialog on errors
if (p.type == 'error' && rcmail.env.task != 'login') {
// hide original message object, we don't want both
rcmail.hide_message(p.object);
}
*/
};
/**
* Initializes searchbar widget
*/
function searchbar_init(bar)
{
var input = $('input', bar),
button = $('a.button.search', bar),
form = $('form', bar),
all_elements = $('form, a.button.options, a.button.reset', 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) {
// TODO: This animation in Chrome does not look as good as in Firefox
$(bar).animate({'width': '0'}, 200, 'swing', function() {
all_elements.hide();
$(bar).width('auto'); // fixes search button position in Chrome
button[is_search_pending() ? 'addClass' : 'removeClass']('active')
.css('display', 'inline-block');
if (focus) {
button.focus();
}
});
};
if (is_search_pending()) {
button.addClass('active');
}
// Display search form (with animation effect)
button.on('click', function() {
$(bar).animate({'width': '100%'}, 200);
all_elements.css('display', 'table-cell');
button.hide();
input.focus();
});
// Search reset action
$('a.button.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});
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) {
if (!button.is(':visible') && $.inArray(bar, $(e.target).parents()) == -1) {
hide_func(e);
}
});
};
/**
* Converts toolbar menu into popup-menu for small screens
*/
function toolbar_init()
{
if (env.got_smart_toolbar) {
return;
}
env.got_smart_toolbar = true;
// TODO: if the toolbar contains "global or list only" buttons
// another popup menu with these options should be created
// on the list (or sidebar if there's no list element).
// TODO: spacer item
// TODO: dropbutton item
// TODO: a way to inject buttons to the menu from content iframe
var items = [], buttons_with_popup = [];
// convert toolbar to a popup list
$('.header > .toolbar', layout.content).each(function() {
var toolbar = $(this);
toolbar.children().each(function() {
var button = $(this).detach();
$('[data-popup]', button).each(function() {
buttons_with_popup.push(this);
});
items.push($('<li role="menuitem">').append(button));
});
});
// append the new toolbar and menu button
if (items.length) {
var menu_button = $('<a class="button toolbar-menu-button" href="#menu">')
.html('<i class="icon ellipsis vertical"></i>')
.attr({'data-popup': 'toolbar-menu', 'data-popup-pos': 'bottom right'});
layout.content.children('.header')
// TODO: copy original toolbar attributes (class, role, aria-*)
.append($('<ul>').attr({'class': 'toolbar ui popup', id: 'toolbar-menu'}).append(items))
.append(menu_button);
// TODO: A menu converted to a popup will be hidden on click in the body
// we do not want that
}
};
/**
* Initialize a popup for specified button element
*/
function popup_init(item)
{
var popup_id = $(item).data('popup'),
popup = $('#' + popup_id)[0],
popup_position = $(item).data('popup-pos') || 'bottom left';
$(item).attr({
'aria-haspopup': 'true',
'aria-expanded': 'false',
'aria-owns': popup_id
})
.popup({
popup: popup,
exclusive: true,
on: 'click',
position: popup_position,
lastResort: true
});
// TODO: Set aria attributes on menu show/hide
// TODO: Set popup height so it is less that window height
$(popup).attr('aria-hidden', 'true')
.data('button', item);
};
/**
* Set UI dialogs size/style depending on screen size
*/
function dialog_open(dialog)
{
var me = $(dialog.uiDialog),
width = me.width(),
height = me.height(),
maxWidth = $(window).width(),
maxHeight = $(window).height();
if (maxWidth <= 480) {
me.css({width: '100%', height: '100%'});
}
else {
if (height > maxHeight) {
me.css('height', '100%');
}
if (width > maxWidth) {
me.css('width', '100%');
}
}
// TODO: style buttons/forms
};
/**
* Handler for menu-open and menu-close events
*/
function menu_toggle(p)
{
if (p && p.name == 'messagelistmenu') {
menu_messagelist(p);
}
};
/**
* Messages list options dialog
*/
function menu_messagelist(p)
{
var content = $('#listoptions-menu'),
width = content.width() + 25,
dialog = content.clone();
// set form values
$('input[name="sort_col"][value="'+rcmail.env.sort_col+'"]', dialog).prop('checked', true);
$('input[name="sort_ord"][value="DESC"]', dialog).prop('checked', rcmail.env.sort_order == 'DESC');
$('input[name="sort_ord"][value="ASC"]', dialog).prop('checked', rcmail.env.sort_order != 'DESC');
// set checkboxes
$('input[name="list_col[]"]', dialog).each(function() {
$(this).prop('checked', $.inArray(this.value, rcmail.env.listcols) != -1);
});
dialog.removeClass('popup');
var save_func = function(e) {
if (rcube_event.is_keyboard(e.originalEvent)) {
$('#listmenulink').focus();
}
var sort = $('input[name="sort_col"]:checked', dialog).val(),
ord = $('input[name="sort_ord"]:checked', dialog).val(),
layout = $('input[name="layout"]:checked', dialog).val(),
cols = $('input[name="list_col[]"]:checked', dialog)
.map(function() { return this.value; }).get();
rcmail.set_list_options(cols, sort, ord, rcmail.env.threading, layout);
return true;
};
rcmail.simple_dialog(dialog, rcmail.gettext('listoptionstitle'), save_func, {
closeOnEscape: true,
open: function(e) {
setTimeout(function() { dialog.find('a, input:not(:disabled)').not('[aria-disabled=true]').first().focus(); }, 100);
},
minWidth: 500,
width: width
});
};
+
+ function about_dialog(elem)
+ {
+ var support_url, support_func, support_button = false,
+ dialog = $('<iframe>').attr({id: 'aboutframe', src: rcmail.url('settings/about', {_framed: 1})}),
+ support_link = $('#supportlink');
+
+ // TODO: 'Get Support' link/button
+ if (support_link.length && (support_url = support_link.attr('href'))) {
+ support_button = support_link.html();
+ support_func = function(e) { support_url.indexOf('mailto:') < 0 ? window.open(support_url) : location.href = support_url };
+ }
+
+ rcmail.simple_dialog(dialog, $(elem).text(), support_func, {
+ button: support_button,
+ width: 600,
+ height: 400
+ });
+ };
}
var UI = new rcube_elastic_ui();

File Metadata

Mime Type
text/x-diff
Expires
Thu, Dec 18, 1:29 PM (1 d, 15 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
418837
Default Alt Text
(43 KB)

Event Timeline