bug 401417 - Add an option for a search box in SeaMonkey toolbar, including additon of an engine manager for OpenSearch, r+ui-r=Neil

This commit is contained in:
Robert Kaiser 2011-03-10 22:42:00 +01:00
Родитель 127ff63bec
Коммит 54b5e8719e
30 изменённых файлов: 1832 добавлений и 20 удалений

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

@ -137,6 +137,9 @@ pref("browser.search.update.log", false);
// Check whether we need to perform engine updates every 6 hours
pref("browser.search.update.interval", 21600);
// enable search suggestions by default
pref("browser.search.suggest.enabled", true);
// Smart Browsing prefs
pref("keyword.enabled", true);
// Override the default keyword.URL. Empty value means

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

@ -1,3 +1,6 @@
@namespace url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul");
@namespace html url("http://www.w3.org/1999/xhtml");
/* ::::: Hide the link toolbar if it is set to autohide and has no items. ::::: */
#linktoolbar[hidden="maybe"][hasitems="false"] {
@ -49,6 +52,15 @@ panel[for="urlbar"] {
-moz-box-align: center;
}
/* ::::: search bar ::::: */
searchbar {
-moz-binding: url("chrome://communicator/content/search/search.xml#searchbar");
}
#wrapper-search-container > #search-container > #searchbar > .searchbar-textbox > .autocomplete-textbox-container > .textbox-input-box > html|*.textbox-input {
visibility: hidden;
}
/* ::::: bookmarks menu ::::: */
.isempty:not(:last-child) {

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

@ -1079,16 +1079,45 @@ var gBookmarkAllTabsHandler = {
const BrowserSearch = {
addEngine: function(engine, targetDoc) {
Services.console.logStringMessage("BrowserSearch.addEngine will be implemented in bug 401417.");
},
if (!this.searchBar)
return;
/**
* Update the browser UI to show whether or not additional engines are
* available when a page is loaded or the user switches tabs to a page that
* has search engines.
*/
updateSearchButton: function() {
Services.console.logStringMessage("BrowserSearch.updateSearchButton will be implemented in bug 401417.");
var browser = getBrowser().getBrowserForDocument(targetDoc);
// ignore search engines from subframes (see bug 479408)
if (!browser)
return;
// Check to see whether we've already added an engine with this title
if (browser.engines) {
if (browser.engines.some(function (e) e.title == engine.title))
return;
}
// Append the URI and an appropriate title to the browser data.
// Use documentURIObject in the check for shouldLoadFavIcon so that we
// do the right thing with about:-style error pages. Bug 453442
var iconURL = null;
if (getBrowser().shouldLoadFavIcon(targetDoc.documentURIObject))
iconURL = getBrowser().buildFavIconString(targetDoc.documentURIObject);
var hidden = false;
// If this engine (identified by title) is already in the list, add it
// to the list of hidden engines rather than to the main list.
// XXX This will need to be changed when engines are identified by URL;
// see bug 335102.
if (Services.search.getEngineByName(engine.title))
hidden = true;
var engines = (hidden ? browser.hiddenEngines : browser.engines) || [];
engines.push({ uri: engine.href,
title: engine.title,
icon: iconURL });
if (hidden)
browser.hiddenEngines = engines;
else
browser.engines = engines;
},
/**
@ -1123,10 +1152,10 @@ const BrowserSearch = {
}
if (isElementVisible(this.searchBar)) {
searchBar.select();
searchBar.focus();
this.searchBar.select();
this.searchBar.focus();
} else if (isElementVisible(this.searchSidebar)) {
searchSidebar.focus();
this.searchSidebar.focus();
} else {
loadURI(Services.search.defaultEngine.searchForm);
window.content.focus();
@ -1197,6 +1226,13 @@ const BrowserSearch = {
return document.getElementById("urn:sidebar:panel:search");
},
loadAddEngines: function BrowserSearch_loadAddEngines() {
var newWindowPref = Services.prefs.getIntPref("browser.link.open_newwindow");
var where = newWindowPref == 3 ? "tabfocused" : "window";
var searchEnginesURL = Services.urlFormatter.formatURLPref("browser.search.searchEnginesURL");
openUILinkIn(searchEnginesURL, where);
},
/**
* Reveal the search sidebar panel.
*/

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

@ -154,6 +154,8 @@
onpopupshowing="window.XULBrowserWindow.populateFeeds(this);"
oncommand="subscribeToFeed(event.target.statusText, event);"
onclick="checkForMiddleClick(this, event);"/>
<!-- for search and content formfill/pw manager -->
<panel id="PopupAutoComplete" type="autocomplete" noautofocus="true"/>
<!-- for invalid form error message -->
@ -293,7 +295,7 @@
ondragover="nsDragAndDrop.dragOver(event, homeButtonObserver); event.stopPropagation()"/>
<toolbaritem id="nav-bar-inner"
flex="1"
flex="4"
persist="width"
class="chromeclass-location nav-bar-class"
title="&locationBar.title;">
@ -377,6 +379,12 @@
ondragexit="nsDragAndDrop.dragExit(event, searchButtonObserver);"/>
</toolbaritem>
<toolbaritem id="search-container" title="&searchItem.title;"
align="center" class="chromeclass-toolbar-additional"
flex="1" persist="width" removable="true">
<searchbar id="searchbar" flex="1"/>
</toolbaritem>
<toolbarbutton id="print-button" type="menu-button"
class="toolbarbutton-1 chromeclass-toolbar-additional"
label="&printButton.label;"

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

@ -456,6 +456,9 @@ nsBrowserStatusHandler.prototype =
var observerService = Components.classes["@mozilla.org/observer-service;1"]
.getService(Components.interfaces.nsIObserverService);
// clear out search-engine data
getBrowser().selectedBrowser.engines = null;
// Set the URI now if it isn't already set, so that the user can tell which
// site is loading. Only do this if user requested the load via chrome UI,
// to minimise spoofing risk.

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

@ -236,6 +236,10 @@ comm.jar:
content/communicator/pref/pref-tabs.xul (pref/pref-tabs.xul)
content/communicator/profile/profileSelection.js (profile/profileSelection.js)
content/communicator/profile/profileSelection.xul (profile/profileSelection.xul)
content/communicator/search/engineManager.js (search/engineManager.js)
content/communicator/search/engineManager.xul (search/engineManager.xul)
* content/communicator/search/search.xml (search/search.xml)
content/communicator/search/searchbarBindings.css (search/searchbarBindings.css)
content/communicator/search/search-panel.js (search/search-panel.js)
content/communicator/search/search-panel.xul (search/search-panel.xul)
content/communicator/sidebar/customize-panel.js (sidebar/customize-panel.js)

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

@ -0,0 +1,526 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is the Browser Search Service.
*
* The Initial Developer of the Original Code is
* Google Inc.
* Portions created by the Initial Developer are Copyright (C) 2005
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Ben Goodger <beng@google.com>
* Gavin Sharp <gavin@gavinsharp.com>
* Pamela Greene <pamg.bugs@gmail.com>
* Ryan Flint <rflint@dslr.net>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
Components.utils.import("resource://gre/modules/Services.jsm");
const Ci = Components.interfaces;
const Cc = Components.classes;
const ENGINE_FLAVOR = "text/x-moz-search-engine";
const BROWSER_SUGGEST_PREF = "browser.search.suggest.enabled";
var gEngineView = null;
var gEngineManagerDialog = {
init: function engineManager_init() {
gEngineView = new EngineView(new EngineStore());
var suggestEnabled = Services.prefs.getBoolPref(BROWSER_SUGGEST_PREF);
document.getElementById("enableSuggest").checked = suggestEnabled;
var tree = document.getElementById("engineList");
tree.view = gEngineView;
Services.obs.addObserver(this, "browser-search-engine-modified", false);
},
destroy: function engineManager_destroy() {
// Remove the observer
Services.obs.removeObserver(this, "browser-search-engine-modified");
},
observe: function engineManager_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);
break;
case "engine-changed":
gEngineView._engineStore.reloadIcons();
gEngineView.invalidate();
break;
case "engine-removed":
case "engine-current":
// Not relevant
break;
}
}
},
onOK: function engineManager_onOK() {
// Set the preference
var newSuggestEnabled = document.getElementById("enableSuggest").checked;
Services.prefs.setBoolPref(BROWSER_SUGGEST_PREF, newSuggestEnabled);
// Commit the changes
gEngineView._engineStore.commit();
},
onRestoreDefaults: function engineManager_onRestoreDefaults() {
var num = gEngineView._engineStore.restoreDefaultEngines();
gEngineView.rowCountChanged(0, num);
gEngineView.invalidate();
},
showRestoreDefaults: function engineManager_showRestoreDefaults(val) {
document.documentElement.getButton("extra2").disabled = !val;
},
loadAddEngines: function engineManager_loadAddEngines() {
this.onOK();
window.opener.BrowserSearch.loadAddEngines();
window.close();
},
remove: function engineManager_remove() {
gEngineView._engineStore.removeEngine(gEngineView.selectedEngine);
var index = gEngineView.selectedIndex;
gEngineView.rowCountChanged(index, -1);
gEngineView.invalidate();
gEngineView.selection.select(Math.min(index, gEngineView.lastIndex));
gEngineView.ensureRowIsVisible(gEngineView.currentIndex);
document.getElementById("engineList").focus();
},
/**
* Moves the selected engine either up or down in the engine list
* @param aDir
* -1 to move the selected engine down, +1 to move it up.
*/
bump: function engineManager_move(aDir) {
var selectedEngine = gEngineView.selectedEngine;
var newIndex = gEngineView.selectedIndex - aDir;
gEngineView._engineStore.moveEngine(selectedEngine, newIndex);
gEngineView.invalidate();
gEngineView.selection.select(newIndex);
gEngineView.ensureRowIsVisible(newIndex);
this.showRestoreDefaults(true);
document.getElementById("engineList").focus();
},
editKeyword: function engineManager_editKeyword() {
var selectedEngine = gEngineView.selectedEngine;
if (!selectedEngine)
return;
var alias = { value: selectedEngine.alias };
var strings = document.getElementById("engineManagerBundle");
var title = strings.getString("editTitle");
var msg = strings.getFormattedString("editMsg", [selectedEngine.name]);
while (Services.prompt.prompt(window, title, msg, alias, null, {})) {
var bduplicate = false;
var eduplicate = false;
var dupName = "";
if (alias.value != "") {
try {
let bmserv = Cc["@mozilla.org/browser/nav-bookmarks-service;1"].
getService(Ci.nsINavBookmarksService);
if (bmserv.getURIForKeyword(alias.value))
bduplicate = true;
} catch(ex) {}
// Check for duplicates in changes we haven't committed yet
let engines = gEngineView._engineStore.engines;
for each (let engine in engines) {
if (engine.alias == alias.value &&
engine.name != selectedEngine.name) {
eduplicate = true;
dupName = engine.name;
break;
}
}
}
// Notify the user if they have chosen an existing engine/bookmark keyword
if (eduplicate || bduplicate) {
var dtitle = strings.getString("duplicateTitle");
var bmsg = strings.getString("duplicateBookmarkMsg");
var emsg = strings.getFormattedString("duplicateEngineMsg", [dupName]);
prompt.alert(window, dtitle, eduplicate ? emsg : bmsg);
} else {
gEngineView._engineStore.changeEngine(selectedEngine, "alias",
alias.value);
gEngineView.invalidate();
break;
}
}
},
onSelect: function engineManager_onSelect() {
// Buttons only work if an engine is selected and it's not the last engine,
// the latter is true when the selected is first and last at the same time.
var lastSelected = (gEngineView.selectedIndex == gEngineView.lastIndex);
var firstSelected = (gEngineView.selectedIndex == 0);
var noSelection = (gEngineView.selectedIndex == -1);
document.getElementById("cmd_remove")
.setAttribute("disabled", noSelection ||
(firstSelected && lastSelected));
document.getElementById("cmd_moveup")
.setAttribute("disabled", noSelection || firstSelected);
document.getElementById("cmd_movedown")
.setAttribute("disabled", noSelection || lastSelected);
document.getElementById("cmd_editkeyword")
.setAttribute("disabled", noSelection);
}
};
function onDragEngineStart(event) {
var selectedIndex = gEngineView.selectedIndex;
if (selectedIndex >= 0) {
event.dataTransfer.setData(ENGINE_FLAVOR, selectedIndex.toString());
event.dataTransfer.effectAllowed = "move";
}
}
// "Operation" objects
function EngineMoveOp(aEngineClone, aNewIndex) {
if (!aEngineClone)
throw new Error("bad args to new EngineMoveOp!");
this._engine = aEngineClone.originalEngine;
this._newIndex = aNewIndex;
}
EngineMoveOp.prototype = {
_engine: null,
_newIndex: null,
commit: function EMO_commit() {
Services.search.moveEngine(this._engine, this._newIndex);
}
}
function EngineRemoveOp(aEngineClone) {
if (!aEngineClone)
throw new Error("bad args to new EngineRemoveOp!");
this._engine = aEngineClone.originalEngine;
}
EngineRemoveOp.prototype = {
_engine: null,
commit: function ERO_commit() {
Services.search.removeEngine(this._engine);
}
}
function EngineUnhideOp(aEngineClone, aNewIndex) {
if (!aEngineClone)
throw new Error("bad args to new EngineUnhideOp!");
this._engine = aEngineClone.originalEngine;
this._newIndex = aNewIndex;
}
EngineUnhideOp.prototype = {
_engine: null,
_newIndex: null,
commit: function EUO_commit() {
this._engine.hidden = false;
Services.search.moveEngine(this._engine, this._newIndex);
}
}
function EngineChangeOp(aEngineClone, aProp, aValue) {
if (!aEngineClone)
throw new Error("bad args to new EngineChangeOp!");
this._engine = aEngineClone.originalEngine;
this._prop = aProp;
this._newValue = aValue;
}
EngineChangeOp.prototype = {
_engine: null,
_prop: null,
_newValue: null,
commit: function ECO_commit() {
this._engine[this._prop] = this._newValue;
}
}
function EngineStore() {
this._engines = Services.search.getVisibleEngines().map(this._cloneEngine);
this._defaultEngines = Services.search.getDefaultEngines().map(this._cloneEngine);
this._ops = [];
// check if we need to disable the restore defaults button
var someHidden = this._defaultEngines.some(function (e) e.hidden);
gEngineManagerDialog.showRestoreDefaults(someHidden);
}
EngineStore.prototype = {
_engines: null,
_defaultEngines: null,
_ops: null,
get engines() {
return this._engines;
},
set engines(val) {
this._engines = val;
return val;
},
_getIndexForEngine: function ES_getIndexForEngine(aEngine) {
return this._engines.indexOf(aEngine);
},
_getEngineByName: function ES_getEngineByName(aName) {
for each (var engine in this._engines)
if (engine.name == aName)
return engine;
return null;
},
_cloneEngine: function ES_cloneEngine(aEngine) {
var clonedObj={};
for (var i in aEngine)
clonedObj[i] = aEngine[i];
clonedObj.originalEngine = aEngine;
return clonedObj;
},
// Callback for Array's some(). A thisObj must be passed to some()
_isSameEngine: function ES_isSameEngine(aEngineClone) {
return aEngineClone.originalEngine == this.originalEngine;
},
commit: function ES_commit() {
var currentEngine = this._cloneEngine(Services.search.currentEngine);
for (var i = 0; i < this._ops.length; i++)
this._ops[i].commit();
// Restore currentEngine if it is a default engine that is still visible.
// Needed if the user deletes currentEngine and then restores it.
if (this._defaultEngines.some(this._isSameEngine, currentEngine) &&
!currentEngine.originalEngine.hidden)
Services.search.currentEngine = currentEngine.originalEngine;
},
addEngine: function ES_addEngine(aEngine) {
this._engines.push(this._cloneEngine(aEngine));
},
moveEngine: function ES_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);
this._ops.push(new EngineMoveOp(aEngine, aNewIndex));
},
removeEngine: function ES_removeEngine(aEngine) {
var index = this._getIndexForEngine(aEngine);
if (index == -1)
throw new Error("invalid engine?");
this._engines.splice(index, 1);
this._ops.push(new EngineRemoveOp(aEngine));
if (this._defaultEngines.some(this._isSameEngine, aEngine))
gEngineManagerDialog.showRestoreDefaults(true);
},
restoreDefaultEngines: function ES_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
this._engines.splice(i, 0, e);
this._ops.push(new EngineUnhideOp(e, i));
added++;
}
}
gEngineManagerDialog.showRestoreDefaults(false);
return added;
},
changeEngine: function ES_changeEngine(aEngine, aProp, aNewValue) {
var index = this._getIndexForEngine(aEngine);
if (index == -1)
throw new Error("invalid engine?");
this._engines[index][aProp] = aNewValue;
this._ops.push(new EngineChangeOp(aEngine, aProp, aNewValue));
},
reloadIcons: function ES_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: function (index, count) {
this.tree.rowCountChanged(index, count);
},
invalidate: function () {
this.tree.invalidate();
},
ensureRowIsVisible: function (index) {
this.tree.ensureRowIsVisible(index);
},
getSourceIndexFromDrag: function (dataTransfer) {
return parseInt(dataTransfer.getData(ENGINE_FLAVOR));
},
// nsITreeView
get rowCount() {
return this._engineStore.engines.length;
},
getImageSrc: function(index, column) {
if (column.id == "engineName" && this._engineStore.engines[index].iconURI)
return this._engineStore.engines[index].iconURI.spec;
return "";
},
getCellText: function(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: function(tree) {
this.tree = tree;
},
canDrop: function(targetIndex, orientation, dataTransfer) {
var sourceIndex = this.getSourceIndexFromDrag(dataTransfer);
return (sourceIndex != -1 &&
sourceIndex != targetIndex &&
sourceIndex != targetIndex + orientation);
},
drop: function(dropIndex, orientation, dataTransfer) {
var sourceIndex = this.getSourceIndexFromDrag(dataTransfer);
var sourceEngine = this._engineStore.engines[sourceIndex];
if (dropIndex > sourceIndex) {
if (orientation == Ci.nsITreeView.DROP_BEFORE)
dropIndex--;
} else {
if (orientation == Ci.nsITreeView.DROP_AFTER)
dropIndex++;
}
this._engineStore.moveEngine(sourceEngine, dropIndex);
gEngineManagerDialog.showRestoreDefaults(true);
// Redraw, and adjust selection
this.invalidate();
this.selection.select(dropIndex);
},
selection: null,
getRowProperties: function(index, properties) { },
getCellProperties: function(index, column, properties) { },
getColumnProperties: function(column, properties) { },
isContainer: function(index) { return false; },
isContainerOpen: function(index) { return false; },
isContainerEmpty: function(index) { return false; },
isSeparator: function(index) { return false; },
isSorted: function(index) { return false; },
getParentIndex: function(index) { return -1; },
hasNextSibling: function(parentIndex, index) { return false; },
getLevel: function(index) { return 0; },
getProgressMode: function(index, column) { },
getCellValue: function(index, column) { },
toggleOpenState: function(index) { },
cycleHeader: function(column) { },
selectionChanged: function() { },
cycleCell: function(row, column) { },
isEditable: function(index, column) { return false; },
isSelectable: function(index, column) { return false; },
setCellValue: function(index, column, value) { },
setCellText: function(index, column, value) { },
performAction: function(action) { },
performActionOnRow: function(action, index) { },
performActionOnCell: function(action, index, column) { }
};

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

