Move some list manipulation functionality to the new treelist widget

pull/15/head
Thomas Bruederli 12 years ago
parent 92ba29f04f
commit 344943f6ce

@ -472,6 +472,7 @@ function rcube_webmail()
});
this.treelist.addEventListener('collapse', function(node){ ref.folder_collapsed(node) });
this.treelist.addEventListener('expand', function(node){ ref.folder_collapsed(node) });
this.treelist.addEventListener('select', function(node){ ref.triggerEvent('selectfolder', { folder:node.id, prefix:'rcmli' }) });
}
}
@ -4416,11 +4417,8 @@ function rcube_webmail()
// callback from server upon group-delete command
this.remove_group_item = function(prop)
{
var li, key = 'G'+prop.source+prop.id;
if ((li = this.get_folder_li(key,'',true))) {
this.triggerEvent('group_delete', { source:prop.source, id:prop.id, li:li });
li.parentNode.removeChild(li);
var key = 'G'+prop.source+prop.id;
if (this.treelist.remove(key)) {
delete this.env.contactfolders[key];
delete this.env.contactgroups[key];
}
@ -4524,14 +4522,12 @@ function rcube_webmail()
link = $('<a>').attr('href', '#')
.attr('rel', prop.source+':'+prop.id)
.click(function() { return rcmail.command('listgroup', prop, this); })
.html(prop.name),
li = $('<li>').attr({id: 'rcmli'+this.html_identifier(key), 'class': 'contactgroup'})
.append(link);
.html(prop.name);
this.env.contactfolders[key] = this.env.contactgroups[key] = prop;
this.add_contact_group_row(prop, li);
this.treelist.insert({ id:key, html:link, classes:['contactgroup'] }, prop.source, true);
this.triggerEvent('group_insert', { id:prop.id, source:prop.source, name:prop.name, li:li[0] });
this.triggerEvent('group_insert', { id:prop.id, source:prop.source, name:prop.name, li:this.treelist.get_item(key) });
};
// callback for renaming a contact group
@ -4540,15 +4536,13 @@ function rcube_webmail()
this.reset_add_input();
var key = 'G'+prop.source+prop.id,
li = this.get_folder_li(key,'',true),
link;
newnode = {};
// group ID has changed, replace link node and identifiers
if (li && prop.newid) {
if (prop.newid) {
var newkey = 'G'+prop.source+prop.newid,
newprop = $.extend({}, prop);;
newprop = $.extend({}, prop);
li.id = 'rcmli' + this.html_identifier(newkey);
this.env.contactfolders[newkey] = this.env.contactfolders[key];
this.env.contactfolders[newkey].id = prop.newid;
this.env.group = prop.newid;
@ -4559,45 +4553,22 @@ function rcube_webmail()
newprop.id = prop.newid;
newprop.type = 'group';
link = $('<a>').attr('href', '#')
newnode.id = newkey;
newnode.html = $('<a>').attr('href', '#')
.attr('rel', prop.source+':'+prop.newid)
.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;
else {
$(this.treelist.get_item(key)).children().first().html(prop.name);
this.env.contactfolders[key].name = this.env.contactgroups[key].name = prop.name;
this.add_contact_group_row(prop, $(li), true);
this.triggerEvent('group_update', { id:prop.id, source:prop.source, name:prop.name, li:li[0], newid:prop.newid });
};
// add contact group row to the list, with sorting
this.add_contact_group_row = function(prop, li, reloc)
{
var row, name = prop.name.toUpperCase(),
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) {
row = li.clone(true);
li.remove();
}
else
row = li;
$('li[id^="'+prefix+'"]', this.gui_objects.folderlist).each(function(i, elem) {
if (name >= $(this).text().toUpperCase())
sibling = elem;
else
return false;
});
// update list node and re-sort it
this.treelist.update(key, newnode, true);
row.insertAfter(sibling);
this.triggerEvent('group_update', { id:prop.id, source:prop.source, name:prop.name, li:this.treelist.get_item(key), newid:prop.newid });
};
this.update_group_commands = function()
@ -4829,11 +4800,9 @@ 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,true), 'class':'contactsearch' })
.append(link),
prop = {name:name, id:id, li:li[0]};
prop = { name:name, id:id };
this.add_saved_search_row(prop, li);
this.treelist.insert({ id:key, html:link, classes:['contactsearch'] }, null, 'contactsearch');
this.select_folder(key,'',true);
this.enable_command('search-delete', true);
this.env.search_id = id;
@ -4841,35 +4810,6 @@ function rcube_webmail()
this.triggerEvent('abook_search_insert', prop);
};
// add saved search row to the list, with sorting
this.add_saved_search_row = function(prop, li, reloc)
{
var row, sibling, name = prop.name.toUpperCase();
// When renaming groups, we need to remove it from DOM and insert it in the proper place
if (reloc) {
row = li.clone(true);
li.remove();
}
else
row = li;
$('li[class~="contactsearch"]', this.gui_objects.folderlist).each(function(i, elem) {
if (!sibling)
sibling = this.previousSibling;
if (name >= $(this).text().toUpperCase())
sibling = elem;
else
return false;
});
if (sibling)
row.insertAfter(sibling);
else
row.appendTo(this.gui_objects.folderlist);
};
// creates an input for saved search name
this.search_create = function()
{
@ -4888,10 +4828,8 @@ function rcube_webmail()
this.remove_search_item = function(id)
{
var li, key = 'S'+id;
if ((li = this.get_folder_li(key,'',true))) {
if (this.treelist.remove(key)) {
this.triggerEvent('search_delete', { id:id, li:li });
li.parentNode.removeChild(li);
}
this.env.search_id = null;
@ -5716,7 +5654,10 @@ function rcube_webmail()
// mark a mailbox as selected and set environment variable
this.select_folder = function(name, prefix, encode)
{
if (this.gui_objects.folderlist) {
if (this.treelist) {
this.treelist.select(name);
}
else if (this.gui_objects.folderlist) {
var current_li, target_li;
if ((current_li = $('li.selected', this.gui_objects.folderlist))) {

@ -55,6 +55,11 @@ function rcube_treelist_widget(node, p)
this.drag_start = drag_start;
this.drag_end = drag_end;
this.intersects = intersects;
this.update = update_node;
this.insert = insert;
this.remove = remove;
this.get_item = get_item;
this.get_selection = get_selection;
/////// startup code (constructor)
@ -68,8 +73,7 @@ function rcube_treelist_widget(node, p)
}
// load data from DOM
else {
data = walk_list(container);
// console.log(data);
update_data();
}
// register click handlers on list
@ -169,6 +173,131 @@ function rcube_treelist_widget(node, p)
return id2dom(id).get(0);
}
/**
* Insert the given node
*/
function insert(node, parent_id, sort)
{
var li, parent_li,
parent_node = parent_id ? indexbyid[parent_id] : null;
// insert as child of an existing node
if (parent_node) {
if (!parent_node.children)
parent_node.children = [];
parent_node.children.push(node);
parent_li = id2dom(parent_id);
// re-render the entire subtree
if (parent_node.children.length == 1) {
render_node(parent_node, parent_li.parent(), parent_li);
li = id2dom(node.id);
}
else {
// append new node to parent's child list
li = render_node(node, parent_li.children('ul').first());
}
}
// insert at top level
else {
data.push(node);
li = render_node(node, container);
}
indexbyid[node.id] = node;
if (sort) {
resort_node(li, typeof sort == 'string' ? '[class~="' + sort + '"]' : '');
}
}
/**
* Update properties of an existing node
*/
function update_node(id, updates, sort)
{
var li, node = indexbyid[id];
if (node) {
li = id2dom(id);
if (updates.id || updates.html || updates.children || updates.classes) {
$.extend(node, updates);
render_node(node, li.parent(), li);
}
if (node.id != id) {
delete indexbyid[id];
indexbyid[node.id] = node;
}
if (sort) {
resort_node(li, typeof sort == 'string' ? '[class~="' + sort + '"]' : '');
}
}
}
/**
* Helper method to sort the list of the given item
*/
function resort_node(li, filter)
{
var first, sibling,
myid = li.get(0).id,
sortname = li.children().first().text().toUpperCase();
li.parent().children('li' + filter).each(function(i, elem) {
if (i == 0)
first = elem;
if (elem.id == myid) {
// skip
}
else if (elem.id != myid && sortname >= $(elem).children().first().text().toUpperCase()) {
sibling = elem;
}
else {
return false;
}
});
if (sibling) {
li.insertAfter(sibling);
}
else {
li.insertBefore(first);
}
// reload data from dom
update_data();
}
/**
* Remove the item with the given ID
*/
function remove(id)
{
var node, li;
if (node = indexbyid[id]) {
li = id2dom(id);
li.remove();
node.deleted = true;
delete indexbyid[id];
return true;
}
return false;
}
/**
* (Re-)read tree data from DOM
*/
function update_data()
{
data = walk_list(container);
}
/**
* Apply the 'collapsed' status of the data node to the corresponding DOM element(s)
*/
@ -202,12 +331,26 @@ function rcube_treelist_widget(node, p)
/**
* Render a specific node into the DOM list
*/
function render_node(node, parent)
function render_node(node, parent, replace)
{
var li = $('<li>' + node.html + '</li>')
.attr('id', p.id_prefix + node.id)
.addClass((node.classes || []).join(' '))
.appendTo(parent);
if (node.deleted)
return;
var li = $('<li>')
.attr('id', p.id_prefix + (p.id_encode ? p.id_encode(node.id) : node.id))
.addClass((node.classes || []).join(' '));
if (replace)
replace.replaceWith(li);
else
li.appendTo(parent);
if (typeof node.html == 'string') {
li.html(node.html);
}
else if (typeof node.html == 'object') {
li.append(node.html);
}
if (node.virtual)
li.addClass('virtual');
@ -217,7 +360,7 @@ function rcube_treelist_widget(node, p)
// add child list and toggle icon
if (node.children && node.children.length) {
$('<div class="treetoggle '+(node.collapsed ? 'collapsed' : 'expanded') + '">&nbsp;</div>').appendTo(li);
var ul = $('<ul>').appendTo(li);
var ul = $('<ul>').appendTo(li).attr('class', node.childlistclass);
if (node.collapsed)
ul.hide();
@ -225,6 +368,8 @@ function rcube_treelist_widget(node, p)
render_node(node.children[i], ul);
}
}
return li;
}
/**
@ -245,6 +390,7 @@ function rcube_treelist_widget(node, p)
}
if (node.children.length) {
node.childlistclass = li.children('ul').attr('class');
node.collapsed = li.children('ul').css('display') == 'none';
}
if (li.hasClass('selected')) {

Loading…
Cancel
Save