One Hat Cyber Team
  • Dir : ~/usr/share/psa-roundcube/skins/elastic/
  • View File Name : ui.js
    // var sw, is_table = false, editor = $(obj), parent = editor.parent(), readonly = editor.is('[readonly],[disabled]'), plain_btn = $('') .attr({title: rcmail.gettext('htmltoggle'), disabled: readonly}) .on('click', function(e) { if (!readonly && rcmail.command('toggle-editor', {id: editor.attr('id'), html: true}, '', e.originalEvent)) { parent.addClass('ishtml'); } }) .on('keydown', function(e) { if (e.which == 9) { // TAB editor.focus(); return false; } }), toolbar = $('
    ').append(plain_btn); if (parent.is('td')) { sw = $('input[type="checkbox"]', parent.parent().next()); is_table = true; } else { sw = editor.next('select.hidden'); } // make the textarea autoresizeable textarea_autoresize_init(obj); // sanity check if (sw.length != 1) { return; } parent.addClass('html-editor'); editor.after(toolbar).data('control', sw) .on('keydown', function(e) { // ALT + F10 is the way to access toolbar in TinyMCE, let's do the same for plain editor if (e.altKey && e.which == 121) { plain_btn.focus(); } }); if (is_table) { // Hide unwanted table cells sw.parents('tr').first().hide(); parent.prev().hide(); // Modify the textarea cell to use 100% width parent.addClass('col-sm-12'); } }; /** * Make the textarea autoresizeable depending on it's content length. * The way there's no vertical scrollbar. */ function textarea_autoresize_init(textarea) { var padding, minHeight, resize = function() { // Wait until the textarea is visible if (!textarea.scrollHeight) { return setTimeout(resize, 250); } if (!padding) { padding = parseInt($(textarea).css('padding-top')) + parseInt($(textarea).css('padding-bottom')) + 2; minHeight = $(textarea).height(); } if (textarea.scrollHeight - padding <= minHeight) { return; } // To fix scroll-jump we'll re-apply scrollTop to the (scrolled) parent // after we reset textarea height var scroll_element, scroll_pos = 0; $(textarea).parents().each(function() { if (this.scrollTop > 0) { scroll_element = this; scroll_pos = this.scrollTop; return false; } }); var oldHeight = $(textarea).outerHeight(); $(textarea).outerHeight(0); var newHeight = Math.max(minHeight, textarea.scrollHeight); $(textarea).outerHeight(oldHeight); if (newHeight !== oldHeight) { $(textarea).height(newHeight); } if (scroll_pos) { scroll_element.scrollTop = scroll_pos; } }; $(textarea).on('input', resize); setTimeout(resize, 100); }; // Initializes smart list input function smart_field_init(field) { var tip, id = field.id + '_list', area = $('
    '), list = field.value ? field.value.split("\n") : ['']; if ($('#' + id).length) { return; } // add input rows $.each(list, function(i, v) { smart_field_row_add($('.content', area), v, i, field); }); area.attr('id', id); field = $(field); if (field.attr('disabled')) { area.hide(); } // disable the original field anyway, we don't want it in POST else { field.prop('disabled', true); } if (field.data('hidden')) { area.hide(); } field.after(area); if (field.hasClass('is-invalid')) { area.addClass('is-invalid'); $('.invalid-feedback', area).text(field.data('error-msg')); } }; function smart_field_row_add(area, value, idx, field, after) { // build row element content var input, elem = $('
    ' + '' + '' + '
    '); input = elem.find('input').attr({ value: value, name: field.name + '[]', size: $(field).data('size'), title: field.title, placeholder: field.placeholder }) .keydown(function(e) { // element creation event (on Enter) if (e.which == 13) { var elem = smart_field_row_add(area, '', (new Date()).getTime(), field, input.parent()); $('input', elem).focus(); } // backspace or delete: remove input, focus previous one else if ((e.which == 8 || e.which == 46) && input.val() == '') { var parent = input.parent(), siblings = area.children(); if (siblings.length > 1) { if (parent.prev().length) { parent.prev().children('input').focus(); } else { parent.next().children('input').focus(); } parent.remove(); return false; } } }); // element deletion event elem.find('a.reset').click(function() { var record = $(this.parentNode.parentNode); if (area.children().length > 1) { $('input', record.next().length ? record.next() : record.prev()).focus(); record.remove(); } else { $('input', record).val('').focus(); } }); elem.find('input,a') .on('focus', function() { area.addClass('focused'); }) .on('blur', function() { area.removeClass('focused'); }); if (after) { after.after(elem); } else { elem.appendTo(area); } return elem; }; // Reset and fill the smart list input with new data function smart_field_reset(field, data) { var id = field.id + '_list', list = data.length ? data : [''], area = $('#' + id).children('.content'); area.empty(); // add input rows $.each(list, function(i, v) { smart_field_row_add(area, v, i, field); }); }; /** * Register form errors, mark fields as invalid, display the error below the input */ function form_errors(tips) { $.each(tips, function() { var input = $('#' + this[0]).addClass('is-invalid'); if (input.data('type') == 'list') { input.data('error-msg', this[2]); $('#' + this[0] + '_list > .invalid-feedback').text(this[2]); return; } input.after($('').text(this[2])); }); }; /** * Show/hide the navigation list */ function switch_nav_list(obj) { var records, height, speed = 250, button = $('a', obj), navlist = $(obj).next(); if (!navlist.height()) { records = $('tr,li', navlist).filter(function() { return this.style.display != 'none'; }); height = $(records[0]).height() || 50; navlist.animate({height: (Math.min(5, records.length) * height + 1) + 'px'}, speed); button.addClass('collapse').removeClass('expand'); $(obj).addClass('expanded'); } else { navlist.animate({height: '0'}, speed); button.addClass('expand').removeClass('collapse'); $(obj).removeClass('expanded'); } }; /** * Create a splitter (resizing) element on a layout column */ function splitter_init(node) { // Use id of the list element, if exists, as a part of the key, instead of action.column-id // This way e.g. the sidebar in Settings is always the same width for all Settings' pages var list_id = node.find('.scroller .listing').first().attr('id'), key = rcmail.env.task + '.' + (list_id || (rcmail.env.action + '.' + node.attr('id'))), pos = get_pref(key), inverted = node.is('.sidebar-right'), set_width = function(width) { node.css({ width: Math.max(100, width), // reset default properties // 'min-width': 100, flex: 'none' }); }; if (!node[inverted ? 'prev' : 'next']().length) { return; } $('
    ') .addClass(inverted ? 'inverted' : null) .appendTo(node) .on('mousedown', function(e) { var ts, splitter = $(this), offset = node.position().left; // Makes col-resize cursor follow the mouse pointer on dragging // and fixes issues related to iframes splitter.addClass('active'); // Disable selection on document while dragging // It can happen when you move mouse out of window, on top document.body.style.userSelect = 'none'; // Start listening to mousemove events $(document) .on('mousemove.resizer', function(e) { // Use of timeouts makes the move more smooth in Chrome clearTimeout(ts); ts = setTimeout(function() { // For left-side-splitter we need the current offset if (inverted) { offset = node.position().left; } var cursor_position = rcube_event.get_mouse_pos(e).x, width = inverted ? node.width() + (offset - cursor_position) : cursor_position - offset; set_width(width); }, 5); }) .on('mouseup.resizer', function() { // Remove registered events $(document).off('.resizer'); $('iframe').off('.resizer'); document.body.style.userSelect = 'auto'; // Set back the splitter width to normal splitter.removeClass('active'); // Save the current position (width) set_pref(key, node.width()); }); }); if (pos) { set_width(pos); } }; /** * Wrapper for rcmail.open_window to intercept window opening * and display a dialog with an iframe instead of a real window. */ function window_open(url, small, toolbar, force_window) { var colorFunc = function (body) { $(body).css({ color: $(document.body).css('color'), backgroundColor: $(document.body).css('background-color') }) }; var setColor = color_mode == 'dark' && /_task=mail/.test(url) && /_action=viewsource/.test(url); // Use 4th argument to bypass the dialog-mode e.g. for external windows if (!is_mobile() || force_window === true) { // On attachment preview page we do not display the properties sidebar // so we can use a smaller window, as we do for print pages if (/_task=mail/.test(url) && /_action=get/.test(url)) { small = true; } var win = env.open_window.call(rcmail, url, small, toolbar); // Switch the plain/text window to dark-mode if (setColor) { $(win).on('load', function() { colorFunc(win.document.body); }); } return win; } // _extwin=1, _framed=1 are required to display attachment preview // layout properly and make mobile menus working url = rcmail.add_url(url, '_framed', 1); url = rcmail.add_url(url, '_extwin', 1); var label, title = '', props = {cancel_button: 'close', width: 768, height: 768}, frame = $('