| | |
| | | * @licstart The following is the entire license notice for the |
| | | * JavaScript code in this file. |
| | | * |
| | | * Copyright (C) 2005-2014, The Roundcube Dev Team |
| | | * Copyright (C) 2011-2014, Kolab Systems AG |
| | | * Copyright (C) 2005-2015, The Roundcube Dev Team |
| | | * Copyright (C) 2011-2015, Kolab Systems AG |
| | | * |
| | | * The JavaScript code in this page is free software: you can |
| | | * redistribute it and/or modify it under the terms of the GNU |
| | |
| | | }); |
| | | |
| | | // unload fix |
| | | $(window).bind('beforeunload', function() { ref.unload = true; }); |
| | | $(window).on('beforeunload', function() { ref.unload = true; }); |
| | | |
| | | // set environment variable(s) |
| | | this.set_env = function(p, value) |
| | |
| | | this.enable_command('compose', 'add-contact', false); |
| | | parent.rcmail.show_contentframe(true); |
| | | } |
| | | |
| | | // initialize drag-n-drop on attachments, so they can e.g. |
| | | // be dropped into mail compose attachments in another window |
| | | if (this.gui_objects.attachments) |
| | | $('li > a', this.gui_objects.attachments).not('.drop').on('dragstart', function(e) { |
| | | var n, href = this.href, dt = e.originalEvent.dataTransfer; |
| | | if (dt) { |
| | | // inject username to the uri |
| | | href = href.replace(/^https?:\/\//, function(m) { return m + urlencode(ref.env.username) + '@'}); |
| | | // cleanup the node to get filename without the size test |
| | | n = $(this).clone(); |
| | | n.children().remove(); |
| | | |
| | | dt.setData('roundcube-uri', href); |
| | | dt.setData('roundcube-name', $.trim(n.text())); |
| | | } |
| | | }); |
| | | } |
| | | else if (this.env.action == 'compose') { |
| | | this.env.address_group_stack = []; |
| | |
| | | if (this.gui_objects.responseslist) { |
| | | $('a.insertresponse', this.gui_objects.responseslist) |
| | | .attr('unselectable', 'on') |
| | | .mousedown(function(e){ return rcube_event.cancel(e); }) |
| | | .bind('mouseup keypress', function(e){ |
| | | .mousedown(function(e) { return rcube_event.cancel(e); }) |
| | | .on('mouseup keypress', function(e) { |
| | | if (e.type == 'mouseup' || rcube_event.get_keycode(e) == 13) { |
| | | ref.command('insert-response', $(this).attr('rel')); |
| | | $(document.body).trigger('mouseup'); // hides the menu |
| | |
| | | input_user = $('#rcmloginuser'), |
| | | input_tz = $('#rcmlogintz'); |
| | | |
| | | input_user.bind('keyup', function(e) { return ref.login_user_keyup(e); }); |
| | | input_user.keyup(function(e) { return ref.login_user_keyup(e); }); |
| | | |
| | | if (input_user.val() == '') |
| | | input_user.focus(); |
| | |
| | | |
| | | // activate html5 file drop feature (if browser supports it and if configured) |
| | | if (this.gui_objects.filedrop && this.env.filedrop && ((window.XMLHttpRequest && XMLHttpRequest.prototype && XMLHttpRequest.prototype.sendAsBinary) || window.FormData)) { |
| | | $(document.body).bind('dragover dragleave drop', function(e){ return ref.document_drag_hover(e, e.type == 'dragover'); }); |
| | | $(document.body).on('dragover dragleave drop', function(e) { return ref.document_drag_hover(e, e.type == 'dragover'); }); |
| | | $(this.gui_objects.filedrop).addClass('droptarget') |
| | | .bind('dragover dragleave', function(e){ return ref.file_drag_hover(e, e.type == 'dragover'); }) |
| | | .get(0).addEventListener('drop', function(e){ return ref.file_dropped(e); }, false); |
| | | .on('dragover dragleave', function(e) { return ref.file_drag_hover(e, e.type == 'dragover'); }) |
| | | .get(0).addEventListener('drop', function(e) { return ref.file_dropped(e); }, false); |
| | | } |
| | | |
| | | // catch document (and iframe) mouse clicks |
| | | var body_mouseup = function(e){ return ref.doc_mouse_up(e); }; |
| | | $(document.body) |
| | | .bind('mouseup', body_mouseup) |
| | | .bind('keydown', function(e){ return ref.doc_keypress(e); }); |
| | | .mouseup(body_mouseup) |
| | | .keydown(function(e){ return ref.doc_keypress(e); }); |
| | | |
| | | $('iframe').on('load', function(e) { |
| | | try { $(this.contentDocument || this.contentWindow).on('mouseup', body_mouseup); } |
| | |
| | | // removes messages that doesn't exists from list selection array |
| | | this.update_selection = function() |
| | | { |
| | | var selected = this.message_list.selection, |
| | | rows = this.message_list.rows, |
| | | var list = this.message_list, |
| | | selected = list.selection, |
| | | rows = list.rows, |
| | | i, selection = []; |
| | | |
| | | for (i in selected) |
| | | if (rows[selected[i]]) |
| | | selection.push(selected[i]); |
| | | |
| | | this.message_list.selection = selection; |
| | | list.selection = selection; |
| | | |
| | | // reset preview frame, if currently previewed message is not selected (has been removed) |
| | | try { |
| | | var win = this.get_frame_window(this.env.contentframe), |
| | | id = win.rcmail.env.uid; |
| | | |
| | | if (id && $.inArray(id, selection) < 0) |
| | | if (id && !list.in_selection(id)) |
| | | this.show_contentframe(false); |
| | | } |
| | | catch (e) {}; |
| | |
| | | $('#'+r.id+' .leaf:first') |
| | | .attr('id', 'rcmexpando' + r.id) |
| | | .attr('class', (r.obj.style.display != 'none' ? 'expanded' : 'collapsed')) |
| | | .bind('mousedown', {uid: r.uid}, |
| | | function(e) { return ref.expand_message_row(e, e.data.uid); }); |
| | | .mousedown({uid: r.uid}, function(e) { |
| | | return ref.expand_message_row(e, e.data.uid); |
| | | }); |
| | | |
| | | r.unread_children = 0; |
| | | roots.push(r); |
| | |
| | | } |
| | | else if (action == 'compose') { |
| | | this.env.compose_commands.push('compose-encrypted'); |
| | | // display the toolbar button |
| | | $('#' + this.buttons['compose-encrypted'][0].id).show(); |
| | | |
| | | var is_html = $('input[name="_is_html"]').val() > 0; |
| | | |
| | |
| | | '<textarea name="text" id="ffresponsetext" cols="40" rows="8"></textarea></div>' + |
| | | '</form>'; |
| | | |
| | | buttons[this.gettext('save')] = function(e) { |
| | | buttons[this.get_label('save')] = function(e) { |
| | | var name = $('#ffresponsename').val(), |
| | | text = $('#ffresponsetext').val(); |
| | | |
| | |
| | | $(this).dialog('close'); |
| | | }; |
| | | |
| | | buttons[this.gettext('cancel')] = function() { |
| | | buttons[this.get_label('cancel')] = function() { |
| | | $(this).dialog('close'); |
| | | }; |
| | | |
| | | this.show_popup_dialog(html, this.gettext('newresponse'), buttons, {button_classes: ['mainaction']}); |
| | | this.show_popup_dialog(html, this.get_label('newresponse'), buttons, {button_classes: ['mainaction']}); |
| | | |
| | | $('#ffresponsetext').val(text); |
| | | $('#ffresponsename').select(); |
| | |
| | | .attr('tabindex', '0') |
| | | .html(this.quote_html(response.name)) |
| | | .appendTo(li) |
| | | .mousedown(function(e){ |
| | | .mousedown(function(e) { |
| | | return rcube_event.cancel(e); |
| | | }) |
| | | .bind('mouseup keypress', function(e){ |
| | | .on('mouseup keypress', function(e) { |
| | | if (e.type == 'mouseup' || rcube_event.get_keycode(e) == 13) { |
| | | ref.command('insert-response', $(this).attr('rel')); |
| | | $(document.body).trigger('mouseup'); // hides the menu |
| | |
| | | if (!this.local_save_timer && window.localStorage && this.env.save_localstorage) { |
| | | // track typing activity and only save on changes |
| | | this.compose_type_activity = this.compose_type_activity_last = 0; |
| | | $(document).bind('keypress', function(e){ ref.compose_type_activity++; }); |
| | | $(document).keypress(function(e) { ref.compose_type_activity++; }); |
| | | |
| | | this.local_save_timer = setInterval(function(){ |
| | | if (ref.compose_type_activity > ref.compose_type_activity_last) { |
| | |
| | | if (filter) |
| | | url._filter = filter; |
| | | |
| | | if (this.gui_objects.search_interval) |
| | | url._interval = $(this.gui_objects.search_interval).val(); |
| | | |
| | | if (search) { |
| | | url._q = search; |
| | | |
| | |
| | | if (this.gui_objects.qsearchbox) |
| | | this.gui_objects.qsearchbox.value = ''; |
| | | |
| | | if (this.gui_objects.search_interval) |
| | | $(this.gui_objects.search_interval).val(''); |
| | | |
| | | if (this.env.qsearch) |
| | | this.abort_request(this.env.qsearch); |
| | | |
| | |
| | | if (!this.qsearch(this.gui_objects.qsearchbox.value) && this.env.search_filter && this.env.search_filter != 'ALL') |
| | | this.filter_mailbox(this.env.search_filter); |
| | | if (scope != 'all') |
| | | this.select_folder(this.env.mailbox, '', true); |
| | | } |
| | | }; |
| | | |
| | | this.set_searchinterval = function(interval) |
| | | { |
| | | var old = this.env.search_interval; |
| | | this.env.search_interval = interval; |
| | | |
| | | // re-send search query with new interval |
| | | if (interval != old && this.env.search_request) { |
| | | if (!this.qsearch(this.gui_objects.qsearchbox.value) && this.env.search_filter && this.env.search_filter != 'ALL') |
| | | this.filter_mailbox(this.env.search_filter); |
| | | if (interval) |
| | | this.select_folder(this.env.mailbox, '', true); |
| | | } |
| | | }; |
| | |
| | | // add link to pop back to parent group |
| | | if (this.env.address_group_stack.length > 1) { |
| | | $('<a href="#list">...</a>') |
| | | .attr('title', this.gettext('uponelevel')) |
| | | .attr('title', this.get_label('uponelevel')) |
| | | .addClass('poplink') |
| | | .appendTo(boxtitle) |
| | | .click(function(e){ return ref.command('popgroup','',this); }); |
| | |
| | | }; |
| | | |
| | | // send a http request to the server |
| | | this.http_request = function(action, data, lock) |
| | | this.http_request = function(action, data, lock, type) |
| | | { |
| | | if (type != 'POST') |
| | | type = 'GET'; |
| | | |
| | | if (typeof data !== 'object') |
| | | data = rcube_parse_query(data); |
| | | |
| | |
| | | } |
| | | } |
| | | |
| | | var url = this.url(action, data); |
| | | |
| | | // send request |
| | | this.log('HTTP GET: ' + url); |
| | | var url = this.url(action); |
| | | |
| | | // reset keep-alive interval |
| | | this.start_keepalive(); |
| | | |
| | | // send request |
| | | return $.ajax({ |
| | | type: 'GET', url: url, dataType: 'json', |
| | | type: type, url: url, data: data, dataType: 'json', |
| | | success: function(data) { ref.http_response(data); }, |
| | | error: function(o, status, err) { ref.http_error(o, status, err, lock, action); } |
| | | }); |
| | | }; |
| | | |
| | | // send a http GET request to the server |
| | | this.http_get = this.http_request; |
| | | |
| | | // send a http POST request to the server |
| | | this.http_post = function(action, data, lock) |
| | | { |
| | | if (typeof data !== 'object') |
| | | data = rcube_parse_query(data); |
| | | |
| | | data._remote = 1; |
| | | data._unlock = lock ? lock : 0; |
| | | |
| | | // trigger plugin hook |
| | | var result = this.triggerEvent('request'+action, data); |
| | | |
| | | // abort if one of the handlers returned false |
| | | if (result === false) { |
| | | if (data._unlock) |
| | | this.set_busy(false, null, data._unlock); |
| | | return false; |
| | | } |
| | | else if (result !== undefined) { |
| | | data = result; |
| | | if (data._action) { |
| | | action = data._action; |
| | | delete data._action; |
| | | } |
| | | } |
| | | |
| | | var url = this.url(action); |
| | | |
| | | // send request |
| | | this.log('HTTP POST: ' + url); |
| | | |
| | | // reset keep-alive interval |
| | | this.start_keepalive(); |
| | | |
| | | return $.ajax({ |
| | | type: 'POST', url: url, data: data, dataType: 'json', |
| | | success: function(data){ ref.http_response(data); }, |
| | | error: function(o, status, err) { ref.http_error(o, status, err, lock, action); } |
| | | }); |
| | | return this.http_request(action, data, lock, 'POST'); |
| | | }; |
| | | |
| | | // aborts ajax request |
| | |
| | | } |
| | | |
| | | // handle upload errors by parsing iframe content in onload |
| | | frame.bind('load', {ts:ts}, onload); |
| | | frame.on('load', {ts:ts}, onload); |
| | | |
| | | $(form).attr({ |
| | | target: frame_name, |
| | |
| | | this.file_drag_hover(e, false); |
| | | |
| | | // prepare multipart form data composition |
| | | var files = e.target.files || e.dataTransfer.files, |
| | | var uri, files = e.target.files || e.dataTransfer.files, |
| | | formdata = window.FormData ? new FormData() : null, |
| | | fieldname = (this.env.filedrop.fieldname || '_file') + (this.env.filedrop.single ? '' : '[]'), |
| | | boundary = '------multipartformboundary' + (new Date).getTime(), |
| | | dashdash = '--', crlf = '\r\n', |
| | | multipart = dashdash + boundary + crlf; |
| | | multipart = dashdash + boundary + crlf, |
| | | args = {_id: this.env.compose_id || this.env.cid || '', _remote: 1, _from: this.env.action}; |
| | | |
| | | if (!files || !files.length) |
| | | if (!files || !files.length) { |
| | | // Roundcube attachment, pass its uri to the backend and attach |
| | | if (uri = e.dataTransfer.getData('roundcube-uri')) { |
| | | var ts = new Date().getTime(), |
| | | // jQuery way to escape filename (#1490530) |
| | | content = $('<span>').text(e.dataTransfer.getData('roundcube-name') || this.get_label('attaching')).html(); |
| | | |
| | | args._uri = uri; |
| | | args._uploadid = ts; |
| | | |
| | | // add to attachments list |
| | | if (!this.add2attachment_list(ts, {name: '', html: content, classname: 'uploading', complete: false})) |
| | | this.file_upload_id = this.set_busy(true, 'attaching'); |
| | | |
| | | this.http_post(this.env.filedrop.action || 'upload', args); |
| | | } |
| | | return; |
| | | } |
| | | |
| | | // inline function to submit the files to the server |
| | | var submit_data = function() { |
| | |
| | | // complete multipart content and post request |
| | | multipart += dashdash + boundary + dashdash + crlf; |
| | | |
| | | args._uploadid = ts; |
| | | |
| | | $.ajax({ |
| | | type: 'POST', |
| | | dataType: 'json', |
| | | url: ref.url(ref.env.filedrop.action || 'upload', {_id: ref.env.compose_id||ref.env.cid||'', _uploadid: ts, _remote: 1, _from: ref.env.action}), |
| | | url: ref.url(ref.env.filedrop.action || 'upload', args), |
| | | contentType: formdata ? false : 'multipart/form-data; boundary=' + boundary, |
| | | processData: false, |
| | | timeout: 0, // disable default timeout set in ajaxSetup() |