@ -0,0 +1,127 @@
<?xml version="1.0"?>
<!-- ***** BEGIN LICENSE BLOCK *****
- Version: MPL 1.1/GPL 2.0/LGPL 2.1
-
- The contents of this file are subject to the Mozilla Public License Version
- 1.1 (the "License"); you may not use this file except in compliance with
- the License. You may obtain a copy of the License at
- http://www.mozilla.org/MPL/
-
- Software distributed under the License is distributed on an "AS IS" basis,
- WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- for the specific language governing rights and limitations under the
- License.
-
- The Original Code is the Browser Search Service.
-
- The Initial Developer of the Original Code is
- Google Inc.
- Portions created by the Initial Developer are Copyright (C) 2005
- the Initial Developer. All Rights Reserved.
-
- Contributor(s):
- Ben Goodger <beng@google.com>
- Gavin Sharp <gavin@gavinsharp.com>
-
- Alternatively, the contents of this file may be used under the terms of
- either the GNU General Public License Version 2 or later (the "GPL"), or
- the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- in which case the provisions of the GPL or the LGPL are applicable instead
- of those above. If you wish to allow use of your version of this file only
- under the terms of either the GPL or the LGPL, and not to allow others to
- use your version of this file under the terms of the MPL, indicate your
- decision by deleting the provisions above and replace them with the notice
- and other provisions required by the GPL or the LGPL. If you do not delete
- the provisions above, a recipient may use your version of this file under
- the terms of any one of the MPL, the GPL or the LGPL.
-
- ***** END LICENSE BLOCK ***** -->
<?xml-stylesheet href="chrome://global/skin/"?>
<?xml-stylesheet href="chrome://communicator/skin/search/engineManager.css"?>
<!DOCTYPE dialog SYSTEM "chrome://communicator/locale/search/engineManager.dtd">
<dialog id="engineManager"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
buttons="accept,cancel,extra2"
buttonlabelextra2="&restoreDefaults.label;"
buttonaccesskeyextra2="&restoreDefaults.accesskey;"
onload="gEngineManagerDialog.init();"
onunload="gEngineManagerDialog.destroy();"
ondialogaccept="gEngineManagerDialog.onOK();"
ondialogextra2="gEngineManagerDialog.onRestoreDefaults();"
title="&engineManager.title;"
style="&engineManager.style;"
persist="screenX screenY width height"
windowtype="Browser:SearchManager">
<script type="application/javascript"
src="chrome://communicator/content/search/engineManager.js"/>
<commandset id="engineManagerCommandSet">
<command id="cmd_remove"
oncommand="gEngineManagerDialog.remove();"
disabled="true"/>
<command id="cmd_moveup"
oncommand="gEngineManagerDialog.bump(1);"
disabled="true"/>
<command id="cmd_movedown"
oncommand="gEngineManagerDialog.bump(-1);"
disabled="true"/>
<command id="cmd_editkeyword"
oncommand="gEngineManagerDialog.editKeyword();"
disabled="true"/>
</commandset>
<keyset id="engineManagerKeyset">
<key id="delete" keycode="VK_DELETE" command="cmd_remove"/>
</keyset>
<stringbundleset id="engineManagerBundleset">
<stringbundle id="engineManagerBundle" src="chrome://communicator/locale/search/engineManager.properties"/>
</stringbundleset>
<description>&engineManager.intro;</description>
<separator class="thin"/>
<hbox flex="1">
<tree id="engineList" flex="1" rows="10" hidecolumnpicker="true"
seltype="single" onselect="gEngineManagerDialog.onSelect();">
<treechildren id="engineChildren" flex="1"
ondragstart="onDragEngineStart(event);"/>
<treecols>
<treecol id="engineName" flex="4" label="&columnLabel.name;"/>
<treecol id="engineKeyword" flex="1" label="&columnLabel.keyword;"/>
</treecols>
</tree>
<vbox>
<spacer flex="1"/>
<button id="edit"
label="&edit.label;"
accesskey="&edit.accesskey;"
command="cmd_editkeyword"/>
<button id="up"
label="&up.label;"
accesskey="&up.accesskey;"
command="cmd_moveup"/>
<button id="down"
label="&dn.label;"
accesskey="&dn.accesskey;"
command="cmd_movedown"/>
<spacer flex="1"/>
<button id="remove"
label="&remove.label;"
accesskey="&remove.accesskey;"
command="cmd_remove"/>
</vbox>
</hbox>
<hbox>
<checkbox id="enableSuggest"
label="&enableSuggest.label;"
accesskey="&enableSuggest.accesskey;"/>
</hbox>
<hbox>
<label id="addEngines" class="text-link" value="&addEngine.label;"
onclick="if (event.button == 0) { gEngineManagerDialog.loadAddEngines(); }"/>
</hbox>
</dialog>

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

