Bug 1171903 - Add endless scrolling to storage inspector to view more items. r=miker

This commit is contained in:
Tim Nguyen 2016-01-07 14:15:00 +01:00
Родитель b23827ce73
Коммит 66d777bfab
2 изменённых файлов: 64 добавлений и 10 удалений

Просмотреть файл

@ -4,11 +4,15 @@
"use strict";
const {Cc, Ci, Cu} = require("chrome");
const EventEmitter = require("devtools/shared/event-emitter");
loader.lazyImporter(this, "setNamedTimeout",
"resource://devtools/client/shared/widgets/ViewHelpers.jsm");
loader.lazyImporter(this, "clearNamedTimeout",
"resource://devtools/client/shared/widgets/ViewHelpers.jsm");
const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
const HTML_NS = "http://www.w3.org/1999/xhtml";
const AFTER_SCROLL_DELAY = 100;
// Different types of events emitted by the Various components of the TableWidget
const EVENTS = {
@ -18,7 +22,8 @@ const EVENTS = {
ROW_SELECTED: "row-selected",
ROW_UPDATED: "row-updated",
HEADER_CONTEXT_MENU: "header-context-menu",
ROW_CONTEXT_MENU: "row-context-menu"
ROW_CONTEXT_MENU: "row-context-menu",
SCROLL_END: "scroll-end"
};
Object.defineProperty(this, "EVENTS", {
value: EVENTS,
@ -67,6 +72,8 @@ function TableWidget(node, options={}) {
this.tbody.setAttribute("flex", "1");
this.tbody.setAttribute("tabindex", "0");
this._parent.appendChild(this.tbody);
this.afterScroll = this.afterScroll.bind(this);
this.tbody.addEventListener("scroll", this.onScroll.bind(this));
this.placeholder = this.document.createElementNS(XUL_NS, "label");
this.placeholder.className = "plain table-widget-empty-text";
@ -428,6 +435,27 @@ TableWidget.prototype = {
column.sort(sortedItems);
}
}
},
/**
* Calls the afterScroll function when the user has stopped scrolling
*/
onScroll: function() {
clearNamedTimeout("table-scroll");
setNamedTimeout("table-scroll", AFTER_SCROLL_DELAY, this.afterScroll);
},
/**
* Emits the "scroll-end" event when the whole table is scrolled
*/
afterScroll: function() {
let scrollHeight = this.tbody.getBoundingClientRect().height -
this.tbody.querySelector(".table-widget-column-header").clientHeight;
// Emit scroll-end event when 9/10 of the table is scrolled
if (this.tbody.scrollTop >= 0.9 * scrollHeight) {
this.emit("scroll-end");
}
}
};

Просмотреть файл

@ -72,6 +72,9 @@ var StorageUI = this.StorageUI = function StorageUI(front, target, panelWin) {
this.displayObjectSidebar = this.displayObjectSidebar.bind(this);
this.table.on(TableWidget.EVENTS.ROW_SELECTED, this.displayObjectSidebar);
this.handleScrollEnd = this.handleScrollEnd.bind(this);
this.table.on(TableWidget.EVENTS.SCROLL_END, this.handleScrollEnd);
this.sidebar = this._panelDoc.getElementById("storage-sidebar");
this.sidebar.setAttribute("width", "300");
this.view = new VariablesView(this.sidebar.firstChild,
@ -99,6 +102,7 @@ StorageUI.prototype = {
storageTypes: null,
shouldResetColumns: true,
shouldLoadMoreItems: true,
destroy: function() {
this.front.off("stores-update", this.onUpdate);
@ -302,11 +306,14 @@ StorageUI.prototype = {
* @param {array} names
* Names of particular store objects. Empty if all are requested
* @param {number} reason
* 2 for update, 1 for new row in an existing table and 0 when
* populating a table for the first time for the given host/type
* 3 for loading next 50 items, 2 for update, 1 for new row in an
* existing table and 0 when populating a table for the first time
* for the given host/type
*/
fetchStorageObjects: function(type, host, names, reason) {
this.storageTypes[type].getStoreObjects(host, names).then(({data}) => {
let fetchOpts = reason === 3 ? {offset: this.itemOffset}
: {};
this.storageTypes[type].getStoreObjects(host, names, fetchOpts).then(({data}) => {
if (!data.length) {
this.emit("store-objects-updated");
return;
@ -537,6 +544,7 @@ StorageUI.prototype = {
}
this.shouldResetColumns = true;
this.fetchStorageObjects(type, host, names, 0);
this.itemOffset = 0;
},
/**
@ -569,9 +577,9 @@ StorageUI.prototype = {
* @param {array[object]} data
* Array of objects to be populated in the storage table
* @param {number} reason
* The reason of this populateTable call. 2 for update, 1 for new row
* in an existing table and 0 when populating a table for the first
* time for the given host/type
* The reason of this populateTable call. 3 for loading next 50 items,
* 2 for update, 1 for new row in an existing table and 0 when
* populating a table for the first time for the given host/type
*/
populateTable: function(data, reason) {
for (let item of data) {
@ -590,7 +598,7 @@ StorageUI.prototype = {
if (item.lastAccessed != null) {
item.lastAccessed = new Date(item.lastAccessed).toLocaleString();
}
if (reason < 2) {
if (reason < 2 || reason == 3) {
this.table.push(item, reason == 0);
} else {
this.table.update(item);
@ -598,6 +606,7 @@ StorageUI.prototype = {
this.displayObjectSidebar();
}
}
this.shouldLoadMoreItems = true;
}
},
@ -614,5 +623,22 @@ StorageUI.prototype = {
event.stopPropagation();
event.preventDefault();
}
},
/**
* Handles endless scrolling for the table
*/
handleScrollEnd: function() {
if (!this.shouldLoadMoreItems) return;
this.shouldLoadMoreItems = false;
this.itemOffset += 50;
let item = this.tree.selectedItem;
let [type, host, db, objectStore] = item;
let names = null;
if (item.length > 2) {
names = [JSON.stringify(item.slice(2))];
}
this.fetchStorageObjects(type, host, names, 3);
}
};