summaryrefslogtreecommitdiffstats
path: root/base/content/sanitizeDialog.js
diff options
context:
space:
mode:
authorThomas Groman <tgroman@nuegia.net>2020-04-20 20:49:37 -0700
committerThomas Groman <tgroman@nuegia.net>2020-04-20 20:49:37 -0700
commitf9cab004186edb425a9b88ad649726605080a17c (patch)
treee2dae51d3144e83d097a12e7a1499e3ea93f90be /base/content/sanitizeDialog.js
parentf428692de8b59ab89a66502c079e1823dfda8aeb (diff)
downloadwebbrowser-f9cab004186edb425a9b88ad649726605080a17c.tar
webbrowser-f9cab004186edb425a9b88ad649726605080a17c.tar.gz
webbrowser-f9cab004186edb425a9b88ad649726605080a17c.tar.lz
webbrowser-f9cab004186edb425a9b88ad649726605080a17c.tar.xz
webbrowser-f9cab004186edb425a9b88ad649726605080a17c.zip
move browser to webbrowser/
Diffstat (limited to 'base/content/sanitizeDialog.js')
-rw-r--r--base/content/sanitizeDialog.js910
1 files changed, 0 insertions, 910 deletions
diff --git a/base/content/sanitizeDialog.js b/base/content/sanitizeDialog.js
deleted file mode 100644
index 7861132..0000000
--- a/base/content/sanitizeDialog.js
+++ /dev/null
@@ -1,910 +0,0 @@
-/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-var Cc = Components.classes;
-var Ci = Components.interfaces;
-
-var gSanitizePromptDialog = {
-
- get bundleBrowser()
- {
- if (!this._bundleBrowser)
- this._bundleBrowser = document.getElementById("bundleBrowser");
- return this._bundleBrowser;
- },
-
- get selectedTimespan()
- {
- var durList = document.getElementById("sanitizeDurationChoice");
- return parseInt(durList.value);
- },
-
- get sanitizePreferences()
- {
- if (!this._sanitizePreferences) {
- this._sanitizePreferences =
- document.getElementById("sanitizePreferences");
- }
- return this._sanitizePreferences;
- },
-
- get warningBox()
- {
- return document.getElementById("sanitizeEverythingWarningBox");
- },
-
- init: function ()
- {
- // This is used by selectByTimespan() to determine if the window has loaded.
- this._inited = true;
-
- var s = new Sanitizer();
- s.prefDomain = "privacy.cpd.";
-
- let sanitizeItemList = document.querySelectorAll("#itemList > [preference]");
- for (let i = 0; i < sanitizeItemList.length; i++) {
- let prefItem = sanitizeItemList[i];
- let name = s.getNameFromPreference(prefItem.getAttribute("preference"));
- s.canClearItem(name, function canClearCallback(aItem, aCanClear, aPrefItem) {
- if (!aCanClear) {
- aPrefItem.preference = null;
- aPrefItem.checked = false;
- aPrefItem.disabled = true;
- }
- }, prefItem);
- }
-
- document.documentElement.getButton("accept").label =
- this.bundleBrowser.getString("sanitizeButtonOK");
-
- if (this.selectedTimespan === Sanitizer.TIMESPAN_EVERYTHING) {
- this.prepareWarning();
- this.warningBox.hidden = false;
- document.title =
- this.bundleBrowser.getString("sanitizeDialog2.everything.title");
- }
- else
- this.warningBox.hidden = true;
- },
-
- selectByTimespan: function ()
- {
- // This method is the onselect handler for the duration dropdown. As a
- // result it's called a couple of times before onload calls init().
- if (!this._inited)
- return;
-
- var warningBox = this.warningBox;
-
- // If clearing everything
- if (this.selectedTimespan === Sanitizer.TIMESPAN_EVERYTHING) {
- this.prepareWarning();
- if (warningBox.hidden) {
- warningBox.hidden = false;
- window.resizeBy(0, warningBox.boxObject.height);
- }
- window.document.title =
- this.bundleBrowser.getString("sanitizeDialog2.everything.title");
- return;
- }
-
- // If clearing a specific time range
- if (!warningBox.hidden) {
- window.resizeBy(0, -warningBox.boxObject.height);
- warningBox.hidden = true;
- }
- window.document.title =
- window.document.documentElement.getAttribute("noneverythingtitle");
- },
-
- sanitize: function ()
- {
- // Update pref values before handing off to the sanitizer (bug 453440)
- this.updatePrefs();
- var s = new Sanitizer();
- s.prefDomain = "privacy.cpd.";
-
- s.range = Sanitizer.getClearRange(this.selectedTimespan);
- s.ignoreTimespan = !s.range;
-
- // As the sanitize is async, we disable the buttons, update the label on
- // the 'accept' button to indicate things are happening and return false -
- // once the async operation completes (either with or without errors)
- // we close the window.
- let docElt = document.documentElement;
- let acceptButton = docElt.getButton("accept");
- acceptButton.disabled = true;
- acceptButton.setAttribute("label",
- this.bundleBrowser.getString("sanitizeButtonClearing"));
- docElt.getButton("cancel").disabled = true;
- try {
- s.sanitize().then(window.close, window.close);
- } catch (er) {
- Components.utils.reportError("Exception during sanitize: " + er);
- return true; // We *do* want to close immediately on error.
- }
- return false;
- },
-
- /**
- * If the panel that displays a warning when the duration is "Everything" is
- * not set up, sets it up. Otherwise does nothing.
- *
- * @param aDontShowItemList Whether only the warning message should be updated.
- * True means the item list visibility status should not
- * be changed.
- */
- prepareWarning: function (aDontShowItemList) {
- // If the date and time-aware locale warning string is ever used again,
- // initialize it here. Currently we use the no-visits warning string,
- // which does not include date and time. See bug 480169 comment 48.
-
- var warningStringID;
- if (this.hasNonSelectedItems()) {
- warningStringID = "sanitizeSelectedWarning";
- if (!aDontShowItemList)
- this.showItemList();
- }
- else {
- warningStringID = "sanitizeEverythingWarning2";
- }
-
- var warningDesc = document.getElementById("sanitizeEverythingWarning");
- warningDesc.textContent =
- this.bundleBrowser.getString(warningStringID);
- },
-
- /**
- * Called when the value of a preference element is synced from the actual
- * pref. Enables or disables the OK button appropriately.
- */
- onReadGeneric: function ()
- {
- var found = false;
-
- // Find any other pref that's checked and enabled.
- var i = 0;
- while (!found && i < this.sanitizePreferences.childNodes.length) {
- var preference = this.sanitizePreferences.childNodes[i];
-
- found = !!preference.value &&
- !preference.disabled;
- i++;
- }
-
- try {
- document.documentElement.getButton("accept").disabled = !found;
- }
- catch (e) { }
-
- // Update the warning prompt if needed
- this.prepareWarning(true);
-
- return undefined;
- },
-
- /**
- * Sanitizer.prototype.sanitize() requires the prefs to be up-to-date.
- * Because the type of this prefwindow is "child" -- and that's needed because
- * without it the dialog has no OK and Cancel buttons -- the prefs are not
- * updated on dialogaccept on platforms that don't support instant-apply
- * (i.e., Windows). We must therefore manually set the prefs from their
- * corresponding preference elements.
- */
- updatePrefs : function ()
- {
- var tsPref = document.getElementById("privacy.sanitize.timeSpan");
- Sanitizer.prefs.setIntPref("timeSpan", this.selectedTimespan);
-
- // Keep the pref for the download history in sync with the history pref.
- document.getElementById("privacy.cpd.downloads").value =
- document.getElementById("privacy.cpd.history").value;
-
- // Now manually set the prefs from their corresponding preference
- // elements.
- var prefs = this.sanitizePreferences.rootBranch;
- for (let i = 0; i < this.sanitizePreferences.childNodes.length; ++i) {
- var p = this.sanitizePreferences.childNodes[i];
- prefs.setBoolPref(p.name, p.value);
- }
- },
-
- /**
- * Check if all of the history items have been selected like the default status.
- */
- hasNonSelectedItems: function () {
- let checkboxes = document.querySelectorAll("#itemList > [preference]");
- for (let i = 0; i < checkboxes.length; ++i) {
- let pref = document.getElementById(checkboxes[i].getAttribute("preference"));
- if (!pref.value)
- return true;
- }
- return false;
- },
-
- /**
- * Show the history items list.
- */
- showItemList: function () {
- var itemList = document.getElementById("itemList");
- var expanderButton = document.getElementById("detailsExpander");
-
- if (itemList.collapsed) {
- expanderButton.className = "expander-up";
- itemList.setAttribute("collapsed", "false");
- if (document.documentElement.boxObject.height)
- window.resizeBy(0, itemList.boxObject.height);
- }
- },
-
- /**
- * Hide the history items list.
- */
- hideItemList: function () {
- var itemList = document.getElementById("itemList");
- var expanderButton = document.getElementById("detailsExpander");
-
- if (!itemList.collapsed) {
- expanderButton.className = "expander-down";
- window.resizeBy(0, -itemList.boxObject.height);
- itemList.setAttribute("collapsed", "true");
- }
- },
-
- /**
- * Called by the item list expander button to toggle the list's visibility.
- */
- toggleItemList: function ()
- {
- var itemList = document.getElementById("itemList");
-
- if (itemList.collapsed)
- this.showItemList();
- else
- this.hideItemList();
- }
-
-#ifdef CRH_DIALOG_TREE_VIEW
- // A duration value; used in the same context as Sanitizer.TIMESPAN_HOUR,
- // Sanitizer.TIMESPAN_2HOURS, et al. This should match the value attribute
- // of the sanitizeDurationCustom menuitem.
- get TIMESPAN_CUSTOM()
- {
- return -1;
- },
-
- get placesTree()
- {
- if (!this._placesTree)
- this._placesTree = document.getElementById("placesTree");
- return this._placesTree;
- },
-
- init: function ()
- {
- // This is used by selectByTimespan() to determine if the window has loaded.
- this._inited = true;
-
- var s = new Sanitizer();
- s.prefDomain = "privacy.cpd.";
-
- let sanitizeItemList = document.querySelectorAll("#itemList > [preference]");
- for (let i = 0; i < sanitizeItemList.length; i++) {
- let prefItem = sanitizeItemList[i];
- let name = s.getNameFromPreference(prefItem.getAttribute("preference"));
- s.canClearItem(name, function canClearCallback(aCanClear) {
- if (!aCanClear) {
- prefItem.preference = null;
- prefItem.checked = false;
- prefItem.disabled = true;
- }
- });
- }
-
- document.documentElement.getButton("accept").label =
- this.bundleBrowser.getString("sanitizeButtonOK");
-
- this.selectByTimespan();
- },
-
- /**
- * Sets up the hashes this.durationValsToRows, which maps duration values
- * to rows in the tree, this.durationRowsToVals, which maps rows in
- * the tree to duration values, and this.durationStartTimes, which maps
- * duration values to their corresponding start times.
- */
- initDurationDropdown: function ()
- {
- // First, calculate the start times for each duration.
- this.durationStartTimes = {};
- var durVals = [];
- var durPopup = document.getElementById("sanitizeDurationPopup");
- var durMenuitems = durPopup.childNodes;
- for (let i = 0; i < durMenuitems.length; i++) {
- let durMenuitem = durMenuitems[i];
- let durVal = parseInt(durMenuitem.value);
- if (durMenuitem.localName === "menuitem" &&
- durVal !== Sanitizer.TIMESPAN_EVERYTHING &&
- durVal !== this.TIMESPAN_CUSTOM) {
- durVals.push(durVal);
- let durTimes = Sanitizer.getClearRange(durVal);
- this.durationStartTimes[durVal] = durTimes[0];
- }
- }
-
- // Sort the duration values ascending. Because one tree index can map to
- // more than one duration, this ensures that this.durationRowsToVals maps
- // a row index to the largest duration possible in the code below.
- durVals.sort();
-
- // Now calculate the rows in the tree of the durations' start times. For
- // each duration, we are looking for the node in the tree whose time is the
- // smallest time greater than or equal to the duration's start time.
- this.durationRowsToVals = {};
- this.durationValsToRows = {};
- var view = this.placesTree.view;
- // For all rows in the tree except the grippy row...
- for (let i = 0; i < view.rowCount - 1; i++) {
- let unfoundDurVals = [];
- let nodeTime = view.QueryInterface(Ci.nsINavHistoryResultTreeViewer).
- nodeForTreeIndex(i).time;
- // For all durations whose rows have not yet been found in the tree, see
- // if index i is their index. An index may map to more than one duration,
- // in which case the final duration (the largest) wins.
- for (let j = 0; j < durVals.length; j++) {
- let durVal = durVals[j];
- let durStartTime = this.durationStartTimes[durVal];
- if (nodeTime < durStartTime) {
- this.durationValsToRows[durVal] = i - 1;
- this.durationRowsToVals[i - 1] = durVal;
- }
- else
- unfoundDurVals.push(durVal);
- }
- durVals = unfoundDurVals;
- }
-
- // If any durations were not found above, then every node in the tree has a
- // time greater than or equal to the duration. In other words, those
- // durations include the entire tree (except the grippy row).
- for (let i = 0; i < durVals.length; i++) {
- let durVal = durVals[i];
- this.durationValsToRows[durVal] = view.rowCount - 2;
- this.durationRowsToVals[view.rowCount - 2] = durVal;
- }
- },
-
- /**
- * If the Places tree is not set up, sets it up. Otherwise does nothing.
- */
- ensurePlacesTreeIsInited: function ()
- {
- if (this._placesTreeIsInited)
- return;
-
- this._placesTreeIsInited = true;
-
- // Either "Last Four Hours" or "Today" will have the most history. If
- // it's been more than 4 hours since today began, "Today" will. Otherwise
- // "Last Four Hours" will.
- var times = Sanitizer.getClearRange(Sanitizer.TIMESPAN_TODAY);
-
- // If it's been less than 4 hours since today began, use the past 4 hours.
- if (times[1] - times[0] < 14400000000) { // 4*60*60*1000000
- times = Sanitizer.getClearRange(Sanitizer.TIMESPAN_4HOURS);
- }
-
- var histServ = Cc["@mozilla.org/browser/nav-history-service;1"].
- getService(Ci.nsINavHistoryService);
- var query = histServ.getNewQuery();
- query.beginTimeReference = query.TIME_RELATIVE_EPOCH;
- query.beginTime = times[0];
- query.endTimeReference = query.TIME_RELATIVE_EPOCH;
- query.endTime = times[1];
- var opts = histServ.getNewQueryOptions();
- opts.sortingMode = opts.SORT_BY_DATE_DESCENDING;
- opts.queryType = opts.QUERY_TYPE_HISTORY;
- var result = histServ.executeQuery(query, opts);
-
- var view = gContiguousSelectionTreeHelper.setTree(this.placesTree,
- new PlacesTreeView());
- result.addObserver(view, false);
- this.initDurationDropdown();
- },
-
- /**
- * Called on select of the duration dropdown and when grippyMoved() sets a
- * duration based on the location of the grippy row. Selects all the nodes in
- * the tree that are contained in the selected duration. If clearing
- * everything, the warning panel is shown instead.
- */
- selectByTimespan: function ()
- {
- // This method is the onselect handler for the duration dropdown. As a
- // result it's called a couple of times before onload calls init().
- if (!this._inited)
- return;
-
- var durDeck = document.getElementById("durationDeck");
- var durList = document.getElementById("sanitizeDurationChoice");
- var durVal = parseInt(durList.value);
- var durCustom = document.getElementById("sanitizeDurationCustom");
-
- // If grippy row is not at a duration boundary, show the custom menuitem;
- // otherwise, hide it. Since the user cannot specify a custom duration by
- // using the dropdown, this conditional is true only when this method is
- // called onselect from grippyMoved(), so no selection need be made.
- if (durVal === this.TIMESPAN_CUSTOM) {
- durCustom.hidden = false;
- return;
- }
- durCustom.hidden = true;
-
- // If clearing everything, show the warning and change the dialog's title.
- if (durVal === Sanitizer.TIMESPAN_EVERYTHING) {
- this.prepareWarning();
- durDeck.selectedIndex = 1;
- window.document.title =
- this.bundleBrowser.getString("sanitizeDialog2.everything.title");
- document.documentElement.getButton("accept").disabled = false;
- return;
- }
-
- // Otherwise -- if clearing a specific time range -- select that time range
- // in the tree.
- this.ensurePlacesTreeIsInited();
- durDeck.selectedIndex = 0;
- window.document.title =
- window.document.documentElement.getAttribute("noneverythingtitle");
- var durRow = this.durationValsToRows[durVal];
- gContiguousSelectionTreeHelper.rangedSelect(durRow);
- gContiguousSelectionTreeHelper.scrollToGrippy();
-
- // If duration is empty (there are no selected rows), disable the dialog's
- // OK button.
- document.documentElement.getButton("accept").disabled = durRow < 0;
- },
-
- sanitize: function ()
- {
- // Update pref values before handing off to the sanitizer (bug 453440)
- this.updatePrefs();
- var s = new Sanitizer();
- s.prefDomain = "privacy.cpd.";
-
- var durList = document.getElementById("sanitizeDurationChoice");
- var durValue = parseInt(durList.value);
- s.ignoreTimespan = durValue === Sanitizer.TIMESPAN_EVERYTHING;
-
- // Set the sanitizer's time range if we're not clearing everything.
- if (!s.ignoreTimespan) {
- // If user selected a custom timespan, use that.
- if (durValue === this.TIMESPAN_CUSTOM) {
- var view = this.placesTree.view;
- var now = Date.now() * 1000;
- // We disable the dialog's OK button if there's no selection, but we'll
- // handle that case just in... case.
- if (view.selection.getRangeCount() === 0)
- s.range = [now, now];
- else {
- var startIndexRef = {};
- // Tree sorted by visit date DEscending, so start time time comes last.
- view.selection.getRangeAt(0, {}, startIndexRef);
- view.QueryInterface(Ci.nsINavHistoryResultTreeViewer);
- var startNode = view.nodeForTreeIndex(startIndexRef.value);
- s.range = [startNode.time, now];
- }
- }
- // Otherwise use the predetermined range.
- else
- s.range = [this.durationStartTimes[durValue], Date.now() * 1000];
- }
-
- try {
- s.sanitize();
- } catch (er) {
- Components.utils.reportError("Exception during sanitize: " + er);
- }
- return true;
- },
-
- /**
- * In order to mark the custom Places tree view and its nsINavHistoryResult
- * for garbage collection, we need to break the reference cycle between the
- * two.
- */
- unload: function ()
- {
- let result = this.placesTree.getResult();
- result.removeObserver(this.placesTree.view);
- this.placesTree.view = null;
- },
-
- /**
- * Called when the user moves the grippy by dragging it, clicking in the tree,
- * or on keypress. Updates the duration dropdown so that it displays the
- * appropriate specific or custom duration.
- *
- * @param aEventName
- * The name of the event whose handler called this method, e.g.,
- * "ondragstart", "onkeypress", etc.
- * @param aEvent
- * The event captured in the event handler.
- */
- grippyMoved: function (aEventName, aEvent)
- {
- gContiguousSelectionTreeHelper[aEventName](aEvent);
- var lastSelRow = gContiguousSelectionTreeHelper.getGrippyRow() - 1;
- var durList = document.getElementById("sanitizeDurationChoice");
- var durValue = parseInt(durList.value);
-
- // Multiple durations can map to the same row. Don't update the dropdown
- // if the current duration is valid for lastSelRow.
- if ((durValue !== this.TIMESPAN_CUSTOM ||
- lastSelRow in this.durationRowsToVals) &&
- (durValue === this.TIMESPAN_CUSTOM ||
- this.durationValsToRows[durValue] !== lastSelRow)) {
- // Setting durList.value causes its onselect handler to fire, which calls
- // selectByTimespan().
- if (lastSelRow in this.durationRowsToVals)
- durList.value = this.durationRowsToVals[lastSelRow];
- else
- durList.value = this.TIMESPAN_CUSTOM;
- }
-
- // If there are no selected rows, disable the dialog's OK button.
- document.documentElement.getButton("accept").disabled = lastSelRow < 0;
- }
-#endif
-
-};
-
-
-#ifdef CRH_DIALOG_TREE_VIEW
-/**
- * A helper for handling contiguous selection in the tree.
- */
-var gContiguousSelectionTreeHelper = {
-
- /**
- * Gets the tree associated with this helper.
- */
- get tree()
- {
- return this._tree;
- },
-
- /**
- * Sets the tree that this module handles. The tree is assigned a new view
- * that is equipped to handle contiguous selection. You can pass in an
- * object that will be used as the prototype of the new view. Otherwise
- * the tree's current view is used as the prototype.
- *
- * @param aTreeElement
- * The tree element
- * @param aProtoTreeView
- * If defined, this will be used as the prototype of the tree's new
- * view
- * @return The new view
- */
- setTree: function CSTH_setTree(aTreeElement, aProtoTreeView)
- {
- this._tree = aTreeElement;
- var newView = this._makeTreeView(aProtoTreeView || aTreeElement.view);
- aTreeElement.view = newView;
- return newView;
- },
-
- /**
- * The index of the row that the grippy occupies. Note that the index of the
- * last selected row is getGrippyRow() - 1. If getGrippyRow() is 0, then
- * no selection exists.
- *
- * @return The row index of the grippy
- */
- getGrippyRow: function CSTH_getGrippyRow()
- {
- var sel = this.tree.view.selection;
- var rangeCount = sel.getRangeCount();
- if (rangeCount === 0)
- return 0;
- if (rangeCount !== 1) {
- throw "contiguous selection tree helper: getGrippyRow called with " +
- "multiple selection ranges";
- }
- var max = {};
- sel.getRangeAt(0, {}, max);
- return max.value + 1;
- },
-
- /**
- * Helper function for the dragover event. Your dragover listener should
- * call this. It updates the selection in the tree under the mouse.
- *
- * @param aEvent
- * The observed dragover event
- */
- ondragover: function CSTH_ondragover(aEvent)
- {
- // Without this when dragging on Windows the mouse cursor is a "no" sign.
- // This makes it a drop symbol.
- var ds = Cc["@mozilla.org/widget/dragservice;1"].
- getService(Ci.nsIDragService).
- getCurrentSession();
- ds.canDrop = true;
- ds.dragAction = 0;
-
- var tbo = this.tree.treeBoxObject;
- aEvent.QueryInterface(Ci.nsIDOMMouseEvent);
- var hoverRow = tbo.getRowAt(aEvent.clientX, aEvent.clientY);
-
- if (hoverRow < 0)
- return;
-
- this.rangedSelect(hoverRow - 1);
- },
-
- /**
- * Helper function for the dragstart event. Your dragstart listener should
- * call this. It starts a drag session.
- *
- * @param aEvent
- * The observed dragstart event
- */
- ondragstart: function CSTH_ondragstart(aEvent)
- {
- var tbo = this.tree.treeBoxObject;
- var clickedRow = tbo.getRowAt(aEvent.clientX, aEvent.clientY);
-
- if (clickedRow !== this.getGrippyRow())
- return;
-
- // This part is a hack. What we really want is a grab and slide, not
- // drag and drop. Start a move drag session with dummy data and a
- // dummy region. Set the region's coordinates to (Infinity, Infinity)
- // so it's drawn offscreen and its size to (1, 1).
- var arr = Cc["@mozilla.org/supports-array;1"].
- createInstance(Ci.nsISupportsArray);
- var trans = Cc["@mozilla.org/widget/transferable;1"].
- createInstance(Ci.nsITransferable);
- trans.init(null);
- trans.setTransferData('dummy-flavor', null, 0);
- arr.AppendElement(trans);
- var reg = Cc["@mozilla.org/gfx/region;1"].
- createInstance(Ci.nsIScriptableRegion);
- reg.setToRect(Infinity, Infinity, 1, 1);
- var ds = Cc["@mozilla.org/widget/dragservice;1"].
- getService(Ci.nsIDragService);
- ds.invokeDragSession(aEvent.target, arr, reg, ds.DRAGDROP_ACTION_MOVE);
- },
-
- /**
- * Helper function for the keypress event. Your keypress listener should
- * call this. Users can use Up, Down, Page Up/Down, Home, and End to move
- * the bottom of the selection window.
- *
- * @param aEvent
- * The observed keypress event
- */
- onkeypress: function CSTH_onkeypress(aEvent)
- {
- var grippyRow = this.getGrippyRow();
- var tbo = this.tree.treeBoxObject;
- var rangeEnd;
- switch (aEvent.keyCode) {
- case aEvent.DOM_VK_HOME:
- rangeEnd = 0;
- break;
- case aEvent.DOM_VK_PAGE_UP:
- rangeEnd = grippyRow - tbo.getPageLength();
- break;
- case aEvent.DOM_VK_UP:
- rangeEnd = grippyRow - 2;
- break;
- case aEvent.DOM_VK_DOWN:
- rangeEnd = grippyRow;
- break;
- case aEvent.DOM_VK_PAGE_DOWN:
- rangeEnd = grippyRow + tbo.getPageLength();
- break;
- case aEvent.DOM_VK_END:
- rangeEnd = this.tree.view.rowCount - 2;
- break;
- default:
- return;
- break;
- }
-
- aEvent.stopPropagation();
-
- // First, clip rangeEnd. this.rangedSelect() doesn't clip the range if we
- // select past the ends of the tree.
- if (rangeEnd < 0)
- rangeEnd = -1;
- else if (this.tree.view.rowCount - 2 < rangeEnd)
- rangeEnd = this.tree.view.rowCount - 2;
-
- // Next, (de)select.
- this.rangedSelect(rangeEnd);
-
- // Finally, scroll the tree. We always want one row above and below the
- // grippy row to be visible if possible.
- if (rangeEnd < grippyRow) // moved up
- tbo.ensureRowIsVisible(rangeEnd < 0 ? 0 : rangeEnd);
- else { // moved down
- if (rangeEnd + 2 < this.tree.view.rowCount)
- tbo.ensureRowIsVisible(rangeEnd + 2);
- else if (rangeEnd + 1 < this.tree.view.rowCount)
- tbo.ensureRowIsVisible(rangeEnd + 1);
- }
- },
-
- /**
- * Helper function for the mousedown event. Your mousedown listener should
- * call this. Users can click on individual rows to make the selection
- * jump to them immediately.
- *
- * @param aEvent
- * The observed mousedown event
- */
- onmousedown: function CSTH_onmousedown(aEvent)
- {
- var tbo = this.tree.treeBoxObject;
- var clickedRow = tbo.getRowAt(aEvent.clientX, aEvent.clientY);
-
- if (clickedRow < 0 || clickedRow >= this.tree.view.rowCount)
- return;
-
- if (clickedRow < this.getGrippyRow())
- this.rangedSelect(clickedRow);
- else if (clickedRow > this.getGrippyRow())
- this.rangedSelect(clickedRow - 1);
- },
-
- /**
- * Selects range [0, aEndRow] in the tree. The grippy row will then be at
- * index aEndRow + 1. aEndRow may be -1, in which case the selection is
- * cleared and the grippy row will be at index 0.
- *
- * @param aEndRow
- * The range [0, aEndRow] will be selected.
- */
- rangedSelect: function CSTH_rangedSelect(aEndRow)
- {
- var tbo = this.tree.treeBoxObject;
- if (aEndRow < 0)
- this.tree.view.selection.clearSelection();
- else
- this.tree.view.selection.rangedSelect(0, aEndRow, false);
- tbo.invalidateRange(tbo.getFirstVisibleRow(), tbo.getLastVisibleRow());
- },
-
- /**
- * Scrolls the tree so that the grippy row is in the center of the view.
- */
- scrollToGrippy: function CSTH_scrollToGrippy()
- {
- var rowCount = this.tree.view.rowCount;
- var tbo = this.tree.treeBoxObject;
- var pageLen = tbo.getPageLength() ||
- parseInt(this.tree.getAttribute("rows")) ||
- 10;
-
- // All rows fit on a single page.
- if (rowCount <= pageLen)
- return;
-
- var scrollToRow = this.getGrippyRow() - Math.ceil(pageLen / 2.0);
-
- // Grippy row is in first half of first page.
- if (scrollToRow < 0)
- scrollToRow = 0;
-
- // Grippy row is in last half of last page.
- else if (rowCount < scrollToRow + pageLen)
- scrollToRow = rowCount - pageLen;
-
- tbo.scrollToRow(scrollToRow);
- },
-
- /**
- * Creates a new tree view suitable for contiguous selection. If
- * aProtoTreeView is specified, it's used as the new view's prototype.
- * Otherwise the tree's current view is used as the prototype.
- *
- * @param aProtoTreeView
- * Used as the new view's prototype if specified
- */
- _makeTreeView: function CSTH__makeTreeView(aProtoTreeView)
- {
- var view = aProtoTreeView;
- var that = this;
-
- //XXXadw: When Alex gets the grippy icon done, this may or may not change,
- // depending on how we style it.
- view.isSeparator = function CSTH_View_isSeparator(aRow)
- {
- return aRow === that.getGrippyRow();
- };
-
- // rowCount includes the grippy row.
- view.__defineGetter__("_rowCount", view.__lookupGetter__("rowCount"));
- view.__defineGetter__("rowCount",
- function CSTH_View_rowCount()
- {
- return this._rowCount + 1;
- });
-
- // This has to do with visual feedback in the view itself, e.g., drawing
- // a small line underneath the dropzone. Not what we want.
- view.canDrop = function CSTH_View_canDrop() { return false; };
-
- // No clicking headers to sort the tree or sort feedback on columns.
- view.cycleHeader = function CSTH_View_cycleHeader() {};
- view.sortingChanged = function CSTH_View_sortingChanged() {};
-
- // Override a bunch of methods to account for the grippy row.
-
- view._getCellProperties = view.getCellProperties;
- view.getCellProperties =
- function CSTH_View_getCellProperties(aRow, aCol)
- {
- var grippyRow = that.getGrippyRow();
- if (aRow === grippyRow)
- return "grippyRow";
- if (aRow < grippyRow)
- return this._getCellProperties(aRow, aCol);
-
- return this._getCellProperties(aRow - 1, aCol);
- };
-
- view._getRowProperties = view.getRowProperties;
- view.getRowProperties =
- function CSTH_View_getRowProperties(aRow)
- {
- var grippyRow = that.getGrippyRow();
- if (aRow === grippyRow)
- return "grippyRow";
-
- if (aRow < grippyRow)
- return this._getRowProperties(aRow);
-
- return this._getRowProperties(aRow - 1);
- };
-
- view._getCellText = view.getCellText;
- view.getCellText =
- function CSTH_View_getCellText(aRow, aCol)
- {
- var grippyRow = that.getGrippyRow();
- if (aRow === grippyRow)
- return "";
- aRow = aRow < grippyRow ? aRow : aRow - 1;
- return this._getCellText(aRow, aCol);
- };
-
- view._getImageSrc = view.getImageSrc;
- view.getImageSrc =
- function CSTH_View_getImageSrc(aRow, aCol)
- {
- var grippyRow = that.getGrippyRow();
- if (aRow === grippyRow)
- return "";
- aRow = aRow < grippyRow ? aRow : aRow - 1;
- return this._getImageSrc(aRow, aCol);
- };
-
- view.isContainer = function CSTH_View_isContainer(aRow) { return false; };
- view.getParentIndex = function CSTH_View_getParentIndex(aRow) { return -1; };
- view.getLevel = function CSTH_View_getLevel(aRow) { return 0; };
- view.hasNextSibling = function CSTH_View_hasNextSibling(aRow, aAfterIndex)
- {
- return aRow < this.rowCount - 1;
- };
-
- return view;
- }
-};
-#endif