@ -0,0 +1,747 @@
<?xml version="1.0"?>
<!-- ***** BEGIN LICENSE BLOCK *****
- Version: MPL 1.1/GPL 2.0/LGPL 2.1
-
- The contents of this file are subject to the Mozilla Public License Version
- 1.1 (the "License"); you may not use this file except in compliance with
- the License. You may obtain a copy of the License at
- http://www.mozilla.org/MPL/
-
- Software distributed under the License is distributed on an "AS IS" basis,
- WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- for the specific language governing rights and limitations under the
- License.
-
- The Original Code is mozilla.org browser.
-
- The Initial Developer of the Original Code is
- Joe Hewitt.
- Portions created by the Initial Developer are Copyright (C) 2003
- the Initial Developer. All Rights Reserved.
-
- Contributor(s):
- Pierre Chanial (v2) <p_ch@verizon.net>
- Gavin Sharp (v3) <gavin@gavinsharp.com>
- Ben Goodger <beng@google.com>
- Pamela Greene <pamg.bugs@gmail.com>
- Michael Ventnor <m.ventnor@gmail.com>
- Ehsan Akhgari <ehsan.akhgari@gmail.com>
-
- Alternatively, the contents of this file may be used under the terms of
- either the GNU General Public License Version 2 or later (the "GPL"), or
- the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- in which case the provisions of the GPL or the LGPL are applicable instead
- of those above. If you wish to allow use of your version of this file only
- under the terms of either the GPL or the LGPL, and not to allow others to
- use your version of this file under the terms of the MPL, indicate your
- decision by deleting the provisions above and replace them with the notice
- and other provisions required by the GPL or the LGPL. If you do not delete
- the provisions above, a recipient may use your version of this file under
- the terms of any one of the MPL, the GPL or the LGPL.
-
- ***** END LICENSE BLOCK ***** -->
<!DOCTYPE bindings [
<!ENTITY % searchBarDTD SYSTEM "chrome://communicator/locale/search/searchbar.dtd">
%searchBarDTD;
<!ENTITY % navigatorDTD SYSTEM "chrome://navigator/locale/navigator.dtd">
%navigatorDTD;
]>
<bindings id="SearchBindings"
xmlns="http://www.mozilla.org/xbl"
xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
xmlns:xbl="http://www.mozilla.org/xbl">
<binding id="searchbar">
<resources>
<stylesheet src="chrome://communicator/content/search/searchbarBindings.css"/>
<stylesheet src="chrome://communicator/skin/search/searchbar.css"/>
</resources>
<content>
<xul:stringbundle src="chrome://communicator/locale/search/search.properties"
anonid="searchbar-stringbundle"/>
<xul:textbox class="searchbar-textbox"
anonid="searchbar-textbox"
type="autocomplete"
flex="1"
autocompletepopup="PopupAutoComplete"
autocompletesearch="search-autocomplete"
autocompletesearchparam="searchbar-history"
timeout="250"
maxrows="10"
completeselectedindex="true"
showcommentcolumn="true"
tabscrolling="true"
xbl:inherits="disabled,disableautocomplete,searchengine,src,newlines">
<xul:box>
<xul:button class="plain searchbar-engine-button"
type="menu"
anonid="searchbar-engine-button">
<xul:image class="searchbar-engine-image" xbl:inherits="src"/>
<xul:image class="searchbar-dropmarker-image"/>
<xul:menupopup class="searchbar-popup"
anonid="searchbar-popup">
<xul:menuseparator/>
<xul:menuitem class="open-engine-manager"
anonid="open-engine-manager"
label="&cmd_engineManager.label;"
oncommand="openManager(event);"/>
</xul:menupopup>
</xul:button>
</xul:box>
<xul:hbox class="search-go-container">
<xul:image class="search-go-button"
anonid="search-go-button"
onclick="handleSearchCommand(event);"
tooltiptext="&searchEndCap.label;"/>
</xul:hbox>
</xul:textbox>
</content>
<implementation implements="nsIObserver">
<constructor><![CDATA[
if (this.parentNode.parentNode.localName == "toolbarpaletteitem")
return;
setTimeout(function (a) { a.init(); }, 0, this);
]]></constructor>
<method name="init">
<body><![CDATA[
// Make sure we rebuild the popup in onpopupshowing
this._needToBuildPopup = true;
// Refresh the display (updating icon, etc)
this.updateDisplay();
var os =
Components.classes["@mozilla.org/observer-service;1"]
.getService(Components.interfaces.nsIObserverService);
os.addObserver(this, "browser-search-engine-modified", false);
this._addedObserver = true;
]]></body>
</method>
<destructor><![CDATA[
if (this._addedObserver) {
var os = Components.classes["@mozilla.org/observer-service;1"]
.getService(Components.interfaces.nsIObserverService);
os.removeObserver(this, "browser-search-engine-modified");
}
// Make sure to break the cycle from _texbox to us. Otherwise we leak
// the world. But make sure it's actually pointing to us.
if (this._textbox.mController.input == this)
this._textbox.mController.input = null;
]]></destructor>
<field name="_stringBundle">document.getAnonymousElementByAttribute(this,
"anonid", "searchbar-stringbundle");</field>
<field name="_textbox">document.getAnonymousElementByAttribute(this,
"anonid", "searchbar-textbox");</field>
<field name="_popup">document.getAnonymousElementByAttribute(this,
"anonid", "searchbar-popup");</field>
<field name="searchButton">document.getAnonymousElementByAttribute(this,
"anonid", "searchbar-engine-button");</field>
<field name="_searchService">
Components.classes["@mozilla.org/browser/search-service;1"]
.getService(Components.interfaces.nsIBrowserSearchService);
</field>
<field name="_engines">null</field>
<property name="engines" readonly="true">
<getter><![CDATA[
if (!this._engines)
this._engines = this.searchService.getVisibleEngines();
return this._engines;
]]></getter>
</property>
<property name="currentEngine"
onset="this.searchService.currentEngine = val; return val;">
<getter><![CDATA[
var currentEngine = this.searchService.currentEngine;
// Return a dummy engine if there is no currentEngine
return currentEngine || {name: "", uri: null};
]]></getter>
</property>
<!-- textbox is used by sanitize.js to clear the undo history when
clearing form information. -->
<property name="textbox" readonly="true"
onget="return this._textbox;"/>
<property name="searchService" readonly="true"
onget="return this._searchService;"/>
<property name="value" onget="return this._textbox.value;"
onset="return this._textbox.value = val;"/>
<method name="focus">
<body><![CDATA[
this._textbox.focus();
]]></body>
</method>
<method name="select">
<body><![CDATA[
this._textbox.select();
]]></body>
</method>
<method name="observe">
<parameter name="aEngine"/>
<parameter name="aTopic"/>
<parameter name="aVerb"/>
<body><![CDATA[
if (aTopic == "browser-search-engine-modified") {
switch (aVerb) {
case "engine-removed":
this.offerNewEngine(aEngine);
break;
case "engine-added":
this.hideNewEngine(aEngine);
break;
case "engine-current":
// The current engine was changed. Rebuilding the menu appears to
// confuse its idea of whether it should be open when it's just
// been clicked, so we force it to close now.
this._popup.hidePopup();
break;
case "engine-changed":
// An engine was removed (or hidden) or added, or an icon was
// changed. Do nothing special.
}
// Make sure the engine list is refetched next time it's needed
this._engines = null;
// Rebuild the popup and update the display after any modification.
this.rebuildPopup();
this.updateDisplay();
}
]]></body>
</method>
<!-- There are two seaprate lists of search engines, whose uses intersect
in this file. The search service (nsIBrowserSearchService and
nsSearchService.js) maintains a list of Engine objects which is used to
populate the searchbox list of available engines and to perform queries.
That list is accessed here via this.SearchService, and it's that sort of
Engine that is passed to this binding's observer as aEngine.
In addition, browser.js fills two lists of autodetected search engines
(browser.engines and browser.hiddenEngines) as properties of
mCurrentBrowser. Those lists contain unnamed JS objects of the form
{ uri:, title:, icon: }, and that's what the searchbar uses to determine
whether to show any "Add <EngineName>" menu items in the drop-down.
The two types of engines are currently related by their identifying
titles (the Engine object's 'name'), although that may change; see bug
335102. -->
<!-- If the engine that was just removed from the searchbox list was
autodetected on this page, move it to each browser's active list so it
will be offered to be added again. -->
<method name="offerNewEngine">
<parameter name="aEngine"/>
<body><![CDATA[
var allbrowsers = getBrowser().mPanelContainer.childNodes;
for (var tab = 0; tab < allbrowsers.length; tab++) {
var browser = getBrowser().getBrowserAtIndex(tab);
if (browser.hiddenEngines) {
// XXX This will need to be changed when engines are identified by
// URL rather than title; see bug 335102.
var removeTitle = aEngine.wrappedJSObject.name;
for (var i = 0; i < browser.hiddenEngines.length; i++) {
if (browser.hiddenEngines[i].title == removeTitle) {
if (!browser.engines)
browser.engines = [];
browser.engines.push(browser.hiddenEngines[i]);
browser.hiddenEngines.splice(i, 1);
break;
}
}
}
}
]]></body>
</method>
<!-- If the engine that was just added to the searchbox list was
autodetected on this page, move it to each browser's hidden list so it is
no longer offered to be added. -->
<method name="hideNewEngine">
<parameter name="aEngine"/>
<body><![CDATA[
var allbrowsers = getBrowser().mPanelContainer.childNodes;
for (var tab = 0; tab < allbrowsers.length; tab++) {
var browser = getBrowser().getBrowserAtIndex(tab);
if (browser.engines) {
// XXX This will need to be changed when engines are identified by
// URL rather than title; see bug 335102.
var removeTitle = aEngine.wrappedJSObject.name;
for (var i = 0; i < browser.engines.length; i++) {
if (browser.engines[i].title == removeTitle) {
if (!browser.hiddenEngines)
browser.hiddenEngines = [];
browser.hiddenEngines.push(browser.engines[i]);
browser.engines.splice(i, 1);
break;
}
}
}
}
]]></body>
</method>
<method name="updateDisplay">
<body><![CDATA[
var uri = this.currentEngine.iconURI;
this.setAttribute("src", uri ? uri.spec : "");
var name = this.currentEngine.name;
var text = this._stringBundle.getFormattedString("searchtip", [name]);
this._textbox.placeholder = name;
this._textbox.tooltipText = text;
]]></body>
</method>
<!-- Rebuilds the dynamic portion of the popup menu (i.e., the menu items
for new search engines that can be added to the available list). This
is called each time the popup is shown.
-->
<method name="rebuildPopupDynamic">
<body><![CDATA[
// We might not have added the main popup items yet, do that first
// if needed.
if (this._needToBuildPopup)
this.rebuildPopup();
var popup = this._popup;
// Clear any addengine menuitems, including addengine-item entries and
// the addengine-separator. Work backward to avoid invalidating the
// indexes as items are removed.
var items = popup.childNodes;
for (var i = items.length - 1; i >= 0; i--) {
if (items[i].classList.contains("addengine-item") ||
items[i].classList.contains("addengine-separator"))
popup.removeChild(items[i]);
}
var addengines = getBrowser().mCurrentBrowser.engines;
if (addengines && addengines.length > 0) {
const kXULNS =
"http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
// Find the (first) separator in the remaining menu, or the first item
// if no separators are present.
var insertLocation = popup.firstChild;
while (insertLocation.nextSibling &&
insertLocation.localName != "menuseparator") {
insertLocation = insertLocation.nextSibling;
}
if (insertLocation.localName != "menuseparator")
insertLocation = popup.firstChild;
var separator = document.createElementNS(kXULNS, "menuseparator");
separator.setAttribute("class", "addengine-separator");
popup.insertBefore(separator, insertLocation);
// Insert the "add this engine" items.
for (var i = 0; i < addengines.length; i++) {
var menuitem = document.createElement("menuitem");
var engineInfo = addengines[i];
var labelStr =
this._stringBundle.getFormattedString("cmd_addFoundEngine",
[engineInfo.title]);
menuitem = document.createElementNS(kXULNS, "menuitem");
menuitem.setAttribute("class", "menuitem-iconic addengine-item");
menuitem.setAttribute("label", labelStr);
menuitem.setAttribute("tooltiptext", engineInfo.uri);
menuitem.setAttribute("uri", engineInfo.uri);
if (engineInfo.icon)
menuitem.setAttribute("src", engineInfo.icon);
menuitem.setAttribute("title", engineInfo.title);
popup.insertBefore(menuitem, insertLocation);
}
}
]]></body>
</method>
<!-- Rebuilds the list of visible search engines in the menu. Does not remove
or update any dynamic entries (i.e., "Add this engine" items) nor the
Manage Engines item. This is called by the observer when the list of
visible engines, or the currently selected engine, has changed.
-->
<method name="rebuildPopup">
<body><![CDATA[
var popup = this._popup;
// Clear the popup, down to the first separator
while (popup.firstChild && popup.firstChild.localName != "menuseparator")
popup.removeChild(popup.firstChild);
const kXULNS =
"http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
var engines = this.engines;
for (var i = engines.length - 1; i >= 0; --i) {
var menuitem = document.createElementNS(kXULNS, "menuitem");
var name = engines[i].name;
menuitem.setAttribute("label", name);
menuitem.setAttribute("id", name);
menuitem.setAttribute("class", "menuitem-iconic searchbar-engine-menuitem menuitem-with-favicon");
// Since this menu is rebuilt by the observer method whenever a new
// engine is selected, the "selected" attribute does not need to be
// explicitly cleared anywhere.
if (engines[i] == this.currentEngine)
menuitem.setAttribute("selected", "true");
var tooltip = this._stringBundle.getFormattedString("searchtip", [name]);
menuitem.setAttribute("tooltiptext", tooltip);
if (engines[i].iconURI)
menuitem.setAttribute("src", engines[i].iconURI.spec);
popup.insertBefore(menuitem, popup.firstChild);
menuitem.engine = engines[i];
}
this._needToBuildPopup = false;
]]></body>
</method>
<method name="openManager">
<parameter name="aEvent"/>
<body><![CDATA[
var wm =
Components.classes["@mozilla.org/appshell/window-mediator;1"]
.getService(Components.interfaces.nsIWindowMediator);
var window = wm.getMostRecentWindow("Browser:SearchManager");
if (window)
window.focus()
else {
setTimeout(function () {
openDialog("chrome://communicator/content/search/engineManager.xul",
"_blank", "chrome,dialog,modal,centerscreen,resizable");
}, 0);
}
]]></body>
</method>
<method name="selectEngine">
<parameter name="aEvent"/>
<parameter name="isNextEngine"/>
<body><![CDATA[
// Find the new index
var newIndex = this.engines.indexOf(this.currentEngine);
newIndex += isNextEngine ? 1 : -1;
if (newIndex >= 0 && newIndex < this.engines.length)
this.currentEngine = this.engines[newIndex];
aEvent.preventDefault();
aEvent.stopPropagation();
]]></body>
</method>
<method name="handleSearchCommand">
<parameter name="aEvent"/>
<body><![CDATA[
var textBox = this._textbox;
var textValue = textBox.value;
var where = "current";
if (aEvent && aEvent.originalTarget.getAttribute("anonid") == "search-go-button") {
if (aEvent.button == 2)
return;
where = whereToOpenLink(aEvent, false, true);
}
else {
var newTabPref = textBox._prefBranch.getBoolPref("browser.search.openintab");
if ((aEvent && aEvent.altKey) ^ newTabPref)
where = "tabfocused";
}
// Save the current value in the form history
if (textValue) {
textBox._formHistSvc.addEntry(textBox.getAttribute("autocompletesearchparam"),
textValue);
}
this.doSearch(textValue, where);
]]></body>
</method>
<method name="doSearch">
<parameter name="aData"/>
<parameter name="aWhere"/>
<body><![CDATA[
// null parameter below specifies HTML response for search
var submission = this.currentEngine.getSubmission(aData);
openUILinkIn(submission.uri.spec, aWhere, null, submission.postData);
]]></body>
</method>
</implementation>
<handlers>
<handler event="command"><![CDATA[
const target = event.originalTarget;
if (target.classList.contains("addengine-item")) {
var searchService =
Components.classes["@mozilla.org/browser/search-service;1"]
.getService(Components.interfaces.nsIBrowserSearchService);
// We only detect OpenSearch files
var type = Components.interfaces.nsISearchEngine.DATA_XML;
searchService.addEngine(target.getAttribute("uri"), type,
target.getAttribute("src"), false);
}
else if (target.engine)
this.currentEngine = target.engine;
else
return;
this.focus();
this.select();
]]></handler>
<handler event="popupshowing" action="this.rebuildPopupDynamic();"/>
<handler event="DOMMouseScroll"
phase="capturing"
#ifdef XP_MACOSX
action="if (event.metaKey) this.selectEngine(event, (event.detail > 0));"/>
#else
action="if (event.ctrlKey) this.selectEngine(event, (event.detail > 0));"/>
#endif
</handlers>
</binding>
<binding id="searchbar-textbox"
extends="chrome://global/content/bindings/autocomplete.xml#autocomplete">
<implementation implements="nsIObserver">
<constructor><![CDATA[
if (document.getBindingParent(this).parentNode.parentNode.localName ==
"toolbarpaletteitem")
return;
setTimeout(function(a) { a.initialize(); }, 0, this);
]]></constructor>
<destructor><![CDATA[
this._prefBranch.removeObserver("browser.search.suggest.enabled", this);
// Because XBL and the customize toolbar code interacts poorly,
// there may not be anything to remove here
try {
this.controllers.removeController(this.searchbarController);
} catch (ex) { }
]]></destructor>
<field name="_stringBundle">document.getBindingParent(this)._stringBundle</field>
<field name="_formHistSvc">
Components.classes["@mozilla.org/satchel/form-history;1"]
.getService(Components.interfaces.nsIFormHistory2)
</field>
<field name="_prefBranch">
Components.classes["@mozilla.org/preferences-service;1"]
.getService(Components.interfaces.nsIPrefBranch2)
</field>
<field name="_suggestMenuItem"/>
<field name="_suggestEnabled">
this._prefBranch.getBoolPref("browser.search.suggest.enabled")
</field>
<method name="initialize">
<body><![CDATA[
const kXULNS =
"http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
if (this._prefBranch.getBoolPref("browser.urlbar.clickSelectsAll"))
this.setAttribute("clickSelectsAll", true);
// Add items to context menu and attach controller to handle them
var textBox = document.getAnonymousElementByAttribute(this,
"anonid", "textbox-input-box");
var cxmenu = document.getAnonymousElementByAttribute(textBox,
"anonid", "input-box-contextmenu");
var pasteAndSearch;
cxmenu.addEventListener("popupshowing", function() {
if (!pasteAndSearch)
return;
var controller = document.commandDispatcher.getControllerForCommand("cmd_paste");
var enabled = controller.isCommandEnabled("cmd_paste");
if (enabled)
pasteAndSearch.removeAttribute("disabled");
else
pasteAndSearch.setAttribute("disabled", "true");
}, false);
var element, label, akey;
element = document.createElementNS(kXULNS, "menuseparator");
cxmenu.appendChild(element);
var insertLocation = cxmenu.firstChild;
while (insertLocation.nextSibling &&
insertLocation.getAttribute("cmd") != "cmd_paste")
insertLocation = insertLocation.nextSibling;
if (insertLocation) {
element = document.createElementNS(kXULNS, "menuitem");
label = this._stringBundle.getString("cmd_pasteAndSearch");
element.setAttribute("label", label);
element.setAttribute("anonid", "paste-and-search");
element.setAttribute("oncommand",
"BrowserSearch.searchBar.select(); goDoCommand('cmd_paste'); BrowserSearch.searchBar.handleSearchCommand();");
cxmenu.insertBefore(element, insertLocation.nextSibling);
pasteAndSearch = element;
}
element = document.createElementNS(kXULNS, "menuitem");
label = this._stringBundle.getString("cmd_clearHistory");
akey = this._stringBundle.getString("cmd_clearHistory_accesskey");
element.setAttribute("label", label);
element.setAttribute("accesskey", akey);
element.setAttribute("cmd", "cmd_clearhistory");
cxmenu.appendChild(element);
element = document.createElementNS(kXULNS, "menuitem");
label = this._stringBundle.getString("cmd_showSuggestions");
akey = this._stringBundle.getString("cmd_showSuggestions_accesskey");
element.setAttribute("anonid", "toggle-suggest-item");
element.setAttribute("label", label);
element.setAttribute("accesskey", akey);
element.setAttribute("cmd", "cmd_togglesuggest");
element.setAttribute("type", "checkbox");
element.setAttribute("checked", this._suggestEnabled);
element.setAttribute("autocheck", "false");
this._suggestMenuItem = element;
cxmenu.appendChild(element);
this.controllers.appendController(this.searchbarController);
// Add observer for suggest preference
this._prefBranch.addObserver("browser.search.suggest.enabled", this, false);
]]></body>
</method>
<method name="observe">
<parameter name="aSubject"/>
<parameter name="aTopic"/>
<parameter name="aData"/>
<body><![CDATA[
if (aTopic == "nsPref:changed") {
this._suggestEnabled =
this._prefBranch.getBoolPref("browser.search.suggest.enabled");
this._suggestMenuItem.setAttribute("checked", this._suggestEnabled);
}
]]></body>
</method>
<method name="openSearch">
<body>
<![CDATA[
// Don't open search popup if history popup is open
if (!this.popupOpen) {
document.getBindingParent(this).searchButton.open = true;
return false;
}
return true;
]]>
</body>
</method>
<!-- override |onTextEntered| in autocomplete.xml -->
<method name="onTextEntered">
<parameter name="aEvent"/>
<body><![CDATA[
var evt = aEvent || this.mEnterEvent;
document.getBindingParent(this).handleSearchCommand(evt);
this.mEnterEvent = null;
]]></body>
</method>
<!-- nsIController -->
<field name="searchbarController" readonly="true"><![CDATA[({
_self: this,
supportsCommand: function(aCommand) {
return aCommand == "cmd_clearhistory" ||
aCommand == "cmd_togglesuggest";
},
isCommandEnabled: function(aCommand) {
if (aCommand == "cmd_clearhistory") {
var param = this._self.getAttribute("autocompletesearchparam");
return this._self._formHistSvc.nameExists(param);
}
return true;
},
doCommand: function (aCommand) {
switch (aCommand) {
case "cmd_clearhistory":
var param = this._self.getAttribute("autocompletesearchparam");
this._self._formHistSvc.removeEntriesForName(param);
this._self.value = "";
break;
case "cmd_togglesuggest":
// The pref observer will update _suggestEnabled and the menu
// checkmark.
this._self._prefBranch.setBoolPref("browser.search.suggest.enabled",
!this._self._suggestEnabled);
break;
default:
// do nothing with unrecognized command
}
}
})]]></field>
</implementation>
<handlers>
<handler event="keypress" keycode="VK_UP" modifiers="accel"
phase="capturing"
action="document.getBindingParent(this).selectEngine(event, false);"/>
<handler event="keypress" keycode="VK_DOWN" modifiers="accel"
phase="capturing"
action="document.getBindingParent(this).selectEngine(event, true);"/>
<handler event="keypress" keycode="VK_DOWN" modifiers="alt"
phase="capturing"
action="return this.openSearch();"/>
<handler event="keypress" keycode="VK_UP" modifiers="alt"
phase="capturing"
action="return this.openSearch();"/>
#ifndef XP_MACOSX
<handler event="keypress" keycode="VK_F4"
phase="capturing"
action="return this.openSearch();"/>
#endif
<handler event="dragover">
<![CDATA[
var types = event.dataTransfer.types;
if (types.contains("text/plain") || types.contains("text/x-moz-text-internal"))
event.preventDefault();
]]>
</handler>
<handler event="drop">
<![CDATA[
var dataTransfer = event.dataTransfer;
var data = dataTransfer.getData("text/plain");
if (!data)
data = dataTransfer.getData("text/x-moz-text-internal");
if (data) {
event.preventDefault();
this.value = data;
this.onTextEntered(event);
}
]]>
</handler>
</handlers>
</binding>
</bindings>

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

@ -0,0 +1,13 @@
@namespace url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul");
.searchbar-textbox {
-moz-binding: url("chrome://communicator/content/search/search.xml#searchbar-textbox");
}
.searchbar-engine-button {
-moz-user-focus: none;
}
.autocomplete-history-dropmarker {
display: none;
}

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

@ -152,10 +152,10 @@
<!ENTITY locationBar.tooltip "Enter search term, keyword, or web address">
<!ENTITY locationBar.accesskey "d">
<!ENTITY locationBar.title "Location">
<!ENTITY proxyIcon.tooltip "Drag and drop this icon to create a link to this page">
<!-- Toolbar items -->
<!ENTITY searchItem.title "Search">
<!ENTITY bookmarksButton.label "Bookmarks">
<!ENTITY bookmarksButton.tooltip "Bookmarks list">
<!ENTITY homeButton.label "Home">

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

@ -7,6 +7,9 @@
<!ENTITY defaultSearchEngine.label "Search using:">
<!ENTITY defaultSearchEngine.accesskey "S">
<!-- Will be used by bug 595246 -->
<!ENTITY engineManager.label "Manage Search Engines…">
<!ENTITY searchResults.label "Search Results">
<!ENTITY openInTab.label "Open new tabs for sidebar search results">

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

@ -0,0 +1,25 @@
<!ENTITY engineManager.title "Manage Search Engine List">
<!ENTITY engineManager.style "min-width: 35em;">
<!ENTITY engineManager.intro "You have the following search engines installed:">
<!ENTITY columnLabel.name "Name">
<!ENTITY columnLabel.keyword "Keyword">
<!-- Buttons -->
<!ENTITY up.label "Move Up">
<!ENTITY up.accesskey "U">
<!ENTITY dn.label "Move Down">
<!ENTITY dn.accesskey "D">
<!ENTITY remove.label "Remove">
<!ENTITY remove.accesskey "R">
<!ENTITY edit.label "Edit Keyword…">
<!ENTITY edit.accesskey "t">
<!ENTITY addEngine.label "Get more search engines…">
<!ENTITY addEngine.accesskey "A">
<!ENTITY enableSuggest.label "Show search suggestions">
<!ENTITY enableSuggest.accesskey "S">
<!ENTITY restoreDefaults.label "Restore Defaults">
<!ENTITY restoreDefaults.accesskey "e">

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

@ -0,0 +1,5 @@
editTitle=Edit Keyword
editMsg=Enter a new keyword for "%S":
duplicateTitle=Duplicate Keyword
duplicateEngineMsg=You have chosen a keyword that is currently in use by "%S". Please select another.
duplicateBookmarkMsg=You have chosen a keyword that is currently in use by a bookmark. Please select another.

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

@ -38,3 +38,5 @@
<!ENTITY search.button.label "Search">
<!ENTITY search.placeholder "Enter search text">
<!-- Will be used by bug 595246 -->
<!ENTITY search.engineManager.label "Manage Search Engines…">

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

@ -0,0 +1,14 @@
searchtip=Search using %S
# LOCALIZATION NOTE (cmd_pasteAndSearch): "Search" is a verb, this is the
# search bar equivalent to the url bar's "Paste & Go"
cmd_pasteAndSearch=Paste & Search
cmd_clearHistory=Clear Search History
cmd_clearHistory_accesskey=H
cmd_showSuggestions=Show Suggestions
cmd_showSuggestions_accesskey=S
cmd_addFoundEngine=Add "%S"

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

@ -0,0 +1,2 @@
<!ENTITY cmd_engineManager.label "Manage Search Engines…">
<!ENTITY searchEndCap.label "Search">

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

@ -3,7 +3,7 @@
<Description>Google Search</Description>
<InputEncoding>UTF-8</InputEncoding>
<Image width="16" height="16">data:image/png;base64,AAABAAEAEBAAAAEAGABoAwAAFgAAACgAAAAQAAAAIAAAAAEAGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADs9Pt8xetPtu9FsfFNtu%2BTzvb2%2B%2Fne4dFJeBw0egA%2FfAJAfAA8ewBBegAAAAD%2B%2FPtft98Mp%2BwWsfAVsvEbs%2FQeqvF8xO7%2F%2F%2F63yqkxdgM7gwE%2FggM%2BfQA%2BegBDeQDe7PIbotgQufcMufEPtfIPsvAbs%2FQvq%2Bfz%2Bf%2F%2B%2B%2FZKhR05hgBBhQI8hgBAgAI9ewD0%2B%2Fg3pswAtO8Cxf4Kw%2FsJvvYAqupKsNv%2B%2Fv7%2F%2FP5VkSU0iQA7jQA9hgBDgQU%2BfQH%2F%2Ff%2FQ6fM4sM4KsN8AteMCruIqqdbZ7PH8%2Fv%2Fg6Nc%2Fhg05kAA8jAM9iQI%2BhQA%2BgQDQu6b97uv%2F%2F%2F7V8Pqw3eiWz97q8%2Ff%2F%2F%2F%2F7%2FPptpkkqjQE4kwA7kAA5iwI8iAA8hQCOSSKdXjiyflbAkG7u2s%2F%2B%2F%2F39%2F%2F7r8utrqEYtjQE8lgA7kwA7kwA9jwA9igA9hACiWSekVRyeSgiYSBHx6N%2F%2B%2Fv7k7OFRmiYtlAA5lwI7lwI4lAA7kgI9jwE9iwI4iQCoVhWcTxCmb0K%2BooT8%2Fv%2F7%2F%2F%2FJ2r8fdwI1mwA3mQA3mgA8lAE8lAE4jwA9iwE%2BhwGfXifWvqz%2B%2Ff%2F58u%2Fev6Dt4tr%2B%2F%2F2ZuIUsggA7mgM6mAM3lgA5lgA6kQE%2FkwBChwHt4dv%2F%2F%2F728ei1bCi7VAC5XQ7kz7n%2F%2F%2F6bsZkgcB03lQA9lgM7kwA2iQktZToPK4r9%2F%2F%2F9%2F%2F%2FSqYK5UwDKZAS9WALIkFn%2B%2F%2F3%2F%2BP8oKccGGcIRJrERILYFEMwAAuEAAdX%2F%2Ff7%2F%2FP%2B%2BfDvGXQLIZgLEWgLOjlf7%2F%2F%2F%2F%2F%2F9QU90EAPQAAf8DAP0AAfMAAOUDAtr%2F%2F%2F%2F7%2B%2Fu2bCTIYwDPZgDBWQDSr4P%2F%2Fv%2F%2F%2FP5GRuABAPkAA%2FwBAfkDAPAAAesAAN%2F%2F%2B%2Fz%2F%2F%2F64g1C5VwDMYwK8Yg7y5tz8%2Fv%2FV1PYKDOcAAP0DAf4AAf0AAfYEAOwAAuAAAAD%2F%2FPvi28ymXyChTATRrIb8%2F%2F3v8fk6P8MAAdUCAvoAAP0CAP0AAfYAAO4AAACAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAQAA</Image>
<Url type="application/x-suggestions+json" method="GET" template="http://suggestqueries.google.com/complete/search?output=firefox&amp;client=seamonkey&amp;hl={moz:locale}&amp;q={searchTerms}"/>
<Url type="application/x-suggestions+json" method="GET" template="http://suggestqueries.google.com/complete/search?output=firefox&amp;client=firefox&amp;hl={moz:locale}&amp;q={searchTerms}"/>
<Url type="text/html" method="GET" template="http://www.google.com/search">
<Param name="q" value="{searchTerms}"/>
<Param name="ie" value="utf-8"/>

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

@ -186,6 +186,10 @@
locale/@AB_CD@/communicator-platform/win/pref/platformPrefOverlay.dtd (%chrome/common/pref/win/platformPrefOverlay.dtd)
locale/@AB_CD@/communicator/profile/profileSelection.dtd (%chrome/common/profile/profileSelection.dtd)
locale/@AB_CD@/communicator/profile/profileSelection.properties (%chrome/common/profile/profileSelection.properties)
locale/@AB_CD@/communicator/search/engineManager.dtd (%chrome/common/search/engineManager.dtd)
locale/@AB_CD@/communicator/search/engineManager.properties (%chrome/common/search/engineManager.properties)
locale/@AB_CD@/communicator/search/search.properties (%chrome/common/search/search.properties)
locale/@AB_CD@/communicator/search/searchbar.dtd (%chrome/common/search/searchbar.dtd)
locale/@AB_CD@/communicator/search/search-panel.dtd (%chrome/common/search/search-panel.dtd)
locale/@AB_CD@/communicator/sidebar/customize.dtd (%chrome/common/sidebar/customize.dtd)
locale/@AB_CD@/communicator/sidebar/preview.dtd (%chrome/common/sidebar/preview.dtd)

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

@ -0,0 +1,47 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is search engine manager code.
*
* The Initial Developer of the Original Code is
* Gavin Sharp.
* Portions created by the Initial Developer are Copyright (C) 2006
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Gavin Sharp <gavin@gavinsharp.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#engineChildren::-moz-tree-image(engineName) {
-moz-margin-end: 4px;
-moz-margin-start: 1px;
width: 16px;
height: 16px;
}
#engineChildren::-moz-tree-row {
height: 20px;
}

