Trying to use a document fragment for the roster view

This commit is contained in:
JC Brand 2014-07-25 09:58:42 +02:00
parent a9f9328682
commit cfa55896a5
2 changed files with 52 additions and 34 deletions

View File

@ -3266,7 +3266,8 @@
toggle_state: toggle_state
});
}
this.$el.hide().html(roster_markup);
this.$fragment = $('<span>');
this.$fragment.append($(roster_markup));
},
onAdd: function (item) {
@ -3281,6 +3282,14 @@
}
},
showRoster: function () {
if (this.$fragment) {
this.$el.html(this.$fragment)
delete this.$fragment;
}
return this;
},
onChange: function (item) {
if ((_.size(item.changed) === 1) && _.contains(_.keys(item.changed), 'sorted')) {
return;
@ -3342,6 +3351,17 @@
return this;
},
getRosterElement: function () {
// TODO: see is _ensureElement can be used.
// Return the document fragment if it exists.
var $el;
if (this.$fragment) {
return this.$fragment;
} else {
return this.$el;
}
},
addRosterItem: function (item) {
if ((converse.show_only_online_users) && (item.get('chat_status') !== 'online')) {
return this;
@ -3352,13 +3372,14 @@
return this;
}
view.render()
var $el = this.getRosterElement();
if (view.$el.hasClass('current-xmpp-contact')) {
// TODO: need to add group support
this.$('.roster-group').after(view.el);
$el.find('.roster-group').after(view.el);
} else if (view.$el.hasClass('pending-xmpp-contact')) {
this.$('#pending-xmpp-contacts').after(view.el);
$el.find('#pending-xmpp-contacts').after(view.el);
} else if (view.$el.hasClass('requesting-xmpp-contact')) {
this.$('#xmpp-contact-requests').after(view.render().el);
$el.find('#xmpp-contact-requests').after(view.render().el);
}
return this;
},
@ -3379,9 +3400,10 @@
},
toggleHeaders: function () {
var $contact_requests = this.$('#xmpp-contact-requests'),
$pending_contacts = this.$('#pending-xmpp-contacts');
var $groups = this.$el.find('.roster-group');
var $el = this.getRosterElement();
var $contact_requests = $el.find('#xmpp-contact-requests'),
$pending_contacts = $el.find('#pending-xmpp-contacts');
var $groups = $el.find('.roster-group');
// Hide the headers if there are no contacts under them
_.each([$groups, $contact_requests, $pending_contacts], function (h) {
var show_or_hide = function (h) {
@ -3431,29 +3453,19 @@
* 1). See if the jquery detach method can be somehow used to avoid DOM reflows.
* 2). Likewise see if documentFragment can be used.
*/
this.$el.find('.roster-group').each($.proxy(function (idx, group) {
var $el = this.getRosterElement();
$el.find('.roster-group').each($.proxy(function (idx, group) {
var $group = $(group);
var $contacts = $group.nextUntil('dt', 'dd.current-xmpp-contact');
$group.after($contacts.tsort({sortFunction: this.sortFunction, data: 'status'}, 'a'));
},this));
// Also sort pending and requesting contacts
var crit = {order:'asc'},
$contact_requests = this.$('#xmpp-contact-requests'),
$pending_contacts = this.$('#pending-xmpp-contacts');
$contact_requests = $el.find('#xmpp-contact-requests'),
$pending_contacts = $el.find('#pending-xmpp-contacts');
$pending_contacts.after($pending_contacts.siblings('dd.pending-xmpp-contact').tsort(crit));
$contact_requests.after($contact_requests.siblings('dd.requesting-xmpp-contact').tsort(crit));
return this;
},
showRoster: function () {
if (!this.$el.is(':visible')) {
// Once all initial roster items have been added, we
// can show the roster.
// TODO: It would be more efficient to use a
// documentFragment and then put that in the DOM
this.$el.show();
}
return this;
}
});

View File

@ -129,28 +129,32 @@
describe("The Contacts Roster", $.proxy(function (mock, utils) {
describe("Pending Contacts", $.proxy(function () {
beforeEach($.proxy(function () {
runs(function () {
converse.rosterview.model.reset();
utils.createContacts('pending').openControlBox();
});
waits(50);
runs(function () {
utils.openContactsPanel();
});
}, converse));
function _clearContacts () {
utils.clearBrowserStorage();
converse.rosterview.model.reset();
converse.rosterview.initialize();
};
function _addContacts () {
_clearContacts();
// Must be initialized, so that render is called and documentFragment set up.
utils.createContacts('pending').openControlBox();
utils.openContactsPanel();
};
it("do not have a header if there aren't any", $.proxy(function () {
converse.rosterview.model.reset();
_addContacts();
this.rosterview.model.reset();
expect(this.rosterview.$el.find('dt#pending-xmpp-contacts').css('display')).toEqual('none');
}, converse));
it("can be collapsed under their own header", $.proxy(function () {
_addContacts();
checkHeaderToggling.apply(this, [this.rosterview.$el.find('dt#pending-xmpp-contacts')]);
}, converse));
it("can be added to the roster", $.proxy(function () {
converse.rosterview.model.reset(); // We want to manually create users so that we can spy
_clearContacts();
spyOn(converse, 'emit');
spyOn(this.rosterview, 'updateRoster').andCallThrough();
runs($.proxy(function () {
@ -171,6 +175,7 @@
}, converse));
it("can be removed by the user", $.proxy(function () {
_addContacts();
var jid = mock.pend_names[0].replace(/ /g,'.').toLowerCase() + '@localhost';
var view = this.rosterview.get(jid);
spyOn(window, 'confirm').andReturn(true);
@ -190,6 +195,7 @@
}, converse));
it("will lose their own header once the last one has been removed", $.proxy(function () {
_addContacts();
var view;
spyOn(window, 'confirm').andReturn(true);
for (i=0; i<mock.pend_names.length; i++) {
@ -200,7 +206,7 @@
}, converse));
it("can be added to the roster and they will be sorted alphabetically", $.proxy(function () {
converse.rosterview.model.reset(); // We want to manually create users so that we can spy
_clearContacts();
var i, t, is_last;
spyOn(converse, 'emit');
spyOn(this.rosterview, 'updateRoster').andCallThrough();