mirror of
https://github.com/ManchildProductions/binoc-central-mirror.git
synced 2026-06-20 10:08:49 +00:00
277 lines
9.9 KiB
XML
277 lines
9.9 KiB
XML
<?xml version="1.0"?>
|
|
|
|
<!-- 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/. -->
|
|
|
|
<!DOCTYPE bindings [
|
|
<!ENTITY % messengerDTD SYSTEM "chrome://messenger/locale/messenger.dtd">
|
|
%messengerDTD;
|
|
]>
|
|
|
|
<bindings id="SearchBindings"
|
|
xmlns="http://www.mozilla.org/xbl"
|
|
xmlns:html="http://www.w3.org/1999/xhtml"
|
|
xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
|
xmlns:xbl="http://www.mozilla.org/xbl">
|
|
|
|
<!--
|
|
- The glodaSearch binding implements a gloda-backed search mechanism. The
|
|
- actual search logic comes from the glodaFacet tab mode in the
|
|
- glodaFacetTabType definition. This binding serves as a means to display
|
|
- and alter the current search query if a "glodaFacet" tab is displayed,
|
|
- or enter a search query and spawn a new "glodaFacet" tab if one is
|
|
- currently not displayed.
|
|
-
|
|
- This widget used to have many weird implementation nuances. Now we are
|
|
- just a little bit of extra stuff on top of the toolkit autocomplete
|
|
- implementation. Our deviations are:
|
|
- - We collapse ourselves when gloda is disabled; we track the state.
|
|
- -
|
|
-->
|
|
<binding id="glodaSearch"
|
|
extends="chrome://global/content/bindings/autocomplete.xml#autocomplete">
|
|
|
|
<handlers>
|
|
<handler event="drop" phase="capturing"><![CDATA[
|
|
nsDragAndDrop.drop(event, this.searchInputDNDObserver);
|
|
]]></handler>
|
|
|
|
<handler event="keypress" keycode="VK_RETURN"><![CDATA[
|
|
this.doSearch();
|
|
event.preventDefault();
|
|
event.stopPropagation();
|
|
]]></handler>
|
|
<handler event="keypress" keycode="VK_ESCAPE"><![CDATA[
|
|
this.clearSearch();
|
|
event.preventDefault();
|
|
event.stopPropagation();
|
|
]]></handler>
|
|
</handlers>
|
|
|
|
<implementation implements="nsIObserver">
|
|
<constructor><![CDATA[
|
|
const Cc = Components.classes;
|
|
const Ci = Components.interfaces;
|
|
const Cu = Components.utils;
|
|
Cu.import("resource:///modules/errUtils.js");
|
|
Cu.import("resource://gre/modules/Services.jsm");
|
|
Cu.import("resource://gre/modules/AppConstants.jsm");
|
|
|
|
try {
|
|
this.setAttribute(
|
|
"placeholder",
|
|
this.getAttribute("emptytextbase")
|
|
.replace("#1", this.getAttribute(
|
|
(AppConstants.platform == "macosx") ?
|
|
"keyLabelMac" : "keyLabelNonMac")));
|
|
|
|
Services.prefs.addObserver("mailnews.database.global.indexer.enabled",
|
|
this._prefObserver, false);
|
|
|
|
this.glodaCompleter =
|
|
Components.classes["@mozilla.org/autocomplete/search;1?name=gloda"]
|
|
.getService()
|
|
.wrappedJSObject;
|
|
Services.obs.addObserver(this, "autocomplete-did-enter-text", false);
|
|
|
|
this.glodaEnabled =
|
|
Services.prefs.getBoolPref("mailnews.database.global.indexer.enabled");
|
|
this.collapsed = !this.glodaEnabled;
|
|
|
|
// make sure we set our emptytext here from the get-go
|
|
if (this.hasAttribute("placeholder"))
|
|
this.placeholder = this.getAttribute("placeholder");
|
|
} catch (e) {
|
|
logException(e, true);
|
|
}
|
|
]]></constructor>
|
|
|
|
<destructor>
|
|
<![CDATA[
|
|
Components.utils.import("resource://gre/modules/Services.jsm");
|
|
|
|
Services.prefs.removeObserver("mailnews.database.global.indexer.enabled",
|
|
this._prefObserver);
|
|
Services.obs.removeObserver(this, "autocomplete-did-enter-text");
|
|
]]>
|
|
</destructor>
|
|
|
|
<field name="_prefObserver">({
|
|
inputSearch: this,
|
|
observe: function(subject, topic, data)
|
|
{
|
|
Components.utils.import("resource://gre/modules/Services.jsm");
|
|
|
|
if (topic == "nsPref:changed") {
|
|
subject.QueryInterface(Components.interfaces.nsIPrefBranch);
|
|
switch (data) {
|
|
case "mailnews.database.global.indexer.enabled":
|
|
this.inputSearch.glodaEnabled =
|
|
Services.prefs.getBoolPref(
|
|
"mailnews.database.global.indexer.enabled");
|
|
this.inputSearch.collapsed = !this.inputSearch.glodaEnabled;
|
|
break;
|
|
}
|
|
}
|
|
},
|
|
|
|
QueryInterface: function(aIID)
|
|
{
|
|
if (aIID.equals(Components.interfaces.nsIObserver) ||
|
|
aIID.equals(Components.interfaces.nsISupports))
|
|
return this;
|
|
throw Components.results.NS_NOINTERFACE;
|
|
}
|
|
});
|
|
</field>
|
|
<field name="glodaCompleter">null</field>
|
|
<property name="menupopup" readonly="true">
|
|
<getter><![CDATA[
|
|
return document.getAnonymousElementByAttribute(
|
|
this, 'anonid', 'quick-search-menupopup');
|
|
]]></getter>
|
|
</property>
|
|
|
|
<property name="state">
|
|
<getter><![CDATA[
|
|
return {
|
|
'string': this.value
|
|
};
|
|
]]></getter>
|
|
<setter><![CDATA[
|
|
this.value = val['string'];
|
|
]]></setter>
|
|
</property>
|
|
|
|
// DND Observer
|
|
<field name="searchInputDNDObserver" readonly="true"><![CDATA[
|
|
({
|
|
inputSearch: this,
|
|
|
|
onDrop: function (aEvent, aXferData, aDragSession) {
|
|
try {
|
|
if (aXferData.data) {
|
|
this.inputSearch.focus();
|
|
this.inputSearch.value = aXferData.data;
|
|
// XXX for some reason the input field is _cleared_ even though
|
|
// the search works.
|
|
this.inputSearch.doSearch();
|
|
}
|
|
} catch (e) {
|
|
logException(e);
|
|
}
|
|
},
|
|
|
|
getSupportedFlavours: function () {
|
|
var flavourSet = new FlavourSet();
|
|
flavourSet.appendFlavour("text/unicode");
|
|
return flavourSet;
|
|
}
|
|
})
|
|
]]></field>
|
|
|
|
<method name="observe">
|
|
<parameter name="aSubject"/>
|
|
<parameter name="aTopic"/>
|
|
<parameter name="aData"/>
|
|
<body><![CDATA[
|
|
try {
|
|
if (aTopic == "autocomplete-did-enter-text" && aSubject == this) {
|
|
let selectedIndex = this.popup.selectedIndex;
|
|
let curResult = this.glodaCompleter.curResult;
|
|
if (! curResult)
|
|
return; // autocomplete didn't even finish.
|
|
let row = curResult.getObjectAt(selectedIndex);
|
|
if (row == null)
|
|
return;
|
|
if (row.fullText) {
|
|
// The autocomplete-did-enter-text notification is synchronously
|
|
// generated by nsAutoCompleteController which will attempt to
|
|
// call ClosePopup after we return and then tell the searchbox
|
|
// about the text entered. Since doSearch may close the current
|
|
// tab (and thus destroy the XUL document that owns the popup and
|
|
// the input field), the search box may no longer have its XBL
|
|
// binding attached when we return and telling it about the
|
|
// entered text could fail.
|
|
// To avoid this, we defer the doSearch call to the next turn of
|
|
// the event loop by using setTimeout.
|
|
setTimeout(this.doSearch.bind(this), 0);
|
|
} else if (row.nounDef) {
|
|
let theQuery = Gloda.newQuery(Gloda.NOUN_MESSAGE);
|
|
if (row.nounDef.name == "tag") {
|
|
theQuery = theQuery.tags(row.item);
|
|
} else if (row.nounDef.name == "identity") {
|
|
theQuery = theQuery.involves(row.item);
|
|
}
|
|
theQuery.orderBy('-date');
|
|
document.getElementById("tabmail").openTab("glodaFacet", {
|
|
query: theQuery
|
|
});
|
|
}
|
|
}
|
|
} catch (e) {
|
|
logException(e);
|
|
}
|
|
]]></body>
|
|
</method>
|
|
|
|
<method name="doSearch">
|
|
<body><![CDATA[
|
|
Components.utils.import("resource://gre/modules/Services.jsm");
|
|
|
|
try {
|
|
if (this.value) {
|
|
let tabmail = document.getElementById("tabmail");
|
|
// If the current tab is a gloda search tab, reset the value
|
|
// to the initial search value. Otherwise, clear it. This
|
|
// is the value that 3is going to be saved with the current
|
|
// tab when we switch back to it next.
|
|
let searchString = this.value;
|
|
|
|
if (tabmail.currentTabInfo.mode.name == "glodaFacet") {
|
|
// we'd rather reuse the existing tab (and somehow do something
|
|
// smart with any preexisting facet choices, but that's a
|
|
// bit hard right now, so doing the cheap thing and closing
|
|
// this tab and starting over
|
|
tabmail.closeTab();
|
|
}
|
|
this.value = ''; // clear our value, to avoid persistence
|
|
let args = {
|
|
searcher: new GlodaMsgSearcher(null, searchString)
|
|
};
|
|
tabmail.openTab("glodaFacet", args);
|
|
}
|
|
} catch (e) {
|
|
logException(e);
|
|
}
|
|
]]>
|
|
</body>
|
|
</method>
|
|
<method name="clearSearch">
|
|
<body><![CDATA[
|
|
this.value = "";
|
|
]]></body>
|
|
</method>
|
|
</implementation>
|
|
</binding>
|
|
|
|
<binding id="searchBarDropMarker">
|
|
<resources>
|
|
<stylesheet src="chrome://messenger/skin/searchBox.css"/>
|
|
</resources>
|
|
<content popup="_child">
|
|
<children/>
|
|
<xul:stack flex="1">
|
|
<xul:hbox align="center">
|
|
<xul:image class="quick-search-button-image" xbl:inherits="src"/>
|
|
</xul:hbox>
|
|
<xul:hbox align="center">
|
|
<xul:image class="quick-search-button-dropmarker"/>
|
|
</xul:hbox>
|
|
</xul:stack>
|
|
</content>
|
|
</binding>
|
|
|
|
</bindings>
|