Двоичные данные
suite/themes/classic/communicator/search/mainwindow-dropdown-arrow.png Executable file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 509 B

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

@ -0,0 +1,68 @@
.searchbar-textbox {
width: 6em;
min-width: 6em;
}
.textbox-input-box {
margin: 0;
}
/* ::::: searchbar-engine-button ::::: */
.searchbar-engine-image {
height: 16px;
width: 16px;
list-style-image: url("chrome://global/skin/icons/folder-item.png");
-moz-image-region: rect(0px, 16px, 16px, 0px);
-moz-margin-start: 2px;
}
.searchbar-engine-button {
min-width: 0;
-moz-padding-end: 2px;
background-color: transparent;
}
.searchbar-dropmarker-image {
list-style-image: url("chrome://communicator/skin/search/mainwindow-dropdown-arrow.png");
-moz-image-region: rect(0, 13px, 11px, 0);
}
.searchbar-engine-button[open="true"] > .searchbar-dropmarker-image {
-moz-image-region: rect(0, 26px, 11px, 13px);
}
/* ::::: search-go-button ::::: */
.search-go-container {
-moz-box-align: center;
}
.search-go-button {
padding: 1px;
-moz-padding-end: 2px;
list-style-image: url("chrome://global/skin/icons/Search-glass.png");
-moz-image-region: rect(0px 16px 16px 0px);
}
.search-go-button:-moz-system-metric(touch-enabled) {
-moz-padding-start: 5px;
-moz-padding-end: 3px;
}
.search-go-button:-moz-locale-dir(rtl) {
-moz-transform: scaleX(-1);
}
.search-go-button:hover {
-moz-image-region: rect(0px 32px 16px 16px);
}
.search-go-button:hover:active {
-moz-image-region: rect(0px, 48px, 16px, 32px);
}
.searchbar-engine-menuitem[selected="true"] > .menu-iconic-text {
font-weight: bold;
}

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

