|
|
@ -47,6 +47,7 @@ function rcube_webmail()
|
|
|
|
this.group2expand = {};
|
|
|
|
this.group2expand = {};
|
|
|
|
this.http_request_jobs = {};
|
|
|
|
this.http_request_jobs = {};
|
|
|
|
this.menu_stack = [];
|
|
|
|
this.menu_stack = [];
|
|
|
|
|
|
|
|
this.entity_selectors = [];
|
|
|
|
|
|
|
|
|
|
|
|
// webmail client settings
|
|
|
|
// webmail client settings
|
|
|
|
this.dblclick_time = 500;
|
|
|
|
this.dblclick_time = 500;
|
|
|
@ -979,14 +980,14 @@ function rcube_webmail()
|
|
|
|
if (this.task == 'mail')
|
|
|
|
if (this.task == 'mail')
|
|
|
|
this.move_messages(props, event);
|
|
|
|
this.move_messages(props, event);
|
|
|
|
else if (this.task == 'addressbook')
|
|
|
|
else if (this.task == 'addressbook')
|
|
|
|
this.move_contacts(props);
|
|
|
|
this.move_contacts(props, event);
|
|
|
|
break;
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
case 'copy':
|
|
|
|
case 'copy':
|
|
|
|
if (this.task == 'mail')
|
|
|
|
if (this.task == 'mail')
|
|
|
|
this.copy_messages(props, event);
|
|
|
|
this.copy_messages(props, event);
|
|
|
|
else if (this.task == 'addressbook')
|
|
|
|
else if (this.task == 'addressbook')
|
|
|
|
this.copy_contacts(props);
|
|
|
|
this.copy_contacts(props, event);
|
|
|
|
break;
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
case 'mark':
|
|
|
|
case 'mark':
|
|
|
@ -5903,10 +5904,15 @@ function rcube_webmail()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
this.env.selection_sources = $.unique(this.env.selection_sources);
|
|
|
|
this.env.selection_sources = $.unique(this.env.selection_sources);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var groupcount = 0;
|
|
|
|
|
|
|
|
if (source.groups)
|
|
|
|
|
|
|
|
$.each(this.env.contactgroups, function(){ if (this.source === ref.env.source) groupcount++ });
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// if a group is currently selected, and there is at least one contact selected
|
|
|
|
// if a group is currently selected, and there is at least one contact selected
|
|
|
|
// thend we can enable the group-remove-selected command
|
|
|
|
// thend we can enable the group-remove-selected command
|
|
|
|
|
|
|
|
this.enable_command('group-assign-selected', groupcount > 0 && selected && writable);
|
|
|
|
this.enable_command('group-remove-selected', this.env.group && selected && writable);
|
|
|
|
this.enable_command('group-remove-selected', this.env.group && selected && writable);
|
|
|
|
this.enable_command('print', selected == 1);
|
|
|
|
this.enable_command('print', selected == 1);
|
|
|
|
this.enable_command('export-selected', 'copy', selected > 0);
|
|
|
|
this.enable_command('export-selected', 'copy', selected > 0);
|
|
|
@ -5953,6 +5959,9 @@ function rcube_webmail()
|
|
|
|
|
|
|
|
|
|
|
|
this.env.address_group_stack = index < 0 ? [] : this.env.address_group_stack.slice(0, index);
|
|
|
|
this.env.address_group_stack = index < 0 ? [] : this.env.address_group_stack.slice(0, index);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// remove cached contact group selector
|
|
|
|
|
|
|
|
this.destroy_entity_selector('contactgroup-selector');
|
|
|
|
|
|
|
|
|
|
|
|
// make sure the current group is on top of the stack
|
|
|
|
// make sure the current group is on top of the stack
|
|
|
|
if (this.env.group) {
|
|
|
|
if (this.env.group) {
|
|
|
|
if (!search) search = {};
|
|
|
|
if (!search) search = {};
|
|
|
@ -6130,8 +6139,15 @@ function rcube_webmail()
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// copy contact(s) to the specified target (group or directory)
|
|
|
|
// copy contact(s) to the specified target (group or directory)
|
|
|
|
this.copy_contacts = function(to)
|
|
|
|
this.copy_contacts = function(to, event)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
|
|
|
|
if (!to) {
|
|
|
|
|
|
|
|
return this.addressbook_selector(event, function(to, obj) {
|
|
|
|
|
|
|
|
var to = $(obj).data('source') ? ref.env.contactgroups['G' + $(obj).data('source') + $(obj).data('gid')] : ref.env.address_sources[to];
|
|
|
|
|
|
|
|
ref.command('copy', to);
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
var dest = to.type == 'group' ? to.source : to.id,
|
|
|
|
var dest = to.type == 'group' ? to.source : to.id,
|
|
|
|
source = this.env.source,
|
|
|
|
source = this.env.source,
|
|
|
|
group = this.env.group ? this.env.group : '',
|
|
|
|
group = this.env.group ? this.env.group : '',
|
|
|
@ -6164,8 +6180,15 @@ function rcube_webmail()
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// move contact(s) to the specified target (group or directory)
|
|
|
|
// move contact(s) to the specified target (group or directory)
|
|
|
|
this.move_contacts = function(to)
|
|
|
|
this.move_contacts = function(to, event)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
|
|
|
|
if (!to) {
|
|
|
|
|
|
|
|
return this.addressbook_selector(event, function(to, obj) {
|
|
|
|
|
|
|
|
var to = $(obj).data('source') ? ref.env.contactgroups['G' + $(obj).data('source') + $(obj).data('gid')] : ref.env.address_sources[to];
|
|
|
|
|
|
|
|
ref.command('move', to);
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
var dest = to.type == 'group' ? to.source : to.id,
|
|
|
|
var dest = to.type == 'group' ? to.source : to.id,
|
|
|
|
source = this.env.source,
|
|
|
|
source = this.env.source,
|
|
|
|
group = this.env.group ? this.env.group : '';
|
|
|
|
group = this.env.group ? this.env.group : '';
|
|
|
@ -6392,6 +6415,10 @@ function rcube_webmail()
|
|
|
|
var key = 'G'+prop.source+prop.id;
|
|
|
|
var key = 'G'+prop.source+prop.id;
|
|
|
|
|
|
|
|
|
|
|
|
if (this.treelist.remove(key)) {
|
|
|
|
if (this.treelist.remove(key)) {
|
|
|
|
|
|
|
|
// make sure there is no cached address book or contact group selectors
|
|
|
|
|
|
|
|
this.destroy_entity_selector('addressbook-selector');
|
|
|
|
|
|
|
|
this.destroy_entity_selector('contactgroup-selector');
|
|
|
|
|
|
|
|
|
|
|
|
this.triggerEvent('group_delete', { source:prop.source, id:prop.id });
|
|
|
|
this.triggerEvent('group_delete', { source:prop.source, id:prop.id });
|
|
|
|
delete this.env.contactfolders[key];
|
|
|
|
delete this.env.contactfolders[key];
|
|
|
|
delete this.env.contactgroups[key];
|
|
|
|
delete this.env.contactgroups[key];
|
|
|
@ -6401,6 +6428,12 @@ function rcube_webmail()
|
|
|
|
this.list_contacts(prop.source, 0);
|
|
|
|
this.list_contacts(prop.source, 0);
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//assign selected contacts to a group
|
|
|
|
|
|
|
|
this.group_assign_selected = function(props, obj, event)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
this.contactgroup_selector(event, function(to) { ref.group_member_change('add', ref.contact_list.get_selection(), ref.env.source, to); });
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
//remove selected contacts from current active group
|
|
|
|
//remove selected contacts from current active group
|
|
|
|
this.group_remove_selected = function()
|
|
|
|
this.group_remove_selected = function()
|
|
|
|
{
|
|
|
|
{
|
|
|
@ -6416,6 +6449,7 @@ function rcube_webmail()
|
|
|
|
for (n=0; n<selection.length; n++) {
|
|
|
|
for (n=0; n<selection.length; n++) {
|
|
|
|
id = selection[n];
|
|
|
|
id = selection[n];
|
|
|
|
this.contact_list.remove_row(id, (n == selection.length-1));
|
|
|
|
this.contact_list.remove_row(id, (n == selection.length-1));
|
|
|
|
|
|
|
|
this.contact_list.clear_selection();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
};
|
|
|
@ -6434,6 +6468,10 @@ function rcube_webmail()
|
|
|
|
this.env.contactfolders[key] = this.env.contactgroups[key] = prop;
|
|
|
|
this.env.contactfolders[key] = this.env.contactgroups[key] = prop;
|
|
|
|
this.treelist.insert({ id:key, html:link, classes:['contactgroup'] }, prop.source, 'contactgroup');
|
|
|
|
this.treelist.insert({ id:key, html:link, classes:['contactgroup'] }, prop.source, 'contactgroup');
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// make sure there is no cached address book or contact group selectors
|
|
|
|
|
|
|
|
this.destroy_entity_selector('addressbook-selector');
|
|
|
|
|
|
|
|
this.destroy_entity_selector('contactgroup-selector');
|
|
|
|
|
|
|
|
|
|
|
|
this.triggerEvent('group_insert', { id:prop.id, source:prop.source, name:prop.name, li:this.treelist.get_item(key) });
|
|
|
|
this.triggerEvent('group_insert', { id:prop.id, source:prop.source, name:prop.name, li:this.treelist.get_item(key) });
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
@ -6476,6 +6514,10 @@ function rcube_webmail()
|
|
|
|
// update list node and re-sort it
|
|
|
|
// update list node and re-sort it
|
|
|
|
this.treelist.update(key, newnode, true);
|
|
|
|
this.treelist.update(key, newnode, true);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// make sure there is no cached address book or contact group selectors
|
|
|
|
|
|
|
|
this.destroy_entity_selector('addressbook-selector');
|
|
|
|
|
|
|
|
this.destroy_entity_selector('contactgroup-selector');
|
|
|
|
|
|
|
|
|
|
|
|
this.triggerEvent('group_update', { id:prop.id, source:prop.source, name:prop.name, li:this.treelist.get_item(key), newid:prop.newid });
|
|
|
|
this.triggerEvent('group_update', { id:prop.id, source:prop.source, name:prop.name, li:this.treelist.get_item(key), newid:prop.newid });
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
@ -8174,48 +8216,113 @@ function rcube_webmail()
|
|
|
|
elem.onclick = function() { ref.command('show-headers', '', elem); };
|
|
|
|
elem.onclick = function() { ref.command('show-headers', '', elem); };
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// create folder selector popup, position and display it
|
|
|
|
// create folder selector popup
|
|
|
|
this.folder_selector = function(event, callback)
|
|
|
|
this.folder_selector = function(event, callback)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
var container = this.folder_selector_element;
|
|
|
|
this.entity_selector('folder-selector', callback, this.env.mailboxes_list, function(obj, a) {
|
|
|
|
|
|
|
|
var n = 0, s = 0,
|
|
|
|
|
|
|
|
delim = ref.env.delimiter,
|
|
|
|
|
|
|
|
folder = ref.env.mailboxes[obj],
|
|
|
|
|
|
|
|
id = folder.id,
|
|
|
|
|
|
|
|
row = $('<li>');
|
|
|
|
|
|
|
|
|
|
|
|
if (!container) {
|
|
|
|
if (folder.virtual)
|
|
|
|
var rows = [],
|
|
|
|
a.addClass('virtual').attr({'aria-disabled': 'true', tabindex: '-1'});
|
|
|
|
delim = this.env.delimiter,
|
|
|
|
else
|
|
|
|
ul = $('<ul class="toolbarmenu">'),
|
|
|
|
a.addClass('active').data('id', folder.id);
|
|
|
|
link = document.createElement('a');
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
container = $('<div id="folder-selector" class="popupmenu"></div>');
|
|
|
|
if (folder['class'])
|
|
|
|
link.href = '#';
|
|
|
|
row.addClass(folder['class']);
|
|
|
|
link.className = 'icon';
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// loop over sorted folders list
|
|
|
|
// calculate/set indentation level
|
|
|
|
$.each(this.env.mailboxes_list, function() {
|
|
|
|
while ((s = id.indexOf(delim, s)) >= 0) {
|
|
|
|
var n = 0, s = 0,
|
|
|
|
n++; s++;
|
|
|
|
folder = ref.env.mailboxes[this],
|
|
|
|
}
|
|
|
|
id = folder.id,
|
|
|
|
a.css('padding-left', n ? (n * 16) + 'px' : 0);
|
|
|
|
a = $(link.cloneNode(false)).attr('rel', folder.id),
|
|
|
|
|
|
|
|
row = $('<li>');
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (folder.virtual)
|
|
|
|
// add folder name element
|
|
|
|
a.addClass('virtual').attr({'aria-disabled': 'true', tabindex: '-1'});
|
|
|
|
a.append($('<span>').text(folder.name));
|
|
|
|
else
|
|
|
|
|
|
|
|
a.addClass('active').data('id', folder.id);
|
|
|
|
return row.append(a);
|
|
|
|
|
|
|
|
}, event);
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// create addressbook selector popup
|
|
|
|
|
|
|
|
this.addressbook_selector = function(event, callback)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
// build addressbook + groups list
|
|
|
|
|
|
|
|
var combined_sources = [];
|
|
|
|
|
|
|
|
|
|
|
|
if (folder['class'])
|
|
|
|
// check we really need it before processing
|
|
|
|
row.addClass(folder['class']);
|
|
|
|
if (!this.entity_selectors['addressbook-selector']) {
|
|
|
|
|
|
|
|
$.each(this.env.address_sources, function() {
|
|
|
|
|
|
|
|
if (!this.readonly) {
|
|
|
|
|
|
|
|
var source = this;
|
|
|
|
|
|
|
|
combined_sources.push(source);
|
|
|
|
|
|
|
|
|
|
|
|
// calculate/set indentation level
|
|
|
|
$.each(ref.env.contactgroups, function() {
|
|
|
|
while ((s = id.indexOf(delim, s)) >= 0) {
|
|
|
|
if (source.id === this.source) {
|
|
|
|
n++; s++;
|
|
|
|
combined_sources.push(this);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
a.css('padding-left', n ? (n * 16) + 'px' : 0);
|
|
|
|
});
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
this.entity_selector('addressbook-selector', callback, combined_sources, function(obj, a) {
|
|
|
|
|
|
|
|
var row = $('<li>');
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (obj.type == 'group') {
|
|
|
|
|
|
|
|
a.attr('rel', this.source + ':' + this.id);
|
|
|
|
|
|
|
|
a.addClass('contactgroup');
|
|
|
|
|
|
|
|
a.data('source', this.source).data('gid', this.id);
|
|
|
|
|
|
|
|
a.addClass('active').data('id', this.source + ':' + this.id);
|
|
|
|
|
|
|
|
a.css('padding-left', '16px');
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
else {
|
|
|
|
|
|
|
|
a.addClass('addressbook');
|
|
|
|
|
|
|
|
a.addClass('active').data('id', obj.id);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
a.append($('<span>').text(obj.name));
|
|
|
|
|
|
|
|
|
|
|
|
// add folder name element
|
|
|
|
return row.append(a);
|
|
|
|
a.append($('<span>').text(folder.name));
|
|
|
|
}, event);
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
row.append(a);
|
|
|
|
// create contactgroup selector popup
|
|
|
|
rows.push(row);
|
|
|
|
this.contactgroup_selector = function(event, callback)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
this.entity_selector('contactgroup-selector', callback, this.env.contactgroups, function(obj, a) {
|
|
|
|
|
|
|
|
if (ref.env.source === obj.source) {
|
|
|
|
|
|
|
|
var row = $('<li>');
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
a.addClass('contactgroup');
|
|
|
|
|
|
|
|
a.addClass('active').data('id', obj.id);
|
|
|
|
|
|
|
|
a.append($('<span>').text(obj.name));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return row.append(a);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}, event);
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// create selector popup (eg for folders or address books), position and display it
|
|
|
|
|
|
|
|
this.entity_selector = function(name, click_callback, entity_list, list_callback, event)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
var container = this.entity_selectors[name];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!container) {
|
|
|
|
|
|
|
|
var rows = [],
|
|
|
|
|
|
|
|
container = $('<div>').attr('id', name).addClass('popupmenu'),
|
|
|
|
|
|
|
|
ul = $('<ul>').addClass('toolbarmenu'),
|
|
|
|
|
|
|
|
link = document.createElement('a');
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
link.href = '#';
|
|
|
|
|
|
|
|
link.className = 'icon';
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// loop over entity list
|
|
|
|
|
|
|
|
$.each(entity_list, function() {
|
|
|
|
|
|
|
|
var a = $(link.cloneNode(false)).attr('rel', this.id);
|
|
|
|
|
|
|
|
rows.push(list_callback(this, a));
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
ul.append(rows).appendTo(container);
|
|
|
|
ul.append(rows).appendTo(container);
|
|
|
@ -8230,18 +8337,23 @@ function rcube_webmail()
|
|
|
|
|
|
|
|
|
|
|
|
// register delegate event handler for folder item clicks
|
|
|
|
// register delegate event handler for folder item clicks
|
|
|
|
container.on('click', 'a.active', function(e) {
|
|
|
|
container.on('click', 'a.active', function(e) {
|
|
|
|
container.data('callback')($(this).data('id'));
|
|
|
|
container.data('callback')($(this).data('id'), this);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
this.folder_selector_element = container;
|
|
|
|
this.entity_selectors[name] = container;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
container.data('callback', callback);
|
|
|
|
container.data('callback', click_callback);
|
|
|
|
|
|
|
|
|
|
|
|
// position menu on the screen
|
|
|
|
// position menu on the screen
|
|
|
|
this.show_menu('folder-selector', true, event);
|
|
|
|
this.show_menu(name, true, event);
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
this.destroy_entity_selector = function(name)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
$("#" + name).remove();
|
|
|
|
|
|
|
|
delete this.entity_selectors[name];
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/***********************************************/
|
|
|
|
/***********************************************/
|
|
|
|
/********* popup menu functions *********/
|
|
|
|
/********* popup menu functions *********/
|
|
|
|