Make things snappier

This commit is contained in:
Simon Kornblith 2011-08-21 05:47:07 +00:00
parent 44225aa4d1
commit 8b51c3e069

View File

@ -73,68 +73,69 @@ Zotero.ItemTreeView.prototype._runCallbacks = function() {
*/ */
Zotero.ItemTreeView.prototype.setTree = function(treebox) Zotero.ItemTreeView.prototype.setTree = function(treebox)
{ {
//Zotero.debug("Calling setTree()"); try {
// Try to set the window document if not yet set //Zotero.debug("Calling setTree()");
if (treebox && !this._ownerDocument) { var start = Date.now();
try { // Try to set the window document if not yet set
this._ownerDocument = treebox.treeBody.ownerDocument; if (treebox && !this._ownerDocument) {
try {
this._ownerDocument = treebox.treeBody.ownerDocument;
}
catch (e) {}
} }
catch (e) {}
} if (this._treebox) {
if (this._needsSort) {
if (this._treebox) { this.sort();
if (this._needsSort) { }
this.sort(); return;
} }
return;
} if (!treebox) {
Components.utils.reportError("Passed treebox empty in setTree()");
if (!treebox) { }
Components.utils.reportError("Passed treebox empty in setTree()");
} this._treebox = treebox;
this._treebox = treebox; if (this._ownerDocument.defaultView.ZoteroPane_Local) {
this._ownerDocument.defaultView.ZoteroPane_Local.setItemsPaneMessage(Zotero.getString('pane.items.loading'));
if (this._ownerDocument.defaultView.ZoteroPane_Local) { this._waitAfter = start + 100;
this._ownerDocument.defaultView.ZoteroPane_Local.setItemsPaneMessage(Zotero.getString('pane.items.loading')); }
}
// Generate the tree contents in a timer to allow message above to display
var paneLoader = function(obj) {
if (Zotero.locked) { if (Zotero.locked) {
var msg = "Zotero is locked -- not loading items tree"; var msg = "Zotero is locked -- not loading items tree";
Zotero.debug(msg, 2); Zotero.debug(msg, 2);
if (obj._ownerDocument.defaultView.ZoteroPane_Local) { if (this._ownerDocument.defaultView.ZoteroPane_Local) {
obj._ownerDocument.defaultView.ZoteroPane_Local.clearItemsPaneMessage(); this._ownerDocument.defaultView.ZoteroPane_Local.clearItemsPaneMessage();
} }
return; return;
} }
// If a DB transaction is open, display error message and bail // If a DB transaction is open, display error message and bail
if (!Zotero.stateCheck()) { if (!Zotero.stateCheck()) {
if (obj._ownerDocument.defaultView.ZoteroPane_Local) { if (this._ownerDocument.defaultView.ZoteroPane_Local) {
obj._ownerDocument.defaultView.ZoteroPane_Local.displayErrorMessage(); this._ownerDocument.defaultView.ZoteroPane_Local.displayErrorMessage();
} }
return; return;
} }
obj.refresh(); this.refresh();
// Add a keypress listener for expand/collapse // Add a keypress listener for expand/collapse
var tree = obj._treebox.treeBody.parentNode; var tree = this._treebox.treeBody.parentNode;
var listener = function(event) { var listener = function(event) {
// Handle arrow keys specially on multiple selection, since // Handle arrow keys specially on multiple selection, since
// otherwise the tree just applies it to the last-selected row // otherwise the tree just applies it to the last-selected row
if (event.keyCode == 39 || event.keyCode == 37) { if (event.keyCode == 39 || event.keyCode == 37) {
if (obj._treebox.view.selection.count > 1) { if (this._treebox.view.selection.count > 1) {
switch (event.keyCode) { switch (event.keyCode) {
case 39: case 39:
obj.expandSelectedRows(); this.expandSelectedRows();
break; break;
case 37: case 37:
obj.collapseSelectedRows(); this.collapseSelectedRows();
break; break;
} }
@ -146,40 +147,56 @@ Zotero.ItemTreeView.prototype.setTree = function(treebox)
var key = String.fromCharCode(event.which); var key = String.fromCharCode(event.which);
if (key == '+' && !(event.ctrlKey || event.altKey || event.metaKey)) { if (key == '+' && !(event.ctrlKey || event.altKey || event.metaKey)) {
obj.expandAllRows(); this.expandAllRows();
event.preventDefault(); event.preventDefault();
return; return;
} }
else if (key == '-' && !(event.shiftKey || event.ctrlKey || event.altKey || event.metaKey)) { else if (key == '-' && !(event.shiftKey || event.ctrlKey || event.altKey || event.metaKey)) {
obj.collapseAllRows(); this.collapseAllRows();
event.preventDefault(); event.preventDefault();
return; return;
} }
}; };
// Store listener so we can call removeEventListener() // Store listener so we can call removeEventListener()
// in overlay.js::onCollectionSelected() // in overlay.js::onCollectionSelected()
obj.listener = listener; this.listener = listener;
tree.addEventListener('keypress', listener, false); tree.addEventListener('keypress', listener, false);
obj.sort(); this.sort();
obj.expandMatchParents(); this.expandMatchParents();
//Zotero.debug('Running callbacks in itemTreeView.setTree()', 4); //Zotero.debug('Running callbacks in itemTreeView.setTree()', 4);
obj._runCallbacks(); this._runCallbacks();
if (obj._ownerDocument.defaultView.ZoteroPane_Local) { if (this._ownerDocument.defaultView.ZoteroPane_Local) {
obj._ownerDocument.defaultView.ZoteroPane_Local.clearItemsPaneMessage(); this._ownerDocument.defaultView.ZoteroPane_Local.clearItemsPaneMessage();
} }
// Select a queued item from selectItem() // Select a queued item from selectItem()
if (obj._itemGroup && obj._itemGroup.itemToSelect) { if (this._itemGroup && this._itemGroup.itemToSelect) {
var item = obj._itemGroup.itemToSelect; var item = this._itemGroup.itemToSelect;
obj.selectItem(item['id'], item['expand']); this.selectItem(item['id'], item['expand']);
obj._itemGroup.itemToSelect = null; this._itemGroup.itemToSelect = null;
} }
delete this._waitAfter;
Zotero.debug("Set tree in "+(Date.now()-start)+" ms");
Zotero.wait();
} catch(e) {
Zotero.logError(e);
}
}
/**
* Checks whether it's taken long enough to load the item pane that we should show a "loading"
* message. This should be called at semi-regular intervals throughout functions that consume a lot
* of time.
*/
Zotero.ItemTreeView.prototype.showLoadingMessageIfNecessary = function() {
if(this._waitAfter && Date.now() > this._waitAfter) {
Zotero.wait();
delete this._waitAfter;
} }
this._ownerDocument.defaultView.setTimeout(paneLoader, 50, this);
} }
@ -246,6 +263,10 @@ Zotero.ItemTreeView.prototype.refresh = function()
added++; added++;
} }
this._searchItemIDs[newRows[i].id] = true; this._searchItemIDs[newRows[i].id] = true;
if(i % 100 === 0) {
this.showLoadingMessageIfNecessary();
}
} }
// Add parents of matches if not matches themselves // Add parents of matches if not matches themselves
@ -968,13 +989,14 @@ Zotero.ItemTreeView.prototype.sort = function(itemID)
// Cache primary values while sorting, since base-field-mapped getField() // Cache primary values while sorting, since base-field-mapped getField()
// calls are relatively expensive // calls are relatively expensive
var cache = []; var cache = {};
// Get the display field for a row (which might be a placeholder title) // Get the display field for a row (which might be a placeholder title)
function getField(row) { var getField;
var field; if (columnField == 'title') {
var type = row.ref.itemTypeID; getField = function (row) {
if (columnField == 'title') { var field;
var type = row.ref.itemTypeID;
switch (type) { switch (type) {
case 8: // letter case 8: // letter
case 10: // interview case 10: // interview
@ -986,24 +1008,29 @@ Zotero.ItemTreeView.prototype.sort = function(itemID)
field = row.getField(columnField, unformatted); field = row.getField(columnField, unformatted);
} }
// Ignore some leading and trailing characters when sorting // Ignore some leading and trailing characters when sorting
field = Zotero.Items.getSortTitle(field); return Zotero.Items.getSortTitle(field);
} }
else { } else {
field = row.getField(columnField, unformatted); getField = function(row) row.getField(columnField, unformatted);
}
return field;
} }
var includeTrashed = this._itemGroup.isTrash(); var includeTrashed = this._itemGroup.isTrash();
var i = 0, me = this;
function rowSort(a, b) { function rowSort(a, b) {
if(i === 1000) {
me.showLoadingMessageIfNecessary();
i = 0;
}
i++;
var cmp, fieldA, fieldB; var cmp, fieldA, fieldB;
var aItemID = a.ref.id; var aItemID = a.id;
if (cache[aItemID]) { if (cache[aItemID]) {
fieldA = cache[aItemID]; fieldA = cache[aItemID];
} }
var bItemID = b.ref.id; var bItemID = b.id;
if (cache[bItemID]) { if (cache[bItemID]) {
fieldB = cache[bItemID]; fieldB = cache[bItemID];
} }
@ -1069,14 +1096,14 @@ Zotero.ItemTreeView.prototype.sort = function(itemID)
} }
} }
if (columnField != 'firstCreator') { if (columnField !== 'firstCreator') {
cmp = creatorSort(a, b); cmp = creatorSort(a, b);
if (cmp) { if (cmp) {
return cmp; return cmp;
} }
} }
if (columnField != 'date') { if (columnField !== 'date') {
fieldA = a.getField('date', true).substr(0, 10); fieldA = a.getField('date', true).substr(0, 10);
fieldB = b.getField('date', true).substr(0, 10); fieldB = b.getField('date', true).substr(0, 10);
@ -1097,18 +1124,18 @@ Zotero.ItemTreeView.prototype.sort = function(itemID)
// //
// Try sorting by first word in firstCreator field, since we already have it // Try sorting by first word in firstCreator field, since we already have it
// //
var fieldA = firstCreatorSortCache[a.ref.id]; var fieldA = firstCreatorSortCache[a.id];
if (fieldA == undefined) { if (fieldA == undefined) {
var matches = Zotero.Items.getSortTitle(a.getField('firstCreator')).match(/^[^\s]+/); var matches = Zotero.Items.getSortTitle(a.getField('firstCreator')).match(/^[^\s]+/);
var fieldA = matches ? matches[0] : ''; var fieldA = matches ? matches[0] : '';
firstCreatorSortCache[a.ref.id] = fieldA; firstCreatorSortCache[a.id] = fieldA;
} }
var fieldB = firstCreatorSortCache[b.ref.id]; var fieldB = firstCreatorSortCache[b.id];
if (fieldB == undefined) { if (fieldB == undefined) {
var matches = Zotero.Items.getSortTitle(b.getField('firstCreator')).match(/^[^\s]+/); var matches = Zotero.Items.getSortTitle(b.getField('firstCreator')).match(/^[^\s]+/);
var fieldB = matches ? matches[0] : ''; var fieldB = matches ? matches[0] : '';
firstCreatorSortCache[b.ref.id] = fieldB; firstCreatorSortCache[b.id] = fieldB;
} }
if (!fieldA && !fieldB) { if (!fieldA && !fieldB) {
@ -1271,10 +1298,6 @@ Zotero.ItemTreeView.prototype.sort = function(itemID)
return (a > b) ? -1 : (a < b) ? 1 : 0; return (a > b) ? -1 : (a < b) ? 1 : 0;
} }
function reverseSort(a, b) {
return rowSort(a,b) * -1;
}
// Need to close all containers before sorting // Need to close all containers before sorting
var openItemIDs = this.saveOpenState(true); var openItemIDs = this.saveOpenState(true);
@ -1287,7 +1310,7 @@ Zotero.ItemTreeView.prototype.sort = function(itemID)
} }
if (order) { if (order) {
var cmp = reverseSort(this._dataItems[i], this._dataItems[row]); var cmp = -1*rowSort(this._dataItems[i], this._dataItems[row]);
} }
else { else {
var cmp = rowSort(this._dataItems[i], this._dataItems[row]); var cmp = rowSort(this._dataItems[i], this._dataItems[row]);
@ -1312,12 +1335,8 @@ Zotero.ItemTreeView.prototype.sort = function(itemID)
} }
// Full sort // Full sort
else { else {
if (order) { this._dataItems.sort(rowSort);
this._dataItems.sort(rowSort); if(!order) this._dataItems.reverse();
}
else {
this._dataItems.sort(reverseSort);
}
} }
this._refreshHashMap(); this._refreshHashMap();
@ -1471,7 +1490,7 @@ Zotero.ItemTreeView.prototype.getSelectedItems = function(asIDs)
this.selection.getRangeAt(i,start,end); this.selection.getRangeAt(i,start,end);
for (var j=start.value; j<=end.value; j++) { for (var j=start.value; j<=end.value; j++) {
if (asIDs) { if (asIDs) {
items.push(this._getItemAtRow(j).ref.id); items.push(this._getItemAtRow(j).id);
} }
else { else {
items.push(this._getItemAtRow(j).ref); items.push(this._getItemAtRow(j).ref);
@ -1515,7 +1534,7 @@ Zotero.ItemTreeView.prototype.deleteSelection = function (force)
{ {
this.selection.getRangeAt(i,start,end); this.selection.getRangeAt(i,start,end);
for (var j=start.value; j<=end.value; j++) for (var j=start.value; j<=end.value; j++)
ids.push(this._getItemAtRow(j).ref.id); ids.push(this._getItemAtRow(j).id);
} }
var itemGroup = this._itemGroup; var itemGroup = this._itemGroup;
@ -2608,6 +2627,7 @@ Zotero.ItemTreeView.TreeRow = function(ref, level, isOpen)
this.ref = ref; //the item associated with this this.ref = ref; //the item associated with this
this.level = level; this.level = level;
this.isOpen = isOpen; this.isOpen = isOpen;
this.id = ref.id;
} }
Zotero.ItemTreeView.TreeRow.prototype.getField = function(field, unformatted) Zotero.ItemTreeView.TreeRow.prototype.getField = function(field, unformatted)