@ -105,7 +105,10 @@ classic.jar:
skin/classic/communicator/profile/profile.css (communicator/profile/profile.css)
skin/classic/communicator/profile/profileManager.css (communicator/profile/profileManager.css)
skin/classic/communicator/profile/profileicon-large.gif (communicator/profile/profileicon-large.gif)
skin/classic/communicator/search/engineManager.css (communicator/search/engineManager.css)
skin/classic/communicator/search/mainwindow-dropdown-arrow.png (communicator/search/mainwindow-dropdown-arrow.png)
skin/classic/communicator/search/search.css (communicator/search/search.css)
skin/classic/communicator/search/searchbar.css (communicator/search/searchbar.css)
skin/classic/communicator/sidebar/sbtab-twisty.gif (communicator/sidebar/sbtab-twisty.gif)
skin/classic/communicator/sidebar/sbtab-twisty-open.gif (communicator/sidebar/sbtab-twisty-open.gif)
skin/classic/communicator/sidebar/customize.css (communicator/sidebar/customize.css)

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

@ -441,6 +441,10 @@ toolbar[mode="text"] > #window-controls > toolbarbutton > .toolbarbutton-icon {
-moz-margin-end: 4px;
}
.autocomplete-treebody::-moz-tree-cell-text(treecolAutoCompleteComment) {
color: GrayText;
}
/* ::::: searchbutton ::::: */
#search-button {
@ -455,6 +459,18 @@ toolbar[mode="icons"] #search-button > .button-box > .button-text {
display: none;
}
/* ::::: search bar ::::: */
.autocomplete-treebody::-moz-tree-cell-text(suggesthint, treecolAutoCompleteComment),
.autocomplete-treebody::-moz-tree-cell-text(suggestfirst, treecolAutoCompleteComment) {
color: GrayText;
font-size: smaller;
}
.autocomplete-treebody::-moz-tree-cell(suggesthint) {
border-top: 1px solid GrayText;
}
/* ::::: sidebar splitter ::::: */
#sidebar-splitter {

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

