'));
$('input,select,textarea', this).addClass('form-control').wrap($('
'));
});
});
$('td.rowbuttons > a', context).addClass('btn');
// Testing Bootstrap Tabs on contact info/edit page
// Tabs do not scale nicely on very small screen, so can be used
// only with small number of tabs with short text labels
// TODO: Should we use Accordion widget instead on mobile?
$('form.tabbed,div.tabbed', context).each(function(idx, item) {
var tabs = [], nav = $('
').attr({'class': 'nav nav-tabs', role: 'tablist'});
$(this).addClass('tab-content').children('fieldset').each(function(i, fieldset) {
var tab, id = 'tab' + idx + '-' + i;
$(fieldset).addClass('tab-pane').attr({id: id, role: 'tabpanel'});
tab = $('- ').addClass('nav-item').append(
$('').addClass('nav-link')
.attr({role: 'tab', 'href': '#' + id})
.text($('legend:first', fieldset).text())
.click(function() { $(this).tab('show'); })
);
$('legend:first', fieldset).hide();
tabs.push(tab);
});
// create the navigation bar
nav.append(tabs).insertBefore(item);
// activate the first tab
$('a.nav-link:first', nav).click();
});
// Make tables pretier
$('table:not(.propform):not(.listing)', context)
.filter(function() {
// exclude direct propform children and external content
return !$(this).parent().is('.propform') && !$(this).parents('.message-htmlpart').length;
})
.each(function() {
// TODO: Consider implementing automatic setting of table-responsive on window resize
$(this).addClass('table table-responsive-sm').find('thead').addClass('thead-default');
});
$('.toolbarmenu select', context).addClass('form-control');
if (context != document) {
$('select,textarea,input:not([type="checkbox"],[type="radio"])', context).addClass('form-control');
}
// The same for some other checkboxes
// We do this here, not in setup() because we want to cover dialogs
$('.propform input[type=checkbox], .form-check > input, .popupmenu.form input[type=checkbox], .toolbarmenu input[type=checkbox]', context)
.each(function() { pretty_checkbox(this); });
// Make message-objects alerts pretty (the same as UI alerts)
$('#message-objects', context).children().each(function() {
alert_style(this, $(this).addClass('boxwarning').attr('class').split(/\s/)[0]);
$('a', this).addClass('btn btn-primary');
});
// Style calendar widget (we use setTimeout() because there's no widget event we could bind to)
$('input.datepicker').focus(function() {
setTimeout(function() { bootstrap_style($('.ui-datepicker')); }, 5);
});
// Form validation errors (managesieve plugin)
$('.error').addClass('is-invalid');
// Make logon form prettier
if (rcmail.env.task == 'login' && context == document) {
$('#login-form table tr').each(function() {
var input = $('input,select', this),
label = $('label', this),
icon = $('').attr('class', 'input-group-addon icon ' + input.attr('name').replace('_', ''));
$(this).addClass('form-group row');
label.parent().css('display', 'none');
input.addClass('form-control')
.attr('placeholder', label.text())
.before(icon)
.parent().addClass('input-group');
});
}
};
/**
* Initializes popup menus
*/
function dropdowns_init()
{
$('[data-popup]').each(function() { popup_init(this); });
// close popups on click in an iframe on the page
var close_all_popups = function(e) {
$('.popover-body:visible').each(function() {
var button = $(this).children('*:first').data('button');
if (e.target != button && typeof button !== 'string') {
$(button).popover('hide');
}
});
};
$(document).on('click', popups_close);
rcube_webmail.set_iframe_events({mousedown: popups_close});
};
/**
* Init content frame
*/
function content_frame_init()
{
var last_selected = env.last_selected,
title_reset = function() {
var title = $('h1.voice').text() || $('title').text() || '';
$('.header > .header-title', layout.content).text(title);
};
// when loading content-frame in small-screen mode display it
layout.content.find('iframe').on('load', function(e) {
var href = '', show = true;
try {
href = e.target.contentWindow.location.href;
show = !href.endsWith(rcmail.env.blankpage);
// Reset title back to the default
$(e.target.contentWindow).on('unload', title_reset);
}
catch(e) { /* ignore */ }
content_frame_navigation(href, e);
if (show && !layout.content.is(':visible')) {
env.last_selected = layout.content[0];
screen_resize();
}
else if (!show) {
if (env.last_selected != last_selected && !env.content_lock) {
env.last_selected = last_selected;
screen_resize();
}
title_reset();
}
env.content_lock = false;
});
// 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 != 'large' && !env.content_lock) {
if (rcmail.env.task == 'addressbook' || (rcmail.env.task == 'mail' && !rcmail.env.action)) {
show_list();
}
}
env.content_lock = false;
// display current folder name in list header
if (rcmail.env.task == 'mail' && !rcmail.env.action) {
var name = $.type(e) == 'string' ? e : rcmail.env.mailbox,
folder = rcmail.env.mailboxes[name];
$('.header > .header-title', layout.list).text(folder ? folder.name : '');
}
};
rcmail
.addEventListener('afterlist', list_handler)
.addEventListener('afterlistgroup', list_handler)
.addEventListener('afterlistsearch', list_handler);
};
/**
* Content frame navigation
*/
function content_frame_navigation(href, event)
{
// Don't display navigation for create/add action frames
// TODO: edit-folder should really be create-folder
if (href.match(/_action=(create|add)/) || (href.match(/_action=edit-folder/) && href.match(/_mbox=&/))) {
if (env.frame_nav) {
$(env.frame_nav).addClass('hidden');
}
return;
}
var uid, list, _list = $('[data-list]', layout.list).data('list');
if (!_list || !(list = rcmail[_list])) {
return;
}
// expand collapsed row so we do not skip the whole thread
// TODO: Unified interface for list and treelist widgets
if (uid = list.get_single_selection()) {
if (list.rows && list.rows[uid] && !list.rows[uid].expanded) {
list.expand_row(event, uid);
}
else if (list.get_node && list.get_node(uid).collapsed) {
list.expand(uid);
}
}
// TODO: Add "message X of Y" text between buttons?
if (!env.frame_nav) {
env.frame_nav = $('