зеркало из https://github.com/mozilla/gecko-dev.git
688 строки
22 KiB
JavaScript
688 строки
22 KiB
JavaScript
/* 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/. */
|
|
|
|
/* import-globals-from extensionControlled.js */
|
|
/* import-globals-from preferences.js */
|
|
|
|
ChromeUtils.defineModuleGetter(this, "PlacesUtils",
|
|
"resource://gre/modules/PlacesUtils.jsm");
|
|
ChromeUtils.defineModuleGetter(this, "ExtensionSettingsStore",
|
|
"resource://gre/modules/ExtensionSettingsStore.jsm");
|
|
|
|
Preferences.addAll([
|
|
{ id: "browser.search.suggest.enabled", type: "bool" },
|
|
{ id: "browser.urlbar.suggest.searches", type: "bool" },
|
|
{ id: "browser.search.hiddenOneOffs", type: "unichar" },
|
|
{ id: "browser.search.widget.inNavBar", type: "bool" },
|
|
{ id: "browser.urlbar.matchBuckets", type: "string" },
|
|
]);
|
|
|
|
const ENGINE_FLAVOR = "text/x-moz-search-engine";
|
|
const SEARCH_TYPE = "default_search";
|
|
const SEARCH_KEY = "defaultSearch";
|
|
|
|
var gEngineView = null;
|
|
|
|
var gSearchPane = {
|
|
|
|
/**
|
|
* Initialize autocomplete to ensure prefs are in sync.
|
|
*/
|
|
_initAutocomplete() {
|
|
Cc["@mozilla.org/autocomplete/search;1?name=unifiedcomplete"]
|
|
.getService(Ci.mozIPlacesAutoComplete);
|
|
},
|
|
|
|
init() {
|
|
gEngineView = new EngineView(new EngineStore());
|
|
document.getElementById("engineList").view = gEngineView;
|
|
this.buildDefaultEngineDropDown();
|
|
|
|
if (Services.policies &&
|
|
!Services.policies.isAllowed("installSearchEngine")) {
|
|
document.getElementById("addEnginesBox").hidden = true;
|
|
} else {
|
|
let addEnginesLink = document.getElementById("addEngines");
|
|
let searchEnginesURL = Services.wm.getMostRecentWindow("navigator:browser")
|
|
.BrowserSearch.searchEnginesURL;
|
|
addEnginesLink.setAttribute("href", searchEnginesURL);
|
|
}
|
|
|
|
window.addEventListener("click", this);
|
|
window.addEventListener("command", this);
|
|
window.addEventListener("dragstart", this);
|
|
window.addEventListener("keypress", this);
|
|
window.addEventListener("select", this);
|
|
window.addEventListener("blur", this, true);
|
|
|
|
Services.obs.addObserver(this, "browser-search-engine-modified");
|
|
window.addEventListener("unload", () => {
|
|
Services.obs.removeObserver(this, "browser-search-engine-modified");
|
|
});
|
|
|
|
this._initAutocomplete();
|
|
|
|
let suggestsPref = Preferences.get("browser.search.suggest.enabled");
|
|
let urlbarSuggestsPref = Preferences.get("browser.urlbar.suggest.searches");
|
|
let updateSuggestionCheckboxes = this._updateSuggestionCheckboxes.bind(this);
|
|
suggestsPref.on("change", updateSuggestionCheckboxes);
|
|
urlbarSuggestsPref.on("change", updateSuggestionCheckboxes);
|
|
let urlbarSuggests = document.getElementById("urlBarSuggestion");
|
|
urlbarSuggests.addEventListener("command", () => {
|
|
urlbarSuggestsPref.value = urlbarSuggests.checked;
|
|
});
|
|
|
|
this._initShowSearchSuggestionsFirst();
|
|
this._updateSuggestionCheckboxes();
|
|
},
|
|
|
|
_initShowSearchSuggestionsFirst() {
|
|
this._urlbarSuggestionsPosPref = Preferences.get("browser.urlbar.matchBuckets");
|
|
let checkbox =
|
|
document.getElementById("showSearchSuggestionsFirstCheckbox");
|
|
|
|
this._urlbarSuggestionsPosPref.on("change", () => {
|
|
this._syncFromShowSearchSuggestionsFirstPref(checkbox);
|
|
});
|
|
this._syncFromShowSearchSuggestionsFirstPref(checkbox);
|
|
|
|
checkbox.addEventListener("command", () => {
|
|
this._syncToShowSearchSuggestionsFirstPref(checkbox.checked);
|
|
});
|
|
},
|
|
|
|
_syncFromShowSearchSuggestionsFirstPref(checkbox) {
|
|
if (!this._urlbarSuggestionsPosPref.value) {
|
|
// The pref is cleared, meaning search suggestions are shown first.
|
|
checkbox.checked = true;
|
|
return;
|
|
}
|
|
// The pref has a value. If the first bucket in the pref is search
|
|
// suggestions, then check the checkbox.
|
|
let buckets = PlacesUtils.convertMatchBucketsStringToArray(this._urlbarSuggestionsPosPref.value);
|
|
checkbox.checked = buckets[0] && buckets[0][0] == "suggestion";
|
|
},
|
|
|
|
_syncToShowSearchSuggestionsFirstPref(checked) {
|
|
if (checked) {
|
|
// Show search suggestions first, so clear the pref since that's the
|
|
// default.
|
|
this._urlbarSuggestionsPosPref.reset();
|
|
return;
|
|
}
|
|
// Show history first.
|
|
this._urlbarSuggestionsPosPref.value = "general:5,suggestion:Infinity";
|
|
},
|
|
|
|
_updateSuggestionCheckboxes() {
|
|
let suggestsPref = Preferences.get("browser.search.suggest.enabled");
|
|
let permanentPB =
|
|
Services.prefs.getBoolPref("browser.privatebrowsing.autostart");
|
|
let urlbarSuggests = document.getElementById("urlBarSuggestion");
|
|
let positionCheckbox =
|
|
document.getElementById("showSearchSuggestionsFirstCheckbox");
|
|
|
|
urlbarSuggests.disabled = !suggestsPref.value || permanentPB;
|
|
|
|
let urlbarSuggestsPref = Preferences.get("browser.urlbar.suggest.searches");
|
|
urlbarSuggests.checked = urlbarSuggestsPref.value;
|
|
if (urlbarSuggests.disabled) {
|
|
urlbarSuggests.checked = false;
|
|
}
|
|
|
|
if (urlbarSuggests.checked) {
|
|
positionCheckbox.disabled = false;
|
|
this._syncFromShowSearchSuggestionsFirstPref(positionCheckbox);
|
|
} else {
|
|
positionCheckbox.disabled = true;
|
|
positionCheckbox.checked = false;
|
|
}
|
|
|
|
let permanentPBLabel =
|
|
document.getElementById("urlBarSuggestionPermanentPBLabel");
|
|
permanentPBLabel.hidden = urlbarSuggests.hidden || !permanentPB;
|
|
},
|
|
|
|
buildDefaultEngineDropDown() {
|
|
// This is called each time something affects the list of engines.
|
|
let list = document.getElementById("defaultEngine");
|
|
// Set selection to the current default engine.
|
|
let currentEngine = Services.search.defaultEngine.name;
|
|
|
|
// If the current engine isn't in the list any more, select the first item.
|
|
let engines = gEngineView._engineStore._engines;
|
|
if (!engines.some(e => e.name == currentEngine))
|
|
currentEngine = engines[0].name;
|
|
|
|
// Now clean-up and rebuild the list.
|
|
list.removeAllItems();
|
|
gEngineView._engineStore._engines.forEach(e => {
|
|
let item = list.appendItem(e.name);
|
|
item.setAttribute("class", "menuitem-iconic searchengine-menuitem menuitem-with-favicon");
|
|
if (e.iconURI) {
|
|
item.setAttribute("image", e.iconURI.spec);
|
|
}
|
|
item.engine = e;
|
|
if (e.name == currentEngine)
|
|
list.selectedItem = item;
|
|
});
|
|
|
|
handleControllingExtension(SEARCH_TYPE, SEARCH_KEY);
|
|
let searchEngineListener = {
|
|
observe(subject, topic, data) {
|
|
handleControllingExtension(SEARCH_TYPE, SEARCH_KEY);
|
|
},
|
|
};
|
|
Services.obs.addObserver(searchEngineListener, "browser-search-engine-modified");
|
|
window.addEventListener("unload", () => {
|
|
Services.obs.removeObserver(searchEngineListener, "browser-search-engine-modified");
|
|
});
|
|
},
|
|
|
|
handleEvent(aEvent) {
|
|
switch (aEvent.type) {
|
|
case "click":
|
|
if (aEvent.target.id != "engineChildren" &&
|
|
!aEvent.target.classList.contains("searchEngineAction")) {
|
|
let engineList = document.getElementById("engineList");
|
|
// We don't want to toggle off selection while editing keyword
|
|
// so proceed only when the input field is hidden.
|
|
// We need to check that engineList.view is defined here
|
|
// because the "click" event listener is on <window> and the
|
|
// view might have been destroyed if the pane has been navigated
|
|
// away from.
|
|
if (engineList.inputField.hidden && engineList.view) {
|
|
let selection = engineList.view.selection;
|
|
if (selection.count > 0) {
|
|
selection.toggleSelect(selection.currentIndex);
|
|
}
|
|
engineList.blur();
|
|
}
|
|
}
|
|
break;
|
|
case "command":
|
|
switch (aEvent.target.id) {
|
|
case "":
|
|
if (aEvent.target.parentNode &&
|
|
aEvent.target.parentNode.parentNode &&
|
|
aEvent.target.parentNode.parentNode.id == "defaultEngine") {
|
|
gSearchPane.setDefaultEngine();
|
|
}
|
|
break;
|
|
case "restoreDefaultSearchEngines":
|
|
gSearchPane.onRestoreDefaults();
|
|
break;
|
|
case "removeEngineButton":
|
|
Services.search.removeEngine(gEngineView.selectedEngine.originalEngine);
|
|
break;
|
|
}
|
|
break;
|
|
case "dragstart":
|
|
if (aEvent.target.id == "engineChildren") {
|
|
onDragEngineStart(aEvent);
|
|
}
|
|
break;
|
|
case "keypress":
|
|
if (aEvent.target.id == "engineList") {
|
|
gSearchPane.onTreeKeyPress(aEvent);
|
|
}
|
|
break;
|
|
case "select":
|
|
if (aEvent.target.id == "engineList") {
|
|
gSearchPane.onTreeSelect();
|
|
}
|
|
break;
|
|
case "blur":
|
|
if (aEvent.target.id == "engineList" &&
|
|
aEvent.target.inputField == document.getBindingParent(aEvent.originalTarget)) {
|
|
gSearchPane.onInputBlur();
|
|
}
|
|
break;
|
|
}
|
|
},
|
|
|
|
observe(aEngine, aTopic, aVerb) {
|
|
if (aTopic == "browser-search-engine-modified") {
|
|
aEngine.QueryInterface(Ci.nsISearchEngine);
|
|
switch (aVerb) {
|
|
case "engine-added":
|
|
gEngineView._engineStore.addEngine(aEngine);
|
|
gEngineView.rowCountChanged(gEngineView.lastIndex, 1);
|
|
gSearchPane.buildDefaultEngineDropDown();
|
|
break;
|
|
case "engine-changed":
|
|
gEngineView._engineStore.reloadIcons();
|
|
gEngineView.invalidate();
|
|
break;
|
|
case "engine-removed":
|
|
gSearchPane.remove(aEngine);
|
|
break;
|
|
case "engine-current":
|
|
// If the user is going through the drop down using up/down keys, the
|
|
// dropdown may still be open (eg. on Windows) when engine-current is
|
|
// fired, so rebuilding the list unconditionally would get in the way.
|
|
let selectedEngine =
|
|
document.getElementById("defaultEngine").selectedItem.engine;
|
|
if (selectedEngine.name != aEngine.name)
|
|
gSearchPane.buildDefaultEngineDropDown();
|
|
break;
|
|
case "engine-default":
|
|
// Not relevant
|
|
break;
|
|
}
|
|
}
|
|
},
|
|
|
|
onInputBlur(aEvent) {
|
|
let tree = document.getElementById("engineList");
|
|
if (!tree.hasAttribute("editing"))
|
|
return;
|
|
|
|
// Accept input unless discarded.
|
|
let accept = aEvent.charCode != KeyEvent.DOM_VK_ESCAPE;
|
|
tree.stopEditing(accept);
|
|
},
|
|
|
|
onTreeSelect() {
|
|
document.getElementById("removeEngineButton").disabled =
|
|
!gEngineView.isEngineSelectedAndRemovable();
|
|
},
|
|
|
|
onTreeKeyPress(aEvent) {
|
|
let index = gEngineView.selectedIndex;
|
|
let tree = document.getElementById("engineList");
|
|
if (tree.hasAttribute("editing"))
|
|
return;
|
|
|
|
if (aEvent.charCode == KeyEvent.DOM_VK_SPACE) {
|
|
// Space toggles the checkbox.
|
|
let newValue = !gEngineView._engineStore.engines[index].shown;
|
|
gEngineView.setCellValue(index, tree.columns.getFirstColumn(),
|
|
newValue.toString());
|
|
// Prevent page from scrolling on the space key.
|
|
aEvent.preventDefault();
|
|
} else {
|
|
let isMac = Services.appinfo.OS == "Darwin";
|
|
if ((isMac && aEvent.keyCode == KeyEvent.DOM_VK_RETURN) ||
|
|
(!isMac && aEvent.keyCode == KeyEvent.DOM_VK_F2)) {
|
|
tree.startEditing(index, tree.columns.getLastColumn());
|
|
} else if (aEvent.keyCode == KeyEvent.DOM_VK_DELETE ||
|
|
(isMac && aEvent.shiftKey &&
|
|
aEvent.keyCode == KeyEvent.DOM_VK_BACK_SPACE &&
|
|
gEngineView.isEngineSelectedAndRemovable())) {
|
|
// Delete and Shift+Backspace (Mac) removes selected engine.
|
|
Services.search.removeEngine(gEngineView.selectedEngine.originalEngine);
|
|
}
|
|
}
|
|
},
|
|
|
|
onRestoreDefaults() {
|
|
let num = gEngineView._engineStore.restoreDefaultEngines();
|
|
gEngineView.rowCountChanged(0, num);
|
|
gEngineView.invalidate();
|
|
},
|
|
|
|
showRestoreDefaults(aEnable) {
|
|
document.getElementById("restoreDefaultSearchEngines").disabled = !aEnable;
|
|
},
|
|
|
|
remove(aEngine) {
|
|
let index = gEngineView._engineStore.removeEngine(aEngine);
|
|
gEngineView.rowCountChanged(index, -1);
|
|
gEngineView.invalidate();
|
|
gEngineView.selection.select(Math.min(index, gEngineView.lastIndex));
|
|
gEngineView.ensureRowIsVisible(gEngineView.currentIndex);
|
|
document.getElementById("engineList").focus();
|
|
},
|
|
|
|
async editKeyword(aEngine, aNewKeyword) {
|
|
let keyword = aNewKeyword.trim();
|
|
if (keyword) {
|
|
let eduplicate = false;
|
|
let dupName = "";
|
|
|
|
// Check for duplicates in Places keywords.
|
|
let bduplicate = !!(await PlacesUtils.keywords.fetch(keyword));
|
|
|
|
// Check for duplicates in changes we haven't committed yet
|
|
let engines = gEngineView._engineStore.engines;
|
|
let lc_keyword = keyword.toLocaleLowerCase();
|
|
for (let engine of engines) {
|
|
if (engine.alias &&
|
|
engine.alias.toLocaleLowerCase() == lc_keyword &&
|
|
engine.name != aEngine.name) {
|
|
eduplicate = true;
|
|
dupName = engine.name;
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Notify the user if they have chosen an existing engine/bookmark keyword
|
|
if (eduplicate || bduplicate) {
|
|
let msgids = [{id: "search-keyword-warning-title"}];
|
|
if (eduplicate) {
|
|
msgids.push({id: "search-keyword-warning-engine", args: { name: dupName }});
|
|
} else {
|
|
msgids.push({id: "search-keyword-warning-bookmark"});
|
|
}
|
|
|
|
let [dtitle, msg] = await document.l10n.formatValues(msgids);
|
|
|
|
Services.prompt.alert(window, dtitle, msg);
|
|
return false;
|
|
}
|
|
}
|
|
|
|
gEngineView._engineStore.changeEngine(aEngine, "alias", keyword);
|
|
gEngineView.invalidate();
|
|
return true;
|
|
},
|
|
|
|
saveOneClickEnginesList() {
|
|
let hiddenList = [];
|
|
for (let engine of gEngineView._engineStore.engines) {
|
|
if (!engine.shown)
|
|
hiddenList.push(engine.name);
|
|
}
|
|
Preferences.get("browser.search.hiddenOneOffs").value =
|
|
hiddenList.join(",");
|
|
},
|
|
|
|
setDefaultEngine() {
|
|
Services.search.defaultEngine =
|
|
document.getElementById("defaultEngine").selectedItem.engine;
|
|
ExtensionSettingsStore.setByUser(SEARCH_TYPE, SEARCH_KEY);
|
|
},
|
|
};
|
|
|
|
function onDragEngineStart(event) {
|
|
var selectedIndex = gEngineView.selectedIndex;
|
|
var tree = document.getElementById("engineList");
|
|
let cell = tree.getCellAt(event.clientX, event.clientY);
|
|
if (selectedIndex >= 0 && !gEngineView.isCheckBox(cell.row, cell.col)) {
|
|
event.dataTransfer.setData(ENGINE_FLAVOR, selectedIndex.toString());
|
|
event.dataTransfer.effectAllowed = "move";
|
|
}
|
|
}
|
|
|
|
|
|
function EngineStore() {
|
|
let pref = Preferences.get("browser.search.hiddenOneOffs").value;
|
|
this.hiddenList = pref ? pref.split(",") : [];
|
|
|
|
this._engines = Services.search.getVisibleEngines().map(this._cloneEngine, this);
|
|
this._defaultEngines = Services.search.getDefaultEngines().map(this._cloneEngine, this);
|
|
|
|
// check if we need to disable the restore defaults button
|
|
var someHidden = this._defaultEngines.some(e => e.hidden);
|
|
gSearchPane.showRestoreDefaults(someHidden);
|
|
}
|
|
EngineStore.prototype = {
|
|
_engines: null,
|
|
_defaultEngines: null,
|
|
|
|
get engines() {
|
|
return this._engines;
|
|
},
|
|
set engines(val) {
|
|
this._engines = val;
|
|
return val;
|
|
},
|
|
|
|
_getIndexForEngine(aEngine) {
|
|
return this._engines.indexOf(aEngine);
|
|
},
|
|
|
|
_getEngineByName(aName) {
|
|
return this._engines.find(engine => engine.name == aName);
|
|
},
|
|
|
|
_cloneEngine(aEngine) {
|
|
var clonedObj = {};
|
|
for (var i in aEngine)
|
|
clonedObj[i] = aEngine[i];
|
|
clonedObj.originalEngine = aEngine;
|
|
clonedObj.shown = !this.hiddenList.includes(clonedObj.name);
|
|
return clonedObj;
|
|
},
|
|
|
|
// Callback for Array's some(). A thisObj must be passed to some()
|
|
_isSameEngine(aEngineClone) {
|
|
return aEngineClone.originalEngine == this.originalEngine;
|
|
},
|
|
|
|
addEngine(aEngine) {
|
|
this._engines.push(this._cloneEngine(aEngine));
|
|
},
|
|
|
|
moveEngine(aEngine, aNewIndex) {
|
|
if (aNewIndex < 0 || aNewIndex > this._engines.length - 1)
|
|
throw new Error("ES_moveEngine: invalid aNewIndex!");
|
|
var index = this._getIndexForEngine(aEngine);
|
|
if (index == -1)
|
|
throw new Error("ES_moveEngine: invalid engine?");
|
|
|
|
if (index == aNewIndex)
|
|
return; // nothing to do
|
|
|
|
// Move the engine in our internal store
|
|
var removedEngine = this._engines.splice(index, 1)[0];
|
|
this._engines.splice(aNewIndex, 0, removedEngine);
|
|
|
|
Services.search.moveEngine(aEngine.originalEngine, aNewIndex);
|
|
},
|
|
|
|
removeEngine(aEngine) {
|
|
if (this._engines.length == 1) {
|
|
throw new Error("Cannot remove last engine!");
|
|
}
|
|
|
|
let engineName = aEngine.name;
|
|
let index = this._engines.findIndex(element => element.name == engineName);
|
|
|
|
if (index == -1)
|
|
throw new Error("invalid engine?");
|
|
|
|
let removedEngine = this._engines.splice(index, 1)[0];
|
|
|
|
if (this._defaultEngines.some(this._isSameEngine, removedEngine))
|
|
gSearchPane.showRestoreDefaults(true);
|
|
gSearchPane.buildDefaultEngineDropDown();
|
|
return index;
|
|
},
|
|
|
|
restoreDefaultEngines() {
|
|
var added = 0;
|
|
|
|
for (var i = 0; i < this._defaultEngines.length; ++i) {
|
|
var e = this._defaultEngines[i];
|
|
|
|
// If the engine is already in the list, just move it.
|
|
if (this._engines.some(this._isSameEngine, e)) {
|
|
this.moveEngine(this._getEngineByName(e.name), i);
|
|
} else {
|
|
// Otherwise, add it back to our internal store
|
|
|
|
// The search service removes the alias when an engine is hidden,
|
|
// so clear any alias we may have cached before unhiding the engine.
|
|
e.alias = "";
|
|
|
|
this._engines.splice(i, 0, e);
|
|
let engine = e.originalEngine;
|
|
engine.hidden = false;
|
|
Services.search.moveEngine(engine, i);
|
|
added++;
|
|
}
|
|
}
|
|
Services.search.resetToOriginalDefaultEngine();
|
|
gSearchPane.showRestoreDefaults(false);
|
|
gSearchPane.buildDefaultEngineDropDown();
|
|
return added;
|
|
},
|
|
|
|
changeEngine(aEngine, aProp, aNewValue) {
|
|
var index = this._getIndexForEngine(aEngine);
|
|
if (index == -1)
|
|
throw new Error("invalid engine?");
|
|
|
|
this._engines[index][aProp] = aNewValue;
|
|
aEngine.originalEngine[aProp] = aNewValue;
|
|
},
|
|
|
|
reloadIcons() {
|
|
this._engines.forEach(function(e) {
|
|
e.uri = e.originalEngine.uri;
|
|
});
|
|
},
|
|
};
|
|
|
|
function EngineView(aEngineStore) {
|
|
this._engineStore = aEngineStore;
|
|
}
|
|
EngineView.prototype = {
|
|
_engineStore: null,
|
|
tree: null,
|
|
|
|
get lastIndex() {
|
|
return this.rowCount - 1;
|
|
},
|
|
get selectedIndex() {
|
|
var seln = this.selection;
|
|
if (seln.getRangeCount() > 0) {
|
|
var min = {};
|
|
seln.getRangeAt(0, min, {});
|
|
return min.value;
|
|
}
|
|
return -1;
|
|
},
|
|
get selectedEngine() {
|
|
return this._engineStore.engines[this.selectedIndex];
|
|
},
|
|
|
|
// Helpers
|
|
rowCountChanged(index, count) {
|
|
this.tree.rowCountChanged(index, count);
|
|
},
|
|
|
|
invalidate() {
|
|
this.tree.invalidate();
|
|
},
|
|
|
|
ensureRowIsVisible(index) {
|
|
this.tree.ensureRowIsVisible(index);
|
|
},
|
|
|
|
getSourceIndexFromDrag(dataTransfer) {
|
|
return parseInt(dataTransfer.getData(ENGINE_FLAVOR));
|
|
},
|
|
|
|
isCheckBox(index, column) {
|
|
return column.id == "engineShown";
|
|
},
|
|
|
|
isEngineSelectedAndRemovable() {
|
|
return this.selectedIndex != -1 && this.lastIndex != 0;
|
|
},
|
|
|
|
// nsITreeView
|
|
get rowCount() {
|
|
return this._engineStore.engines.length;
|
|
},
|
|
|
|
getImageSrc(index, column) {
|
|
if (column.id == "engineName") {
|
|
if (this._engineStore.engines[index].iconURI)
|
|
return this._engineStore.engines[index].iconURI.spec;
|
|
|
|
if (window.devicePixelRatio > 1)
|
|
return "chrome://browser/skin/search-engine-placeholder@2x.png";
|
|
return "chrome://browser/skin/search-engine-placeholder.png";
|
|
}
|
|
|
|
return "";
|
|
},
|
|
|
|
getCellText(index, column) {
|
|
if (column.id == "engineName")
|
|
return this._engineStore.engines[index].name;
|
|
else if (column.id == "engineKeyword")
|
|
return this._engineStore.engines[index].alias;
|
|
return "";
|
|
},
|
|
|
|
setTree(tree) {
|
|
this.tree = tree;
|
|
},
|
|
|
|
canDrop(targetIndex, orientation, dataTransfer) {
|
|
var sourceIndex = this.getSourceIndexFromDrag(dataTransfer);
|
|
return (sourceIndex != -1 &&
|
|
sourceIndex != targetIndex &&
|
|
sourceIndex != targetIndex + orientation);
|
|
},
|
|
|
|
drop(dropIndex, orientation, dataTransfer) {
|
|
var sourceIndex = this.getSourceIndexFromDrag(dataTransfer);
|
|
var sourceEngine = this._engineStore.engines[sourceIndex];
|
|
|
|
const nsITreeView = Ci.nsITreeView;
|
|
if (dropIndex > sourceIndex) {
|
|
if (orientation == nsITreeView.DROP_BEFORE)
|
|
dropIndex--;
|
|
} else if (orientation == nsITreeView.DROP_AFTER) {
|
|
dropIndex++;
|
|
}
|
|
|
|
this._engineStore.moveEngine(sourceEngine, dropIndex);
|
|
gSearchPane.showRestoreDefaults(true);
|
|
gSearchPane.buildDefaultEngineDropDown();
|
|
|
|
// Redraw, and adjust selection
|
|
this.invalidate();
|
|
this.selection.select(dropIndex);
|
|
},
|
|
|
|
selection: null,
|
|
getRowProperties(index) { return ""; },
|
|
getCellProperties(index, column) { return ""; },
|
|
getColumnProperties(column) { return ""; },
|
|
isContainer(index) { return false; },
|
|
isContainerOpen(index) { return false; },
|
|
isContainerEmpty(index) { return false; },
|
|
isSeparator(index) { return false; },
|
|
isSorted(index) { return false; },
|
|
getParentIndex(index) { return -1; },
|
|
hasNextSibling(parentIndex, index) { return false; },
|
|
getLevel(index) { return 0; },
|
|
getCellValue(index, column) {
|
|
if (column.id == "engineShown")
|
|
return this._engineStore.engines[index].shown;
|
|
return undefined;
|
|
},
|
|
toggleOpenState(index) { },
|
|
cycleHeader(column) { },
|
|
selectionChanged() { },
|
|
cycleCell(row, column) { },
|
|
isEditable(index, column) { return column.id != "engineName"; },
|
|
setCellValue(index, column, value) {
|
|
if (column.id == "engineShown") {
|
|
this._engineStore.engines[index].shown = value == "true";
|
|
gEngineView.invalidate();
|
|
gSearchPane.saveOneClickEnginesList();
|
|
}
|
|
},
|
|
setCellText(index, column, value) {
|
|
if (column.id == "engineKeyword") {
|
|
gSearchPane.editKeyword(this._engineStore.engines[index], value)
|
|
.then(valid => {
|
|
if (!valid)
|
|
document.getElementById("engineList").startEditing(index, column);
|
|
});
|
|
}
|
|
},
|
|
performAction(action) { },
|
|
performActionOnRow(action, index) { },
|
|
performActionOnCell(action, index, column) { },
|
|
};
|