@ -476,6 +476,10 @@ panel[nomatch="true"] > .autocomplete-search-box {
-moz-margin-end: 4px;
}
.autocomplete-treebody::-moz-tree-cell-text(treecolAutoCompleteComment) {
color: GrayText;
}
/* ::::: go and searchbuttons ::::: */
#search-button,
@ -507,6 +511,18 @@ toolbar[mode="icons"] #search-button > .button-box > .button-text {
display: none;
}
/* ::::: search bar ::::: */
.autocomplete-treebody::-moz-tree-cell-text(suggesthint, treecolAutoCompleteComment),
.autocomplete-treebody::-moz-tree-cell-text(suggestfirst, treecolAutoCompleteComment) {
color: GrayText;
font-size: smaller;
}
.autocomplete-treebody::-moz-tree-cell(suggesthint) {
border-top: 1px solid GrayText;
}
/* ::::: sidebar splitter ::::: */
#sidebar-splitter {

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

@ -0,0 +1,47 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is search engine manager code.
*
* The Initial Developer of the Original Code is
* Gavin Sharp.
* Portions created by the Initial Developer are Copyright (C) 2006
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Gavin Sharp <gavin@gavinsharp.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#engineChildren::-moz-tree-image(engineName) {
-moz-margin-end: 4px;
-moz-margin-start: 1px;
width: 16px;
height: 16px;
}
#engineChildren::-moz-tree-row {
height: 20px;
}

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 576 B

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

