summaryrefslogtreecommitdiff
path: root/program/js/app.js
diff options
context:
space:
mode:
authorThomas Bruederli <thomas@roundcube.net>2013-01-31 13:49:35 +0100
committerThomas Bruederli <thomas@roundcube.net>2013-01-31 13:49:35 +0100
commit3c309af0663f1673f921682c6ae3f673426e1397 (patch)
treec7f576fecd73e50cbdaa56548936f4eda97ded5a /program/js/app.js
parentb7ea947844b97fe4cb0e2bd37b84d79fff8014f4 (diff)
- Refactored the hierarchical mailboxlist control into a separate widget class
- Build address book directories list as hierarchical list - Make address book groups collapsible using the new new treelist widget - Use encoded identifiers for address book directory list items
Diffstat (limited to 'program/js/app.js')
-rw-r--r--program/js/app.js206
1 files changed, 67 insertions, 139 deletions
diff --git a/program/js/app.js b/program/js/app.js
index 6d5bdfe74..dbb65eea4 100644
--- a/program/js/app.js
+++ b/program/js/app.js
@@ -4,7 +4,7 @@
| |
| This file is part of the Roundcube Webmail client |
| Copyright (C) 2005-2013, The Roundcube Dev Team |
- | Copyright (C) 2011-2012, Kolab Systems AG |
+ | Copyright (C) 2011-2013, Kolab Systems AG |
| |
| Licensed under the GNU General Public License version 3 or |
| any later version with exceptions for skins & plugins. |
@@ -459,9 +459,22 @@ function rcube_webmail()
this.display_message(this.pending_message[0], this.pending_message[1], this.pending_message[2]);
// map implicit containers
- if (this.gui_objects.folderlist)
+ if (this.gui_objects.folderlist) {
this.gui_containers.foldertray = $(this.gui_objects.folderlist);
+ // init treelist widget
+ if (window.rcube_treelist_widget) {
+ this.treelist = new rcube_treelist_widget(this.gui_objects.folderlist, {
+ id_prefix: 'rcmli',
+ id_encode: this.html_identifier_encode,
+ id_decode: this.html_identifier_decode,
+ check_droptarget: function(node){ return !node.virtual && ref.check_droptarget(node.id) }
+ });
+ this.treelist.addEventListener('collapse', function(node){ ref.folder_collapsed(node) });
+ this.treelist.addEventListener('expand', function(node){ ref.folder_collapsed(node) });
+ }
+ }
+
// 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'); });
@@ -1263,11 +1276,12 @@ function rcube_webmail()
this.html_identifier = function(str, encode)
{
- str = String(str);
- if (encode)
- return Base64.encode(str).replace(/=+$/, '').replace(/\+/g, '-').replace(/\//g, '_');
- else
- return str.replace(this.identifier_expr, '_');
+ return encode ? this.html_identifier_encode(str) : String(str).replace(this.identifier_expr, '_');
+ };
+
+ this.html_identifier_encode = function(str)
+ {
+ return Base64.encode(String(str)).replace(/=+$/, '').replace(/\+/g, '-').replace(/\//g, '_');
};
this.html_identifier_decode = function(str)
@@ -1320,29 +1334,9 @@ function rcube_webmail()
if (this.preview_read_timer)
clearTimeout(this.preview_read_timer);
- // save folderlist and folders location/sizes for droptarget calculation in drag_move()
- if (this.gui_objects.folderlist && model) {
- this.initialBodyScrollTop = bw.ie ? 0 : window.pageYOffset;
- this.initialListScrollTop = this.gui_objects.folderlist.parentNode.scrollTop;
-
- var k, li, height,
- list = $(this.gui_objects.folderlist);
- pos = list.offset();
-
- this.env.folderlist_coords = { x1:pos.left, y1:pos.top, x2:pos.left + list.width(), y2:pos.top + list.height() };
-
- this.env.folder_coords = [];
- for (k in model) {
- if (li = this.get_folder_li(k)) {
- // only visible folders
- if (height = li.firstChild.offsetHeight) {
- pos = $(li.firstChild).offset();
- this.env.folder_coords[k] = { x1:pos.left, y1:pos.top,
- x2:pos.left + li.firstChild.offsetWidth, y2:pos.top + height, on:0 };
- }
- }
- }
- }
+ // prepare treelist widget for dragging interactions
+ if (this.treelist)
+ this.treelist.drag_start();
};
this.drag_end = function(e)
@@ -1350,87 +1344,28 @@ function rcube_webmail()
this.drag_active = false;
this.env.last_folder_target = null;
- if (this.folder_auto_timer) {
- clearTimeout(this.folder_auto_timer);
- this.folder_auto_timer = null;
- this.folder_auto_expand = null;
- }
-
- // over the folders
- if (this.gui_objects.folderlist && this.env.folder_coords) {
- for (var k in this.env.folder_coords) {
- if (this.env.folder_coords[k].on)
- $(this.get_folder_li(k)).removeClass('droptarget');
- }
- }
+ if (this.treelist)
+ this.treelist.drag_end();
};
this.drag_move = function(e)
{
- if (this.gui_objects.folderlist && this.env.folder_coords) {
- var k, li, div, check, oldclass,
+ if (this.gui_objects.folderlist) {
+ var drag_target, oldclass,
layerclass = 'draglayernormal',
- mouse = rcube_event.get_mouse_pos(e),
- pos = this.env.folderlist_coords,
- // offsets to compensate for scrolling while dragging a message
- boffset = bw.ie ? -document.documentElement.scrollTop : this.initialBodyScrollTop,
- moffset = this.initialListScrollTop-this.gui_objects.folderlist.parentNode.scrollTop;
+ mouse = rcube_event.get_mouse_pos(e);
if (this.contact_list && this.contact_list.draglayer)
oldclass = this.contact_list.draglayer.attr('class');
- mouse.y += -moffset-boffset;
-
- // if mouse pointer is outside of folderlist
- if (mouse.x < pos.x1 || mouse.x >= pos.x2 || mouse.y < pos.y1 || mouse.y >= pos.y2) {
- if (this.env.last_folder_target) {
- $(this.get_folder_li(this.env.last_folder_target)).removeClass('droptarget');
- this.env.folder_coords[this.env.last_folder_target].on = 0;
- this.env.last_folder_target = null;
- }
- if (layerclass != oldclass && this.contact_list && this.contact_list.draglayer)
- this.contact_list.draglayer.attr('class', layerclass);
- return;
+ // mouse intersects a valid drop target on the treelist
+ if (this.treelist && (drag_target = this.treelist.intersects(mouse, true))) {
+ this.env.last_folder_target = drag_target;
+ layerclass = 'draglayer' + (this.check_droptarget(drag_target) > 1 ? 'copy' : 'normal');
}
-
- // over the folders
- for (k in this.env.folder_coords) {
- pos = this.env.folder_coords[k];
- if (mouse.x >= pos.x1 && mouse.x < pos.x2 && mouse.y >= pos.y1 && mouse.y < pos.y2) {
- if (check = this.check_droptarget(k)) {
- li = this.get_folder_li(k);
- div = $(li.getElementsByTagName('div')[0]);
-
- // if the folder is collapsed, expand it after 1sec and restart the drag & drop process.
- if (div.hasClass('collapsed')) {
- if (this.folder_auto_timer)
- clearTimeout(this.folder_auto_timer);
-
- this.folder_auto_expand = this.env.mailboxes[k].id;
- this.folder_auto_timer = setTimeout(function() {
- rcmail.command('collapse-folder', rcmail.folder_auto_expand);
- rcmail.drag_start(null);
- }, 1000);
- }
- else if (this.folder_auto_timer) {
- clearTimeout(this.folder_auto_timer);
- this.folder_auto_timer = null;
- this.folder_auto_expand = null;
- }
-
- $(li).addClass('droptarget');
- this.env.folder_coords[k].on = 1;
- this.env.last_folder_target = k;
- layerclass = 'draglayer' + (check > 1 ? 'copy' : 'normal');
- }
- // Clear target, otherwise drag end will trigger move into last valid droptarget
- else
- this.env.last_folder_target = null;
- }
- else if (pos.on) {
- $(this.get_folder_li(k)).removeClass('droptarget');
- this.env.folder_coords[k].on = 0;
- }
+ else {
+ // Clear target, otherwise drag end will trigger move into last valid droptarget
+ this.env.last_folder_target = null;
}
if (layerclass != oldclass && this.contact_list && this.contact_list.draglayer)
@@ -1440,40 +1375,33 @@ function rcube_webmail()
this.collapse_folder = function(name)
{
- var li = this.get_folder_li(name, '', true),
- div = $('div:first', li),
- ul = $('ul:first', li);
+ if (this.treelist)
+ this.treelist.toggle(name);
+ };
+
+ this.folder_collapsed = function(node)
+ {
+ var prefname = this.env.task == 'addressbook' ? 'collapsed_abooks' : 'collapsed_folders';
- if (div.hasClass('collapsed')) {
- ul.show();
- div.removeClass('collapsed').addClass('expanded');
- var reg = new RegExp('&'+urlencode(name)+'&');
- this.env.collapsed_folders = this.env.collapsed_folders.replace(reg, '');
- }
- else if (div.hasClass('expanded')) {
- ul.hide();
- div.removeClass('expanded').addClass('collapsed');
- this.env.collapsed_folders = this.env.collapsed_folders+'&'+urlencode(name)+'&';
+ if (node.collapsed) {
+ this.env[prefname] = this.env[prefname] + '&'+urlencode(node.id)+'&';
// select the folder if one of its childs is currently selected
// don't select if it's virtual (#1488346)
- if (this.env.mailbox.indexOf(name + this.env.delimiter) == 0 && !$(li).hasClass('virtual'))
+ if (this.env.mailbox && this.env.mailbox.indexOf(name + this.env.delimiter) == 0 && !node.virtual)
this.command('list', name);
}
- else
- return;
-
- // Work around a bug in IE6 and IE7, see #1485309
- if (bw.ie6 || bw.ie7) {
- var siblings = li.nextSibling ? li.nextSibling.getElementsByTagName('ul') : null;
- if (siblings && siblings.length && (li = siblings[0]) && li.style && li.style.display != 'none') {
- li.style.display = 'none';
- li.style.display = '';
- }
+ else {
+ var reg = new RegExp('&'+urlencode(node.id)+'&');
+ this.env[prefname] = this.env[prefname].replace(reg, '');
}
- this.command('save-pref', { name: 'collapsed_folders', value: this.env.collapsed_folders });
- this.set_unread_count_display(name, false);
+ if (!this.drag_active) {
+ this.command('save-pref', { name: prefname, value: this.env[prefname] });
+
+ if (this.env.unread_counts)
+ this.set_unread_count_display(node.id, false);
+ }
};
this.doc_mouse_up = function(e)
@@ -1498,9 +1426,9 @@ function rcube_webmail()
if (this.drag_active && model && this.env.last_folder_target) {
var target = model[this.env.last_folder_target];
- $(this.get_folder_li(this.env.last_folder_target)).removeClass('droptarget');
this.env.last_folder_target = null;
list.draglayer.hide();
+ this.drag_end(e);
if (!this.drag_menu(e, target))
this.command('moveto', target);
@@ -4164,7 +4092,7 @@ function rcube_webmail()
else if (!this.env.search_request)
folder = group ? 'G'+src+group : src;
- this.select_folder(folder);
+ this.select_folder(folder, '', true);
this.env.source = src;
this.env.group = group;
@@ -4468,7 +4396,7 @@ function rcube_webmail()
this.name_input.bind('keydown', function(e){ return rcmail.add_input_keydown(e); });
this.env.group_renaming = true;
- var link, li = this.get_folder_li(this.env.source+this.env.group, 'rcmliG');
+ var link, li = this.get_folder_li('G'+this.env.source+this.env.group,'',true);
if (li && (link = li.firstChild)) {
$(link).hide().before(this.name_input);
}
@@ -4489,7 +4417,7 @@ function rcube_webmail()
this.remove_group_item = function(prop)
{
var li, key = 'G'+prop.source+prop.id;
- if ((li = this.get_folder_li(key))) {
+ if ((li = this.get_folder_li(key,'',true))) {
this.triggerEvent('group_delete', { source:prop.source, id:prop.id, li:li });
li.parentNode.removeChild(li);
@@ -4511,7 +4439,7 @@ function rcube_webmail()
this.name_input.bind('keydown', function(e){ return rcmail.add_input_keydown(e); });
this.name_input_li = $('<li>').addClass(type).append(this.name_input);
- var li = type == 'contactsearch' ? $('li:last', this.gui_objects.folderlist) : this.get_folder_li(this.env.source);
+ var li = type == 'contactsearch' ? $('li:last', this.gui_objects.folderlist) : $('ul.groups li:last', this.get_folder_li(this.env.source,'',true));
this.name_input_li.insertAfter(li);
}
@@ -4612,7 +4540,7 @@ function rcube_webmail()
this.reset_add_input();
var key = 'G'+prop.source+prop.id,
- li = this.get_folder_li(key),
+ li = this.get_folder_li(key,'',true),
link;
// group ID has changed, replace link node and identifiers
@@ -4651,8 +4579,8 @@ function rcube_webmail()
this.add_contact_group_row = function(prop, li, reloc)
{
var row, name = prop.name.toUpperCase(),
- sibling = this.get_folder_li(prop.source),
- prefix = 'rcmliG' + this.html_identifier(prop.source);
+ sibling = this.get_folder_li(prop.source,'',true),
+ prefix = 'rcmli' + this.html_identifier('G'+prop.source, true);
// When renaming groups, we need to remove it from DOM and insert it in the proper place
if (reloc) {
@@ -4901,12 +4829,12 @@ function rcube_webmail()
.attr('rel', id)
.click(function() { return rcmail.command('listsearch', id, this); })
.html(name),
- li = $('<li>').attr({id: 'rcmli' + this.html_identifier(key), 'class': 'contactsearch'})
+ li = $('<li>').attr({ id:'rcmli' + this.html_identifier(key,true), 'class':'contactsearch' })
.append(link),
prop = {name:name, id:id, li:li[0]};
this.add_saved_search_row(prop, li);
- this.select_folder('S'+id);
+ this.select_folder(key,'',true);
this.enable_command('search-delete', true);
this.env.search_id = id;
@@ -4960,7 +4888,7 @@ function rcube_webmail()
this.remove_search_item = function(id)
{
var li, key = 'S'+id;
- if ((li = this.get_folder_li(key))) {
+ if ((li = this.get_folder_li(key,'',true))) {
this.triggerEvent('search_delete', { id:id, li:li });
li.parentNode.removeChild(li);
@@ -4982,7 +4910,7 @@ function rcube_webmail()
}
this.reset_qsearch();
- this.select_folder('S'+id);
+ this.select_folder('S'+id, '', true);
// reset vars
this.env.current_page = 1;