| | |
| | | | Roundcube Webmail Client Script | |
| | | | | |
| | | | This file is part of the Roundcube Webmail client | |
| | | | Copyright (C) 2005-2010, Roundcube Dev, - Switzerland | |
| | | | Copyright (C) 2005-2010, The Roundcube Dev Team | |
| | | | Licensed under the GNU GPL | |
| | | | | |
| | | +-----------------------------------------------------------------------+ |
| | |
| | | |
| | | $Id$ |
| | | */ |
| | | |
| | | |
| | | function rcube_webmail() |
| | | { |
| | |
| | | // set environment variable(s) |
| | | this.set_env = function(p, value) |
| | | { |
| | | if (p != null && typeof(p) == 'object' && !value) |
| | | if (p != null && typeof p === 'object' && !value) |
| | | for (var n in p) |
| | | this.env[n] = p[n]; |
| | | else |
| | |
| | | |
| | | if ((this.env.action=='add' || this.env.action=='edit') && this.gui_objects.editform) { |
| | | this.enable_command('save', true); |
| | | $("input[type='text']").first().select(); |
| | | this.enable_command('upload-photo', this.env.coltypes.photo ? true : false); |
| | | this.enable_command('delete-photo', this.env.coltypes.photo && this.env.action == 'edit'); |
| | | |
| | | for (var col in this.env.coltypes) |
| | | this.init_edit_field(col, null); |
| | | |
| | | $('.contactfieldgroup .row a.deletebutton').click(function(){ ref.delete_edit_field(this); return false }); |
| | | |
| | | $('select.addfieldmenu').change(function(e){ |
| | | ref.insert_edit_field($(this).val(), $(this).attr('rel'), this); |
| | | this.selectedIndex = 0; |
| | | }); |
| | | |
| | | $("input[type='text']:visible").first().focus(); |
| | | } |
| | | else if (this.gui_objects.qsearchbox) { |
| | | this.enable_command('search', 'reset-search', 'moveto', true); |
| | |
| | | // execute all foreign onload scripts |
| | | // @deprecated |
| | | for (var i in this.onloads) { |
| | | if (typeof(this.onloads[i]) == 'string') |
| | | if (typeof this.onloads[i] === 'string') |
| | | eval(this.onloads[i]); |
| | | else if (typeof(this.onloads[i]) == 'function') |
| | | else if (typeof this.onloads[i] === 'function') |
| | | this.onloads[i](); |
| | | } |
| | | |
| | |
| | | } |
| | | |
| | | // process external commands |
| | | if (typeof this.command_handlers[command] == 'function') { |
| | | if (typeof this.command_handlers[command] === 'function') { |
| | | var ret = this.command_handlers[command](props, obj); |
| | | return ret !== null ? ret : (obj ? false : true); |
| | | return ret !== undefined ? ret : (obj ? false : true); |
| | | } |
| | | else if (typeof this.command_handlers[command] == 'string') { |
| | | else if (typeof this.command_handlers[command] === 'string') { |
| | | var ret = window[this.command_handlers[command]](props, obj); |
| | | return ret !== null ? ret : (obj ? false : true); |
| | | return ret !== undefined ? ret : (obj ? false : true); |
| | | } |
| | | |
| | | // trigger plugin hooks |
| | | this.triggerEvent('actionbefore', {props:props, action:command}); |
| | | var event_ret = this.triggerEvent('before'+command, props); |
| | | if (typeof event_ret != 'undefined') { |
| | | if (event_ret !== undefined) { |
| | | // abort if one the handlers returned false |
| | | if (event_ret === false) |
| | | return false; |
| | |
| | | input_name.focus(); |
| | | break; |
| | | } |
| | | else if (input_email.length && !rcube_check_email(input_email.val())) { |
| | | else if (this.task == 'settings' && input_email.length && !rcube_check_email(input_email.val())) { |
| | | alert(this.get_label('noemailwarning')); |
| | | input_email.focus(); |
| | | break; |
| | | } |
| | | |
| | | // clear empty input fields |
| | | $('input.placeholder').each(function(){ if (this.value == this._placeholder) this.value = ''; }); |
| | | } |
| | | |
| | | this.gui_objects.editform.submit(); |
| | |
| | | |
| | | case 'export': |
| | | if (this.contact_list.rowcount > 0) { |
| | | var add_url = (this.env.source ? '_source='+urlencode(this.env.source)+'&' : ''); |
| | | if (this.env.search_request) |
| | | add_url += '_search='+this.env.search_request; |
| | | |
| | | this.goto_url('export', add_url); |
| | | this.goto_url('export', { _source:this.env.source, _gid:this.env.group, _search:this.env.search_request }); |
| | | } |
| | | break; |
| | | |
| | | case 'upload-photo': |
| | | this.upload_contact_photo(props); |
| | | break; |
| | | |
| | | case 'delete-photo': |
| | | this.replace_contact_photo('-del-'); |
| | | break; |
| | | |
| | | // user settings commands |
| | | case 'preferences': |
| | | this.goto_url(''); |
| | | break; |
| | | |
| | | case 'identities': |
| | | this.goto_url('settings/identities'); |
| | | break; |
| | | |
| | | case 'folders': |
| | | this.goto_url('settings/folders'); |
| | | this.goto_url('settings/' + command); |
| | | break; |
| | | |
| | | // unified command call (command name == function name) |
| | | default: |
| | | var func = command.replace(/-/g, '_'); |
| | | if (this[func] && typeof this[func] == 'function') |
| | | if (this[func] && typeof this[func] === 'function') |
| | | this[func](props); |
| | | break; |
| | | } |
| | |
| | | |
| | | this.is_framed = function() |
| | | { |
| | | return (this.env.framed && parent.rcmail); |
| | | return (this.env.framed && parent.rcmail && parent.rcmail != this && parent.rcmail.command); |
| | | }; |
| | | |
| | | |
| | |
| | | // reset 'pressed' buttons |
| | | if (this.buttons_sel) { |
| | | for (var id in this.buttons_sel) |
| | | if (typeof id != 'function') |
| | | if (typeof id !== 'function') |
| | | this.button_out(this.buttons_sel[id], id); |
| | | this.buttons_sel = {}; |
| | | } |
| | |
| | | message.expanded = true; |
| | | } |
| | | else if (message.has_children) { |
| | | if (typeof(message.expanded) == 'undefined' && (this.env.autoexpand_threads == 1 || (this.env.autoexpand_threads == 2 && message.unread_children))) { |
| | | if (message.expanded === undefined && (this.env.autoexpand_threads == 1 || (this.env.autoexpand_threads == 2 && message.unread_children))) { |
| | | message.expanded = true; |
| | | } |
| | | } |
| | |
| | | var action = flags.mbox == this.env.drafts_mailbox ? 'compose' : 'show'; |
| | | var uid_param = flags.mbox == this.env.drafts_mailbox ? '_draft_uid' : '_uid'; |
| | | cols.subject = '<a href="./?_task=mail&_action='+action+'&_mbox='+urlencode(flags.mbox)+'&'+uid_param+'='+uid+'"'+ |
| | | ' onclick="return rcube_event.cancel(event)">'+cols.subject+'</a>'; |
| | | ' onclick="return rcube_event.cancel(event)" onmouseover="rcube_webmail.long_subject_title(this,'+(message.depth+1)+')">'+cols.subject+'</a>'; |
| | | } |
| | | |
| | | // add each submitted col |
| | |
| | | { |
| | | var update, add_url = ''; |
| | | |
| | | if (typeof sort_col == 'undefined') |
| | | if (sort_col === undefined) |
| | | sort_col = this.env.sort_col; |
| | | if (!sort_order) |
| | | sort_order = this.env.sort_order; |
| | |
| | | var url = '', target = window; |
| | | |
| | | if (!mbox) |
| | | mbox = this.env.mailbox; |
| | | mbox = this.env.mailbox ? this.env.mailbox : 'INBOX'; |
| | | |
| | | if (add_url) |
| | | url += add_url; |
| | |
| | | // copy selected messages to the specified mailbox |
| | | this.copy_messages = function(mbox) |
| | | { |
| | | if (mbox && typeof mbox == 'object') |
| | | if (mbox && typeof mbox === 'object') |
| | | mbox = mbox.id; |
| | | |
| | | // exit if current or no mailbox specified or if selection is empty |
| | |
| | | // move selected messages to the specified mailbox |
| | | this.move_messages = function(mbox) |
| | | { |
| | | if (mbox && typeof mbox == 'object') |
| | | if (mbox && typeof mbox === 'object') |
| | | mbox = mbox.id; |
| | | |
| | | // exit if current or no mailbox specified or if selection is empty |
| | |
| | | |
| | | // check if all files has been uploaded |
| | | for (var key in this.env.attachments) { |
| | | if (typeof this.env.attachments[key] == 'object' && !this.env.attachments[key].complete) { |
| | | if (typeof this.env.attachments[key] === 'object' && !this.env.attachments[key].complete) { |
| | | alert(this.get_label('notuploadedwarning')); |
| | | return false; |
| | | } |
| | |
| | | |
| | | // create hidden iframe and post upload form |
| | | if (send) { |
| | | var ts = new Date().getTime(); |
| | | var frame_name = 'rcmupload'+ts; |
| | | |
| | | // have to do it this way for IE |
| | | // otherwise the form will be posted to a new window |
| | | if (document.all) { |
| | | var html = '<iframe name="'+frame_name+'" src="program/blank.gif" style="width:0;height:0;visibility:hidden;"></iframe>'; |
| | | document.body.insertAdjacentHTML('BeforeEnd',html); |
| | | } |
| | | else { // for standards-compilant browsers |
| | | var frame = document.createElement('iframe'); |
| | | frame.name = frame_name; |
| | | frame.style.border = 'none'; |
| | | frame.style.width = 0; |
| | | frame.style.height = 0; |
| | | frame.style.visibility = 'hidden'; |
| | | document.body.appendChild(frame); |
| | | } |
| | | |
| | | // handle upload errors, parsing iframe content in onload |
| | | $(frame_name).bind('load', {ts:ts}, function(e) { |
| | | var frame_name = this.async_upload_form(form, 'upload', function(e) { |
| | | var d, content = ''; |
| | | try { |
| | | if (this.contentDocument) { |
| | |
| | | d = this.contentWindow.document; |
| | | } |
| | | content = d.childNodes[0].innerHTML; |
| | | } catch (e) {} |
| | | } catch (err) {} |
| | | |
| | | if (!content.match(/add2attachment/) && (!bw.opera || (rcmail.env.uploadframe && rcmail.env.uploadframe == e.data.ts))) { |
| | | if (!content.match(/display_message/)) |
| | |
| | | rcmail.env.uploadframe = e.data.ts; |
| | | }); |
| | | |
| | | form.target = frame_name; |
| | | form.action = this.env.comm_path+'&_action=upload&_uploadid='+ts; |
| | | form.setAttribute('enctype', 'multipart/form-data'); |
| | | form.submit(); |
| | | |
| | | // display upload indicator and cancel button |
| | | var content = this.get_label('uploading'); |
| | | var content = this.get_label('uploading'), |
| | | ts = frame_name.replace(/^rcmupload/, ''); |
| | | |
| | | if (this.env.loadingicon) |
| | | content = '<img src="'+this.env.loadingicon+'" alt="" />'+content; |
| | | if (this.env.cancelicon) |
| | |
| | | end = inp_value.substring(p+this.ksearch_value.length, inp_value.length); |
| | | |
| | | // insert all members of a group |
| | | if (typeof this.env.contacts[id] == 'object' && this.env.contacts[id].id) { |
| | | if (typeof this.env.contacts[id] === 'object' && this.env.contacts[id].id) { |
| | | insert += this.env.contacts[id].name + ', '; |
| | | this.group2expand = $.extend({}, this.env.contacts[id]); |
| | | this.group2expand.input = this.ksearch_input; |
| | | this.http_request('group-expand', '_source='+urlencode(this.env.contacts[id].source)+'&_gid='+urlencode(this.env.contacts[id].id), false); |
| | | } |
| | | else if (typeof this.env.contacts[id] == 'string') |
| | | else if (typeof this.env.contacts[id] === 'string') |
| | | insert = this.env.contacts[id] + ', '; |
| | | |
| | | this.ksearch_input.value = pre + insert + end; |
| | |
| | | if (q == this.ksearch_value) |
| | | return; |
| | | |
| | | if (q.length < min) { |
| | | if (q.length && q.length < min) { |
| | | if (!this.env.acinfo) { |
| | | var label = this.get_label('autocompletechars'); |
| | | label = label.replace('$min', min); |
| | | this.env.acinfo = this.display_message(label); |
| | | this.env.acinfo = this.display_message( |
| | | this.get_label('autocompletechars').replace('$min', min)); |
| | | } |
| | | return; |
| | | } |
| | | else if (this.env.acinfo && q.length == min) { |
| | | else if (this.env.acinfo) { |
| | | this.hide_message(this.env.acinfo); |
| | | } |
| | | |
| | |
| | | |
| | | // add each result line to list |
| | | for (i=0; i < a_results.length; i++) { |
| | | text = typeof a_results[i] == 'object' ? a_results[i].name : a_results[i]; |
| | | text = typeof a_results[i] === 'object' ? a_results[i].name : a_results[i]; |
| | | li = document.createElement('LI'); |
| | | li.innerHTML = text.replace(new RegExp('('+RegExp.escape(s_val)+')', 'ig'), '##$1%%').replace(/</g, '<').replace(/>/g, '>').replace(/##([^%]+)%%/g, '<b>$1</b>'); |
| | | li.onmouseover = function(){ ref.ksearch_select(this); }; |
| | |
| | | this.show_contentframe(false); |
| | | } |
| | | |
| | | if (this.env.group) |
| | | qs += '&_gid='+urlencode(this.env.group); |
| | | |
| | | // also send search request to get the right records from the next page |
| | | if (this.env.search_request) |
| | | qs += '&_search='+this.env.search_request; |
| | |
| | | // update a contact record in the list |
| | | this.update_contact_row = function(cid, cols_arr, newcid) |
| | | { |
| | | cid = String(cid).replace(this.identifier_expr, '_'); |
| | | newcid = String(newcid).replace(this.identifier_expr, '_'); |
| | | |
| | | var row; |
| | | if (this.contact_list.rows[cid] && (row = this.contact_list.rows[cid].obj)) { |
| | | for (var c=0; c<cols_arr.length; c++) |
| | |
| | | even = rowcount%2, |
| | | row = document.createElement('tr'); |
| | | |
| | | row.id = 'rcmrow'+cid; |
| | | row.id = 'rcmrow'+String(cid).replace(this.identifier_expr, '_'); |
| | | row.className = 'contact '+(even ? 'even' : 'odd'); |
| | | |
| | | if (this.contact_list.in_selection(cid)) |
| | |
| | | this.env.contactfolders[key] = this.env.contactgroups[key] = prop; |
| | | |
| | | var link = $('<a>').attr('href', '#') |
| | | .attr('rel', prop.source+':'+prop.id) |
| | | .bind('click', function() { return rcmail.command('listgroup', prop, this);}) |
| | | .html(prop.name); |
| | | var li = $('<li>').attr('id', 'rcmli'+key) |
| | | var li = $('<li>').attr('id', 'rcmli'+key.replace(this.identifier_expr, '_')) |
| | | .addClass('contactgroup') |
| | | .append(link) |
| | | .insertAfter(this.get_folder_li(prop.source)); |
| | |
| | | { |
| | | this.reset_add_input(); |
| | | |
| | | var key = 'G'+prop.source+prop.id, link, li = this.get_folder_li(key); |
| | | var key = 'G'+prop.source+prop.id, |
| | | li = this.get_folder_li(key), |
| | | link; |
| | | |
| | | if (li && (link = li.firstChild) && link.tagName.toLowerCase() == 'a') |
| | | // group ID has changed, replace link node and identifiers |
| | | if (li && prop.newid) { |
| | | var newkey = 'G'+prop.source+prop.newid; |
| | | li.id = String('rcmli'+newkey).replace(this.identifier_expr, '_'); |
| | | this.env.contactfolders[newkey] = this.env.contactfolders[key]; |
| | | this.env.group = prop.newid; |
| | | |
| | | var newprop = $.extend({}, prop); |
| | | newprop.id = prop.newid; |
| | | newprop.type = 'group'; |
| | | |
| | | link = $('<a>').attr('href', '#') |
| | | .attr('rel', prop.source+':'+prop.newid) |
| | | .bind('click', function() { return rcmail.command('listgroup', newprop, this);}) |
| | | .html(prop.name); |
| | | $(li).children().replaceWith(link); |
| | | } |
| | | // update displayed group name |
| | | else if (li && (link = li.firstChild) && link.tagName.toLowerCase() == 'a') |
| | | link.innerHTML = prop.name; |
| | | |
| | | this.env.contactfolders[key].name = this.env.contactgroups[key].name = prop.name; |
| | | this.triggerEvent('group_update', { id:prop.id, source:prop.source, name:prop.name, li:li[0] }); |
| | | this.triggerEvent('group_update', { id:prop.id, source:prop.source, name:prop.name, li:li[0], newid:prop.newid }); |
| | | }; |
| | | |
| | | |
| | | this.init_edit_field = function(col, elem) |
| | | { |
| | | if (!elem) |
| | | elem = $('.ff_' + col); |
| | | |
| | | elem.focus(function(){ ref.focus_textfield(this); }) |
| | | .blur(function(){ ref.blur_textfield(this); }) |
| | | .each(function(){ this._placeholder = this.title = ref.env.coltypes[col].label; ref.blur_textfield(this); }); |
| | | }; |
| | | |
| | | this.insert_edit_field = function(col, section, menu) |
| | | { |
| | | // just make pre-defined input field visible |
| | | var elem = $('#ff_'+col); |
| | | if (elem.length) { |
| | | elem.show().focus(); |
| | | $(menu).children('option[value="'+col+'"]').attr('disabled', true); |
| | | } |
| | | else { |
| | | var lastelem = $('.ff_'+col), |
| | | appendcontainer = $('#contactsection'+section+' .contactcontroller'+col); |
| | | |
| | | if (!appendcontainer.length) |
| | | appendcontainer = $('<fieldset>').addClass('contactfieldgroup contactcontroller'+col).insertAfter($('#contactsection'+section+' .contactfieldgroup').last()); |
| | | |
| | | if (appendcontainer.length && appendcontainer.get(0).nodeName == 'FIELDSET') { |
| | | var input, colprop = this.env.coltypes[col], |
| | | row = $('<div>').addClass('row'), |
| | | cell = $('<div>').addClass('contactfieldcontent data'), |
| | | label = $('<div>').addClass('contactfieldlabel label'); |
| | | |
| | | if (colprop.subtypes_select) |
| | | label.html(colprop.subtypes_select); |
| | | else |
| | | label.html(colprop.label); |
| | | |
| | | var name_suffix = colprop.limit != 1 ? '[]' : ''; |
| | | if (colprop.type == 'text' || colprop.type == 'date') { |
| | | input = $('<input>') |
| | | .addClass('ff_'+col) |
| | | .attr('type', 'text') |
| | | .attr('name', '_'+col+name_suffix) |
| | | .attr('size', colprop.size) |
| | | .appendTo(cell); |
| | | |
| | | this.init_edit_field(col, input); |
| | | } |
| | | else if (colprop.type == 'composite') { |
| | | var childcol, cp, first; |
| | | for (var childcol in colprop.childs) { |
| | | cp = colprop.childs[childcol]; |
| | | input = $('<input>') |
| | | .addClass('ff_'+childcol) |
| | | .attr('type', 'text') |
| | | .attr('name', '_'+childcol+name_suffix) |
| | | .attr('size', cp.size) |
| | | .appendTo(cell); |
| | | cell.append(" "); |
| | | this.init_edit_field(childcol, input); |
| | | if (!first) first = input; |
| | | } |
| | | input = first; // set focus to the first of this composite fields |
| | | } |
| | | else if (colprop.type == 'select') { |
| | | input = $('<select>') |
| | | .addClass('ff_'+col) |
| | | .attr('name', '_'+col+name_suffix) |
| | | .appendTo(cell); |
| | | |
| | | var options = input.attr('options'); |
| | | options[options.length] = new Option('---', ''); |
| | | if (colprop.options) |
| | | $.each(colprop.options, function(i, val){ options[options.length] = new Option(val, i); }); |
| | | } |
| | | |
| | | if (input) { |
| | | var delbutton = $('<a href="#del"></a>') |
| | | .addClass('contactfieldbutton deletebutton') |
| | | .attr('title', this.get_label('delete')) |
| | | .attr('rel', col) |
| | | .html(this.env.delbutton) |
| | | .click(function(){ ref.delete_edit_field(this); return false }) |
| | | .appendTo(cell); |
| | | |
| | | row.append(label).append(cell).appendTo(appendcontainer.show()); |
| | | input.first().focus(); |
| | | |
| | | // disable option if limit reached |
| | | if (!colprop.count) colprop.count = 0; |
| | | if (++colprop.count == colprop.limit && colprop.limit) |
| | | $(menu).children('option[value="'+col+'"]').attr('disabled', true); |
| | | } |
| | | } |
| | | } |
| | | }; |
| | | |
| | | this.delete_edit_field = function(elem) |
| | | { |
| | | var col = $(elem).attr('rel'), |
| | | colprop = this.env.coltypes[col], |
| | | fieldset = $(elem).parents('fieldset.contactfieldgroup'), |
| | | addmenu = fieldset.parent().find('select.addfieldmenu'); |
| | | |
| | | // just clear input but don't hide the last field |
| | | if (--colprop.count <= 0 && colprop.visible) |
| | | $(elem).parent().children('input').val('').blur(); |
| | | else { |
| | | $(elem).parents('div.row').remove(); |
| | | // hide entire fieldset if no more rows |
| | | if (!fieldset.children('div.row').length) |
| | | fieldset.hide(); |
| | | } |
| | | |
| | | // enable option in add-field selector or insert it if necessary |
| | | if (addmenu.length) { |
| | | var option = addmenu.children('option[value="'+col+'"]'); |
| | | if (option.length) |
| | | option.attr('disabled', false); |
| | | else |
| | | option = $('<option>').attr('value', col).html(colprop.label).appendTo(addmenu); |
| | | addmenu.show(); |
| | | } |
| | | }; |
| | | |
| | | |
| | | this.upload_contact_photo = function(form) |
| | | { |
| | | if (form && form.elements._photo.value) { |
| | | this.async_upload_form(form, 'upload-photo', function(e) { |
| | | rcmail.set_busy(false, null, rcmail.photo_upload_id); |
| | | }); |
| | | |
| | | // display upload indicator |
| | | this.photo_upload_id = this.set_busy(true, 'uploading'); |
| | | } |
| | | }; |
| | | |
| | | this.replace_contact_photo = function(id) |
| | | { |
| | | $('#ff_photo').val(id); |
| | | |
| | | var buttons = this.buttons['upload-photo']; |
| | | for (var n=0; n < buttons.length; n++) |
| | | $('#'+buttons[n].id).html(this.get_label(id == '-del-' ? 'addphoto' : 'replacephoto')); |
| | | |
| | | var img_src = id == '-del-' ? this.env.photo_placeholder : |
| | | this.env.comm_path + '&_action=photo&_source=' + this.env.source + '&_cid=' + this.env.cid + '&_photo=' + id; |
| | | $(this.gui_objects.contactphoto).children('img').attr('src', img_src); |
| | | |
| | | this.enable_command('delete-photo', id != '-del-'); |
| | | }; |
| | | |
| | | this.photo_upload_end = function() |
| | | { |
| | | this.set_busy(false, null, this.photo_upload_id); |
| | | delete this.photo_upload_id; |
| | | }; |
| | | |
| | | |
| | |
| | | } |
| | | }; |
| | | |
| | | // disables subscription checkbox (for protected folder) |
| | | this.disable_subscription = function(folder) |
| | | { |
| | | var id = this.get_folder_row_id(folder); |
| | | if (id) |
| | | $('input[name="_subscribed[]"]', $('#'+id)).attr('disabled', true); |
| | | }; |
| | | |
| | | this.folder_size = function(folder) |
| | | { |
| | | var lock = this.set_busy(true, 'loading'); |
| | |
| | | this.init_buttons = function() |
| | | { |
| | | for (var cmd in this.buttons) { |
| | | if (typeof cmd != 'string') |
| | | if (typeof cmd !== 'string') |
| | | continue; |
| | | |
| | | for (var i=0; i< this.buttons[cmd].length; i++) { |
| | |
| | | obj.src = button[state]; |
| | | } |
| | | // set class name according to button state |
| | | else if (obj && typeof(button[state])!='undefined') { |
| | | else if (obj && button[state] !== undefined) { |
| | | button.status = state; |
| | | obj.className = button[state]; |
| | | } |
| | |
| | | } |
| | | }; |
| | | |
| | | |
| | | this.focus_textfield = function(elem) |
| | | { |
| | | elem._hasfocus = true; |
| | | var $elem = $(elem); |
| | | if ($elem.hasClass('placeholder') || $elem.val() == elem._placeholder) |
| | | $elem.val('').removeClass('placeholder').attr('spellcheck', true); |
| | | }; |
| | | |
| | | this.blur_textfield = function(elem) |
| | | { |
| | | elem._hasfocus = false; |
| | | var $elem = $(elem); |
| | | if (elem._placeholder && (!$elem.val() || $elem.val() == elem._placeholder)) |
| | | $elem.addClass('placeholder').attr('spellcheck', false).val(elem._placeholder); |
| | | }; |
| | | |
| | | // write to the document/window title |
| | | this.set_pagetitle = function(title) |
| | | { |
| | |
| | | type = type ? type : 'notice'; |
| | | |
| | | var ref = this, |
| | | key = msg, |
| | | date = new Date(), |
| | | id = type + date.getTime(), |
| | | timeout = type == 'loading' ? this.env.request_timeout * 1000 : (this.message_time * (type == 'error' || type == 'warning' ? 2 : 1)); |
| | | |
| | | if (type == 'loading' && !msg) |
| | | msg = this.get_label('loading'); |
| | | timeout = this.message_time * (type == 'error' || type == 'warning' ? 2 : 1); |
| | | |
| | | if (type == 'loading') { |
| | | key = 'loading'; |
| | | timeout = this.env.request_timeout * 1000; |
| | | if (!msg) |
| | | msg = this.get_label('loading'); |
| | | } |
| | | |
| | | // The same message is already displayed |
| | | if (this.messages[msg]) { |
| | | this.messages[msg].elements.push(id); |
| | | window.setTimeout(function() { ref.hide_message(id, true); }, timeout); |
| | | if (this.messages[key]) { |
| | | // replace label |
| | | if (this.messages[key].obj) |
| | | this.messages[key].obj.html(msg); |
| | | // store label in stack |
| | | if (type == 'loading') { |
| | | this.messages[key].labels.push({'id': id, 'msg': msg}); |
| | | } |
| | | // add element and set timeout |
| | | this.messages[key].elements.push(id); |
| | | window.setTimeout(function() { ref.hide_message(id, type == 'loading'); }, timeout); |
| | | return id; |
| | | } |
| | | |
| | | var obj = $('<div>').addClass(type).html(msg).data('msg', msg), |
| | | cont = $(this.gui_objects.message).show(); |
| | | // create DOM object and display it |
| | | var obj = $('<div>').addClass(type).html(msg).data('key', key), |
| | | cont = $(this.gui_objects.message).append(obj).show(); |
| | | |
| | | this.messages[key] = {'obj': obj, 'elements': [id]}; |
| | | |
| | | if (type == 'loading') { |
| | | obj.appendTo(cont); |
| | | this.messages[msg] = {'obj': obj, 'elements': [id]}; |
| | | window.setTimeout(function() { rcmail.hide_message(id); }, timeout); |
| | | return id; |
| | | this.messages[key].labels = [{'id': id, 'msg': msg}]; |
| | | } |
| | | else { |
| | | obj.appendTo(cont).bind('mousedown', function() { return ref.hide_message(obj, true); }); |
| | | window.setTimeout(function() { ref.hide_message(id, true); }, timeout); |
| | | this.messages[msg] = { 'obj': obj, 'elements': [id] }; |
| | | return id; |
| | | obj.click(function() { return ref.hide_message(obj); }); |
| | | } |
| | | |
| | | window.setTimeout(function() { ref.hide_message(id, type == 'loading'); }, timeout); |
| | | return id; |
| | | }; |
| | | |
| | | // make a message to disapear |
| | |
| | | if (this.is_framed()) |
| | | return parent.rcmail.hide_message(obj, fade); |
| | | |
| | | if (typeof(obj) == 'object') { |
| | | // hide message object |
| | | var k, n, i, msg, m = this.messages; |
| | | |
| | | // Hide message by object, don't use for 'loading'! |
| | | if (typeof obj === 'object') { |
| | | $(obj)[fade?'fadeOut':'hide'](); |
| | | |
| | | var msg = $(obj).data('msg'); |
| | | msg = $(obj).data('key'); |
| | | if (this.messages[msg]) |
| | | delete this.messages[msg]; |
| | | } |
| | | // Hide message by id |
| | | else { |
| | | // hide message by id |
| | | var k, n, m = this.messages; |
| | | for (k in m) { |
| | | for (n in m[k].elements) { |
| | | if (m[k] && m[k].elements[n] == obj) { |
| | | m[k].elements.splice(n, 1); |
| | | // hide dom element if last instance is removed |
| | | // hide DOM element if last instance is removed |
| | | if (!m[k].elements.length) { |
| | | m[k].obj[fade?'fadeOut':'hide'](); |
| | | delete m[k]; |
| | | } |
| | | // set pending action label for 'loading' message |
| | | else if (k == 'loading') { |
| | | for (i in m[k].labels) { |
| | | if (m[k].labels[i].id == obj) { |
| | | delete m[k].labels[i]; |
| | | } |
| | | else { |
| | | msg = m[k].labels[i].msg; |
| | | } |
| | | m[k].obj.html(msg); |
| | | } |
| | | } |
| | | } |
| | | } |
| | |
| | | } |
| | | th.appendChild(tr); |
| | | thead.parentNode.replaceChild(th, thead); |
| | | thead = th; |
| | | } |
| | | |
| | | for (n=0, len=this.env.coltypes.length; n<len; n++) { |
| | |
| | | this.set_quota = function(content) |
| | | { |
| | | if (content && this.gui_objects.quotadisplay) { |
| | | if (typeof(content) == 'object' && content.type == 'image') |
| | | if (typeof content === 'object' && content.type == 'image') |
| | | this.percent_indicator(this.gui_objects.quotadisplay, content); |
| | | else |
| | | $(this.gui_objects.quotadisplay).html(content); |
| | |
| | | // update the mailbox count display |
| | | this.set_unread_count_display = function(mbox, set_title) |
| | | { |
| | | var reg, text_obj, item, mycount, childcount, div; |
| | | var reg, link, text_obj, item, mycount, childcount, div; |
| | | |
| | | if (item = this.get_folder_li(mbox)) { |
| | | mycount = this.env.unread_counts[mbox] ? this.env.unread_counts[mbox] : 0; |
| | | text_obj = item.getElementsByTagName('a')[0]; |
| | | link = $(item).children('a').eq(0); |
| | | text_obj = link.children('span.unreadcount'); |
| | | if (!text_obj.length && mycount) |
| | | text_obj = $('<span>').addClass('unreadcount').appendTo(link); |
| | | reg = /\s+\([0-9]+\)$/i; |
| | | |
| | | childcount = 0; |
| | |
| | | childcount += this.env.unread_counts[k]; |
| | | } |
| | | |
| | | if (mycount && text_obj.innerHTML.match(reg)) |
| | | text_obj.innerHTML = text_obj.innerHTML.replace(reg, ' ('+mycount+')'); |
| | | else if (mycount) |
| | | text_obj.innerHTML += ' ('+mycount+')'; |
| | | else |
| | | text_obj.innerHTML = text_obj.innerHTML.replace(reg, ''); |
| | | if (mycount && text_obj.length) |
| | | text_obj.html(' ('+mycount+')'); |
| | | else if (text_obj.length) |
| | | text_obj.remove(); |
| | | |
| | | // set parent's display |
| | | reg = new RegExp(RegExp.escape(this.env.delimiter) + '[^' + RegExp.escape(this.env.delimiter) + ']+$'); |
| | |
| | | /********************************************************/ |
| | | /********* remote request methods *********/ |
| | | /********************************************************/ |
| | | |
| | | // compose a valid url with the given parameters |
| | | this.url = function(action, query) |
| | | { |
| | | var querystring = typeof query === 'string' ? '&' + query : ''; |
| | | |
| | | if (typeof action !== 'string') |
| | | query = action; |
| | | else if (!query || typeof query !== 'object') |
| | | query = {}; |
| | | |
| | | if (action) |
| | | query._action = action; |
| | | else |
| | | query._action = this.env.action; |
| | | |
| | | var base = this.env.comm_path; |
| | | |
| | | // overwrite task name |
| | | if (query._action.match(/([a-z]+)\/([a-z-_]+)/)) { |
| | | query._action = RegExp.$2; |
| | | base = base.replace(/\_task=[a-z]+/, '_task='+RegExp.$1); |
| | | } |
| | | |
| | | // remove undefined values |
| | | var param = {}; |
| | | for (var k in query) { |
| | | if (query[k] !== undefined && query[k] !== null) |
| | | param[k] = query[k]; |
| | | } |
| | | |
| | | return base + '&' + $.param(param) + querystring; |
| | | }; |
| | | |
| | | this.redirect = function(url, lock) |
| | | { |
| | |
| | | |
| | | this.goto_url = function(action, query, lock) |
| | | { |
| | | var url = this.env.comm_path, |
| | | querystring = query ? '&'+query : ''; |
| | | |
| | | // overwrite task name |
| | | if (action.match(/([a-z]+)\/([a-z-_]+)/)) { |
| | | action = RegExp.$2; |
| | | url = url.replace(/\_task=[a-z]+/, '_task='+RegExp.$1); |
| | | } |
| | | |
| | | this.redirect(url+'&_action='+action+querystring, lock); |
| | | this.redirect(this.url(action, query)); |
| | | }; |
| | | |
| | | // send a http request to the server |
| | | this.http_request = function(action, query, lock) |
| | | { |
| | | var url = this.env.comm_path; |
| | | |
| | | // overwrite task name |
| | | if (action.match(/([a-z]+)\/([a-z-_]+)/)) { |
| | | action = RegExp.$2; |
| | | url = url.replace(/\_task=[a-z]+/, '_task='+RegExp.$1); |
| | | } |
| | | var url = this.url(action, query); |
| | | |
| | | // trigger plugin hook |
| | | var result = this.triggerEvent('request'+action, query); |
| | | |
| | | if (typeof result != 'undefined') { |
| | | if (result !== undefined) { |
| | | // abort if one the handlers returned false |
| | | if (result === false) |
| | | return false; |
| | |
| | | query = result; |
| | | } |
| | | |
| | | url += '&_remote=1&_action=' + action + (query ? '&' : '') + query; |
| | | url += '&_remote=1'; |
| | | |
| | | // send request |
| | | console.log('HTTP GET: ' + url); |
| | |
| | | // send a http POST request to the server |
| | | this.http_post = function(action, postdata, lock) |
| | | { |
| | | var url = this.env.comm_path; |
| | | var url = this.url(action); |
| | | |
| | | // overwrite task name |
| | | if (action.match(/([a-z]+)\/([a-z-_]+)/)) { |
| | | action = RegExp.$2; |
| | | url = url.replace(/\_task=[a-z]+/, '_task='+RegExp.$1); |
| | | } |
| | | |
| | | url += '&_action=' + action; |
| | | |
| | | if (postdata && typeof(postdata) == 'object') { |
| | | if (postdata && typeof postdata === 'object') { |
| | | postdata._remote = 1; |
| | | postdata._unlock = (lock ? lock : 0); |
| | | } |
| | |
| | | |
| | | // trigger plugin hook |
| | | var result = this.triggerEvent('request'+action, postdata); |
| | | if (typeof result != 'undefined') { |
| | | if (result !== undefined) { |
| | | // abort if one the handlers returned false |
| | | if (result === false) |
| | | return false; |
| | |
| | | this.set_env(response.env); |
| | | |
| | | // we have labels to add |
| | | if (typeof response.texts == 'object') { |
| | | if (typeof response.texts === 'object') { |
| | | for (var name in response.texts) |
| | | if (typeof response.texts[name] == 'string') |
| | | if (typeof response.texts[name] === 'string') |
| | | this.add_label(name, response.texts[name]); |
| | | } |
| | | |
| | |
| | | this.display_message(this.get_label('servererror') + ' (' + errmsg + ')', 'error'); |
| | | }; |
| | | |
| | | // post the given form to a hidden iframe |
| | | this.async_upload_form = function(form, action, onload) |
| | | { |
| | | var ts = new Date().getTime(), |
| | | frame_name = 'rcmupload'+ts; |
| | | |
| | | // have to do it this way for IE |
| | | // otherwise the form will be posted to a new window |
| | | if (document.all) { |
| | | var html = '<iframe name="'+frame_name+'" src="program/blank.gif" style="width:0;height:0;visibility:hidden;"></iframe>'; |
| | | document.body.insertAdjacentHTML('BeforeEnd', html); |
| | | } |
| | | else { // for standards-compilant browsers |
| | | var frame = document.createElement('iframe'); |
| | | frame.name = frame_name; |
| | | frame.style.border = 'none'; |
| | | frame.style.width = 0; |
| | | frame.style.height = 0; |
| | | frame.style.visibility = 'hidden'; |
| | | document.body.appendChild(frame); |
| | | } |
| | | |
| | | // handle upload errors, parsing iframe content in onload |
| | | $(frame_name).bind('load', {ts:ts}, onload); |
| | | |
| | | form.target = frame_name; |
| | | form.action = this.url(action, { _uploadid:ts }); |
| | | form.setAttribute('enctype', 'multipart/form-data'); |
| | | form.submit(); |
| | | |
| | | return frame_name; |
| | | }; |
| | | |
| | | // starts interval for keep-alive/check-recent signal |
| | | this.start_keepalive = function() |
| | | { |
| | |
| | | // gets cursor position |
| | | this.get_caret_pos = function(obj) |
| | | { |
| | | if (typeof(obj.selectionEnd)!='undefined') |
| | | if (obj.selectionEnd !== undefined) |
| | | return obj.selectionEnd; |
| | | else if (document.selection && document.selection.createRange) { |
| | | var range = document.selection.createRange(); |
| | |
| | | |
| | | } // end object rcube_webmail |
| | | |
| | | |
| | | // some static methods |
| | | rcube_webmail.long_subject_title = function(elem, indent) |
| | | { |
| | | if (!elem.title) { |
| | | var $elem = $(elem); |
| | | if ($elem.width() + indent * 15 > $elem.parent().width()) |
| | | elem.title = $elem.html(); |
| | | } |
| | | }; |
| | | |
| | | // copy event engine prototype |
| | | rcube_webmail.prototype.addEventListener = rcube_event_engine.prototype.addEventListener; |
| | | rcube_webmail.prototype.removeEventListener = rcube_event_engine.prototype.removeEventListener; |