@ -0,0 +1,62 @@
.searchbar-textbox {
width: 6em;
min-width: 6em;
}
.autocomplete-textbox-container {
-moz-box-align: stretch;
}
.textbox-input-box {
margin: 0;
}
/* ::::: searchbar-engine-button ::::: */
.searchbar-engine-image {
height: 16px;
width: 16px;
list-style-image: url("chrome://communicator/skin/directory/file-icon.gif");
-moz-margin-start: 2px;
}
.searchbar-engine-button {
min-width: 0;
-moz-padding-end: 2px;
-moz-box-align: center;
background: none;
}
.searchbar-dropmarker-image {
list-style-image: url("chrome://communicator/skin/search/mainwindow-dropdown-arrow.png");
-moz-image-region: rect(0, 13px, 11px, 0);
}
.searchbar-engine-button[open="true"] > .searchbar-dropmarker-image {
-moz-image-region: rect(0, 26px, 11px, 13px);
}
/* ::::: search-go-button ::::: */
.search-go-container {
-moz-box-align: center;
}
.search-go-button {
padding: 1px;
list-style-image: url("chrome://global/skin/icons/search.gif");
}
.search-go-button:-moz-system-metric(touch-enabled) {
-moz-padding-start: 5px;
-moz-padding-end: 3px;
}
.search-go-button:-moz-locale-dir(rtl) {
-moz-transform: scaleX(-1);
}
.searchbar-engine-menuitem[selected="true"] > .menu-iconic-text {
font-weight: bold;
}

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

@ -103,7 +103,10 @@ modern.jar:
skin/modern/communicator/profile/migrate.gif (communicator/profile/migrate.gif)
skin/modern/communicator/profile/profile.gif (communicator/profile/profile.gif)
skin/modern/communicator/profile/profile.css (communicator/profile/profile.css)
skin/modern/communicator/search/engineManager.css (communicator/search/engineManager.css)
skin/modern/communicator/search/mainwindow-dropdown-arrow.png (communicator/search/mainwindow-dropdown-arrow.png)
skin/modern/communicator/search/search.css (communicator/search/search.css)
skin/modern/communicator/search/searchbar.css (communicator/search/searchbar.css)
skin/modern/communicator/sidebar/sidebarBindings.xml (communicator/sidebar/sidebarBindings.xml)
skin/modern/communicator/sidebar/sbar-top.gif (communicator/sidebar/sbar-top.gif)
skin/modern/communicator/sidebar/sbar-top-tabopen.gif (communicator/sidebar/sbar-top-tabopen.gif)

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

@ -671,6 +671,10 @@ panel[nomatch="true"] > .autocomplete-search-box {
list-style-image: url("chrome://navigator/skin/toolbar/ubhist-arrow-act.gif");
}
.autocomplete-treebody::-moz-tree-cell-text(treecolAutoCompleteComment) {
color: #999999;
}
/* ::::: go and searchbuttons ::::: */
#go-button,
@ -688,6 +692,18 @@ panel[nomatch="true"] > .autocomplete-search-box {
list-style-image: url("chrome://global/skin/icons/search.gif");
}
/* ::::: search bar ::::: */
.autocomplete-treebody::-moz-tree-cell-text(suggesthint, treecolAutoCompleteComment),
.autocomplete-treebody::-moz-tree-cell-text(suggestfirst, treecolAutoCompleteComment) {
color: #999999;
font-size: smaller;
}
.autocomplete-treebody::-moz-tree-cell(suggesthint) {
border-top: 1px solid #999999;
}
/* ::::: navigator throbber ::::: */
#throbber-box {