mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-09-27 10:57:34 +09:00
Issue #1258 - Part 1: Import mailnews, ldap, and mork from comm-esr52.9.1
This commit is contained in:
parent
23e0d82436
commit
e400f4130a
1564 changed files with 510348 additions and 0 deletions
94
mailnews/db/gloda/content/glodacomplete.css
Normal file
94
mailnews/db/gloda/content/glodacomplete.css
Normal file
|
|
@ -0,0 +1,94 @@
|
|||
/* 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/. */
|
||||
|
||||
textbox[type="glodacomplete"] {
|
||||
-moz-binding: url("chrome://global/content/bindings/autocomplete.xml#autocomplete");
|
||||
}
|
||||
|
||||
panel[type="glodacomplete-richlistbox"] {
|
||||
-moz-binding: url("chrome://gloda/content/glodacomplete.xml#glodacomplete-rich-result-popup");
|
||||
}
|
||||
|
||||
.autocomplete-richlistbox {
|
||||
-moz-binding: url("chrome://global/content/bindings/autocomplete.xml#autocomplete-richlistbox");
|
||||
-moz-user-focus: ignore;
|
||||
-moz-appearance: none;
|
||||
}
|
||||
|
||||
.autocomplete-richlistbox > scrollbox {
|
||||
overflow-x: hidden !important;
|
||||
}
|
||||
|
||||
.explanation, .gloda-single-identity {
|
||||
margin-inline-start: 1em;
|
||||
margin-top: 2px;
|
||||
margin-bottom: 2px;
|
||||
}
|
||||
|
||||
.ac-comment {
|
||||
font-size: 1.1em;
|
||||
margin-inline-start: 0;
|
||||
}
|
||||
|
||||
.ac-url-text {
|
||||
color: -moz-nativehyperlinktext;
|
||||
font-size: 0.95em;
|
||||
}
|
||||
|
||||
span.ac-emphasize-text {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.ac-url-text[selected="true"] {
|
||||
color: inherit !important;
|
||||
}
|
||||
|
||||
.gloda-single-identity[selected="true"] .ac-url{
|
||||
color: white;
|
||||
}
|
||||
|
||||
.parameters {
|
||||
font-style: italic;
|
||||
margin-inline-start: 1em;
|
||||
}
|
||||
|
||||
.autocomplete-richlistitem[type="gloda-single-tag"] {
|
||||
-moz-binding: url("chrome://gloda/content/glodacomplete.xml#gloda-single-tag-item");
|
||||
overflow: -moz-hidden-unscrollable;
|
||||
}
|
||||
|
||||
.autocomplete-richlistitem[type="gloda-single-identity"] {
|
||||
-moz-binding: url("chrome://gloda/content/glodacomplete.xml#gloda-single-identity-item");
|
||||
-moz-box-orient: vertical;
|
||||
overflow: -moz-hidden-unscrollable;
|
||||
}
|
||||
|
||||
.autocomplete-richlistitem[type="gloda-fulltext-single"] {
|
||||
-moz-binding: url("chrome://gloda/content/glodacomplete.xml#gloda-fulltext-single-item");
|
||||
overflow: -moz-hidden-unscrollable;
|
||||
}
|
||||
|
||||
.autocomplete-richlistitem[type="gloda-fulltext-any"] {
|
||||
-moz-binding: url("chrome://gloda/content/glodacomplete.xml#gloda-fulltext-any-item");
|
||||
overflow: -moz-hidden-unscrollable;
|
||||
}
|
||||
|
||||
.autocomplete-richlistitem[type="gloda-fulltext-all"] {
|
||||
-moz-binding: url("chrome://gloda/content/glodacomplete.xml#gloda-fulltext-all-item");
|
||||
overflow: -moz-hidden-unscrollable;
|
||||
}
|
||||
|
||||
richlistitem[type="gloda-contact-chunk"] {
|
||||
-moz-binding: url("chrome://gloda/content/glodacomplete.xml#gloda-contact-chunk");
|
||||
-moz-box-orient: vertical;
|
||||
overflow: -moz-hidden-unscrollable;
|
||||
}
|
||||
|
||||
.autocomplete-richlistitem[type="gloda-multi"] {
|
||||
-moz-binding: url("chrome://gloda/content/glodacomplete.xml#gloda-multi-item");
|
||||
-moz-box-orient: vertical;
|
||||
overflow: -moz-hidden-unscrollable;
|
||||
}
|
||||
|
||||
/* .autocomplete-history-dropmarker wants to be optional, but we don't care */
|
||||
644
mailnews/db/gloda/content/glodacomplete.xml
Normal file
644
mailnews/db/gloda/content/glodacomplete.xml
Normal file
|
|
@ -0,0 +1,644 @@
|
|||
<?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/. -->
|
||||
|
||||
<bindings id="autocompleteBindings"
|
||||
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">
|
||||
|
||||
<binding id="glodacomplete-rich-result-popup" extends="chrome://global/content/bindings/autocomplete.xml#autocomplete-rich-result-popup">
|
||||
<implementation implements="nsIAutoCompletePopup">
|
||||
<method name="_appendCurrentResult">
|
||||
<body>
|
||||
<![CDATA[
|
||||
var controller = this.mInput.controller;
|
||||
|
||||
// Process maxRows per chunk to improve performance and user experience
|
||||
for (let i = 0; i < this.maxRows; i++) {
|
||||
if (this._currentIndex >= this._matchCount)
|
||||
return;
|
||||
|
||||
var existingItemsCount = this.richlistbox.childNodes.length;
|
||||
var item;
|
||||
|
||||
// trim the leading/trailing whitespace
|
||||
var trimmedSearchString = controller.searchString.trim();
|
||||
|
||||
// Unescape the URI spec for showing as an entry in the popup
|
||||
let url = Components.classes["@mozilla.org/intl/texttosuburi;1"].
|
||||
getService(Components.interfaces.nsITextToSubURI).
|
||||
unEscapeURIForUI("UTF-8", controller.getValueAt(this._currentIndex));
|
||||
|
||||
// Unlike our superclass, we create nodes every time because we have
|
||||
// heterogeneous results and we cannot rely on the XBL bindings to
|
||||
// to change fast enough.
|
||||
item = document.createElementNS("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul", "richlistitem");
|
||||
|
||||
var glodaCompleter = Components.
|
||||
classes["@mozilla.org/autocomplete/search;1?name=gloda"].
|
||||
getService(). //Components.interfaces.nsIAutoCompleteSearch)
|
||||
wrappedJSObject;
|
||||
var result = glodaCompleter.curResult;
|
||||
|
||||
// set these attributes before we set the class
|
||||
// so that we can use them from the contructor
|
||||
var row = result.getObjectAt(this._currentIndex);
|
||||
var obj = row.item;
|
||||
item.setAttribute("text", trimmedSearchString);
|
||||
item.setAttribute("type", result.getStyleAt(this._currentIndex));
|
||||
|
||||
item.row = row;
|
||||
|
||||
// set the class at the end so we can use the attributes
|
||||
// in the xbl constructor
|
||||
item.className = "autocomplete-richlistitem";
|
||||
this.richlistbox.appendChild(item);
|
||||
|
||||
this._currentIndex++;
|
||||
}
|
||||
|
||||
// yield after each batch of items so that typing the url bar is responsive
|
||||
setTimeout(() => this._appendCurrentResult(), 0);
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
<method name="_invalidate">
|
||||
<body>
|
||||
<![CDATA[
|
||||
setTimeout(() => this.adjustHeight(), 0);
|
||||
|
||||
// remove all child nodes because we never want to reuse them.
|
||||
while (this.richlistbox.hasChildNodes())
|
||||
this.richlistbox.lastChild.remove();
|
||||
|
||||
this._currentIndex = 0;
|
||||
this._appendCurrentResult();
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
</implementation>
|
||||
</binding>
|
||||
|
||||
<!-- This is autocomplete.xml's autocomplete-richlistitem duplicated and
|
||||
modified to include its useful helper functions, but eliminating anything
|
||||
that assumes specific content sub-items. Namely, url/title/etc. -->
|
||||
<binding id="glodacomplete-base-richlistitem" extends="chrome://global/content/bindings/richlistbox.xml#richlistitem">
|
||||
<implementation implements="nsIDOMXULSelectControlItemElement">
|
||||
<field name="_boundaryCutoff">null</field>
|
||||
|
||||
<property name="boundaryCutoff" readonly="true">
|
||||
<getter>
|
||||
<![CDATA[
|
||||
if (!this._boundaryCutoff) {
|
||||
this._boundaryCutoff =
|
||||
Services.prefs
|
||||
.getIntPref("toolkit.autocomplete.richBoundaryCutoff");
|
||||
}
|
||||
return this._boundaryCutoff;
|
||||
]]>
|
||||
</getter>
|
||||
</property>
|
||||
|
||||
<method name="_getBoundaryIndices">
|
||||
<parameter name="aText"/>
|
||||
<parameter name="aSearchTokens"/>
|
||||
<body>
|
||||
<![CDATA[
|
||||
// Short circuit for empty search ([""] == "")
|
||||
if (aSearchTokens == "")
|
||||
return [0, aText.length];
|
||||
|
||||
// Find which regions of text match the search terms
|
||||
let regions = [];
|
||||
for (let search of aSearchTokens) {
|
||||
let matchIndex;
|
||||
let startIndex = 0;
|
||||
let searchLen = search.length;
|
||||
|
||||
// Find all matches of the search terms, but stop early for perf
|
||||
let lowerText = aText.toLowerCase().substr(0, this.boundaryCutoff);
|
||||
while ((matchIndex = lowerText.indexOf(search, startIndex)) >= 0) {
|
||||
// Start the next search from where this one finished
|
||||
startIndex = matchIndex + searchLen;
|
||||
regions.push([matchIndex, startIndex]);
|
||||
}
|
||||
}
|
||||
|
||||
// Sort the regions by start position then end position
|
||||
regions = regions.sort(function(a, b) {
|
||||
let start = a[0] - b[0];
|
||||
return (start == 0) ? a[1] - b[1] : start;
|
||||
});
|
||||
|
||||
// Generate the boundary indices from each region
|
||||
let start = 0;
|
||||
let end = 0;
|
||||
let boundaries = [];
|
||||
let len = regions.length;
|
||||
for (let i = 0; i < len; i++) {
|
||||
// We have a new boundary if the start of the next is past the end
|
||||
let region = regions[i];
|
||||
if (region[0] > end) {
|
||||
// First index is the beginning of match
|
||||
boundaries.push(start);
|
||||
// Second index is the beginning of non-match
|
||||
boundaries.push(end);
|
||||
|
||||
// Track the new region now that we've stored the previous one
|
||||
start = region[0];
|
||||
}
|
||||
|
||||
// Push back the end index for the current or new region
|
||||
end = Math.max(end, region[1]);
|
||||
}
|
||||
|
||||
// Add the last region
|
||||
boundaries.push(start);
|
||||
boundaries.push(end);
|
||||
|
||||
// Put on the end boundary if necessary
|
||||
if (end < aText.length)
|
||||
boundaries.push(aText.length);
|
||||
|
||||
// Skip the first item because it's always 0
|
||||
return boundaries.slice(1);
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<method name="_getSearchTokens">
|
||||
<parameter name="aSearch"/>
|
||||
<body>
|
||||
<![CDATA[
|
||||
let search = aSearch.toLowerCase();
|
||||
return search.split(/\s+/);
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<method name="_needsAlternateEmphasis">
|
||||
<parameter name="aText"/>
|
||||
<body>
|
||||
<![CDATA[
|
||||
for (let i = aText.length; --i >= 0; ) {
|
||||
let charCode = aText.charCodeAt(i);
|
||||
// Arabic, Syriac, Indic languages are likely to have ligatures
|
||||
// that are broken when using the main emphasis styling
|
||||
if (0x0600 <= charCode && charCode <= 0x109F)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<method name="_setUpDescription">
|
||||
<parameter name="aDescriptionElement"/>
|
||||
<parameter name="aText"/>
|
||||
<body>
|
||||
<![CDATA[
|
||||
// Get rid of all previous text
|
||||
while (aDescriptionElement.hasChildNodes())
|
||||
aDescriptionElement.lastChild.remove();
|
||||
|
||||
// Get the indices that separate match and non-match text
|
||||
let search = this.getAttribute("text");
|
||||
let tokens = this._getSearchTokens(search);
|
||||
let indices = this._getBoundaryIndices(aText, tokens);
|
||||
|
||||
// If we're searching for something that needs alternate emphasis,
|
||||
// we'll need to check the text that we match
|
||||
let checkAlt = this._needsAlternateEmphasis(search);
|
||||
|
||||
let next;
|
||||
let start = 0;
|
||||
let len = indices.length;
|
||||
// Even indexed boundaries are matches, so skip the 0th if it's empty
|
||||
for (let i = indices[0] == 0 ? 1 : 0; i < len; i++) {
|
||||
next = indices[i];
|
||||
let text = aText.substr(start, next - start);
|
||||
start = next;
|
||||
|
||||
if (i % 2 == 0) {
|
||||
// Emphasize the text for even indices
|
||||
let span = aDescriptionElement.appendChild(
|
||||
document.createElementNS("http://www.w3.org/1999/xhtml", "span"));
|
||||
span.className = checkAlt && this._needsAlternateEmphasis(text) ?
|
||||
"ac-emphasize-alt" : "ac-emphasize-text";
|
||||
span.textContent = text;
|
||||
} else {
|
||||
// Otherwise, it's plain text
|
||||
aDescriptionElement.appendChild(document.createTextNode(text));
|
||||
}
|
||||
}
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<method name="_setUpOverflow">
|
||||
<parameter name="aParentBox"/>
|
||||
<parameter name="aEllipsis"/>
|
||||
<body>
|
||||
<![CDATA[
|
||||
// Hide the ellipsis incase there's just enough to not underflow
|
||||
aEllipsis.hidden = true;
|
||||
|
||||
// Start with the parent's width and subtract off its children
|
||||
let tooltip = [];
|
||||
let children = aParentBox.childNodes;
|
||||
let widthDiff = aParentBox.boxObject.width;
|
||||
|
||||
for (let i = 0; i < children.length; i++) {
|
||||
// Only consider a child if it actually takes up space
|
||||
let childWidth = children[i].boxObject.width;
|
||||
if (childWidth > 0) {
|
||||
// Subtract a little less to account for subpixel rounding
|
||||
widthDiff -= childWidth - .5;
|
||||
|
||||
// Add to the tooltip if it's not hidden and has text
|
||||
let childText = children[i].textContent;
|
||||
if (childText)
|
||||
tooltip.push(childText);
|
||||
}
|
||||
}
|
||||
|
||||
// If the children take up more space than the parent.. overflow!
|
||||
if (widthDiff < 0) {
|
||||
// Re-show the ellipsis now that we know it's needed
|
||||
aEllipsis.hidden = false;
|
||||
|
||||
// Separate text components with a ndash --
|
||||
aParentBox.tooltipText = tooltip.join(" \u2013 ");
|
||||
}
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<method name="_doUnderflow">
|
||||
<parameter name="aName"/>
|
||||
<body>
|
||||
<![CDATA[
|
||||
// Hide the ellipsis right when we know we're underflowing instead of
|
||||
// waiting for the timeout to trigger the _setUpOverflow calculations
|
||||
this[aName + "Box"].tooltipText = "";
|
||||
this[aName + "OverflowEllipsis"].hidden = true;
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
|
||||
</implementation>
|
||||
</binding>
|
||||
|
||||
<binding id="gloda-single-tag-item" extends="chrome://gloda/content/glodacomplete.xml#glodacomplete-base-richlistitem">
|
||||
<content orient="vertical">
|
||||
<xul:description anonid="explanation" class="explanation gloda-single"/>
|
||||
</content>
|
||||
<implementation implements="nsIDOMXULSelectControlItemElement">
|
||||
<constructor>
|
||||
<![CDATA[
|
||||
this._explanation = document.getAnonymousElementByAttribute(this, "anonid", "explanation");
|
||||
|
||||
this._adjustAcItem();
|
||||
]]>
|
||||
</constructor>
|
||||
|
||||
<property name="label" readonly="true">
|
||||
<getter>
|
||||
<![CDATA[
|
||||
return "tag " + this.row.item.tag;
|
||||
]]>
|
||||
</getter>
|
||||
</property>
|
||||
|
||||
<method name="_adjustAcItem">
|
||||
<body>
|
||||
<![CDATA[
|
||||
let label = gGlodaCompleteStrings.get("glodaComplete.messagesTagged.label");
|
||||
this._explanation.value = label.replace("#1", this.row.item.tag);
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
</implementation>
|
||||
</binding>
|
||||
|
||||
|
||||
<binding id="gloda-fulltext-single-item" extends="chrome://gloda/content/glodacomplete.xml#glodacomplete-base-richlistitem">
|
||||
<content orient="vertical">
|
||||
<xul:description anonid="explanation" class="explanation gloda-fulltext-single"/>
|
||||
<xul:description anonid="parameters"/>
|
||||
</content>
|
||||
<implementation implements="nsIDOMXULSelectControlItemElement">
|
||||
<constructor>
|
||||
<![CDATA[
|
||||
this._explanation = document.getAnonymousElementByAttribute(this, "anonid", "explanation");
|
||||
|
||||
this._adjustAcItem();
|
||||
]]>
|
||||
</constructor>
|
||||
|
||||
<property name="label" readonly="true">
|
||||
<getter>
|
||||
<![CDATA[
|
||||
return "full text search: " + this.row.item;
|
||||
]]>
|
||||
</getter>
|
||||
</property>
|
||||
|
||||
<method name="_adjustAcItem">
|
||||
<body>
|
||||
<![CDATA[
|
||||
let label = gGlodaCompleteStrings.get("glodaComplete.messagesMentioning.label");
|
||||
this._explanation.value = label.replace("#1", this.row.item);
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
</implementation>
|
||||
</binding>
|
||||
|
||||
<binding id="gloda-fulltext-all-item" extends="chrome://gloda/content/glodacomplete.xml#glodacomplete-base-richlistitem">
|
||||
<content orient="vertical">
|
||||
<xul:description anonid="explanation" class="explanation"/>
|
||||
</content>
|
||||
<implementation implements="nsIDOMXULSelectControlItemElement">
|
||||
<constructor>
|
||||
<![CDATA[
|
||||
this._explanation = document.getAnonymousElementByAttribute(this, "anonid", "explanation");
|
||||
this._adjustAcItem();
|
||||
]]>
|
||||
</constructor>
|
||||
|
||||
<property name="label" readonly="true">
|
||||
<getter>
|
||||
<![CDATA[
|
||||
return "full text search: " + this.row.item; // what is this for? l10n?
|
||||
]]>
|
||||
</getter>
|
||||
</property>
|
||||
|
||||
<method name="_adjustAcItem">
|
||||
<body>
|
||||
<![CDATA[
|
||||
let label = gGlodaCompleteStrings.get("glodaComplete.messagesMentioningMany.label");
|
||||
this._explanation.value = label.replace("#1", this.row.words.join(", "));
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
</implementation>
|
||||
</binding>
|
||||
|
||||
<binding id="gloda-single-identity-item" extends="chrome://gloda/content/glodacomplete.xml#glodacomplete-base-richlistitem">
|
||||
<content>
|
||||
<xul:hbox class="gloda-single-identity">
|
||||
<xul:image anonid="picture" class="picture"/>
|
||||
<xul:vbox>
|
||||
<xul:hbox>
|
||||
<xul:hbox anonid="name-box" class="ac-title" flex="1"
|
||||
onunderflow="_doUnderflow('_name');">
|
||||
<xul:description anonid="name" class="ac-normal-text ac-comment"
|
||||
xbl:inherits="selected"/>
|
||||
</xul:hbox>
|
||||
<xul:label anonid="name-overflow-ellipsis" xbl:inherits="selected"
|
||||
class="ac-ellipsis-after ac-comment" hidden="true"/>
|
||||
</xul:hbox>
|
||||
<xul:hbox>
|
||||
<xul:hbox anonid="identity-box" class="ac-url" flex="1"
|
||||
onunderflow="_doUnderflow('_identity');">
|
||||
<xul:description anonid="identity" class="ac-normal-text ac-url-text"
|
||||
xbl:inherits="selected"/>
|
||||
</xul:hbox>
|
||||
<xul:label anonid="identity-overflow-ellipsis" xbl:inherits="selected"
|
||||
class="ac-ellipsis-after ac-url-text" hidden="true"/>
|
||||
<xul:image anonid="type-image" class="ac-type-icon"/>
|
||||
</xul:hbox>
|
||||
</xul:vbox>
|
||||
</xul:hbox>
|
||||
</content>
|
||||
<implementation implements="nsIDOMXULSelectControlItemElement">
|
||||
<constructor>
|
||||
<![CDATA[
|
||||
let ellipsis = "\u2026";
|
||||
try {
|
||||
ellipsis = Services.prefs.getComplexValue("intl.ellipsis",
|
||||
Components.interfaces.nsIPrefLocalizedString).data;
|
||||
} catch (ex) {
|
||||
// Do nothing.. we already have a default
|
||||
}
|
||||
|
||||
this._identityOverflowEllipsis = document.getAnonymousElementByAttribute(this, "anonid", "identity-overflow-ellipsis");
|
||||
this._nameOverflowEllipsis = document.getAnonymousElementByAttribute(this, "anonid", "name-overflow-ellipsis");
|
||||
|
||||
this._identityOverflowEllipsis.value = ellipsis;
|
||||
this._nameOverflowEllipsis.value = ellipsis;
|
||||
|
||||
this._typeImage = document.getAnonymousElementByAttribute(this, "anonid", "type-image");
|
||||
|
||||
this._identityBox = document.getAnonymousElementByAttribute(this, "anonid", "identity-box");
|
||||
this._identity = document.getAnonymousElementByAttribute(this, "anonid", "identity");
|
||||
|
||||
this._nameBox = document.getAnonymousElementByAttribute(this, "anonid", "name-box");
|
||||
this._name = document.getAnonymousElementByAttribute(this, "anonid", "name");
|
||||
|
||||
this._picture = document.getAnonymousElementByAttribute(this, "anonid", "picture");
|
||||
|
||||
this._adjustAcItem();
|
||||
]]>
|
||||
</constructor>
|
||||
|
||||
<property name="label" readonly="true">
|
||||
<getter>
|
||||
<![CDATA[
|
||||
var identity = this.row.item;
|
||||
return identity.accessibleLabel;
|
||||
]]>
|
||||
</getter>
|
||||
</property>
|
||||
|
||||
<method name="_adjustAcItem">
|
||||
<body>
|
||||
<![CDATA[
|
||||
var identity = this.row.item;
|
||||
|
||||
if (identity == null)
|
||||
return;
|
||||
|
||||
// I guess we should get the picture size from CSS or something?
|
||||
this._picture.src = identity.pictureURL(32);
|
||||
|
||||
// Emphasize the matching search terms for the description
|
||||
this._setUpDescription(this._name, identity.contact.name);
|
||||
this._setUpDescription(this._identity, identity.value);
|
||||
|
||||
// Set up overflow on a timeout because the contents of the box
|
||||
// might not have a width yet even though we just changed them
|
||||
setTimeout(this._setUpOverflow, 0, this._nameBox, this._nameOverflowEllipsis);
|
||||
setTimeout(this._setUpOverflow, 0, this._identityBox, this._identityOverflowEllipsis);
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
</implementation>
|
||||
</binding>
|
||||
|
||||
<binding id="gloda-contact-chunk" extends="chrome://gloda/content/glodacomplete.xml#glodacomplete-base-richlistitem">
|
||||
<content orient="horizontal">
|
||||
<xul:image anonid="picture"/>
|
||||
<xul:vbox>
|
||||
<xul:hbox>
|
||||
<xul:hbox anonid="name-box" class="ac-title" flex="1"
|
||||
onunderflow="_doUnderflow('_name');">
|
||||
<xul:description anonid="name" class="ac-normal-text ac-comment"
|
||||
xbl:inherits="selected"/>
|
||||
</xul:hbox>
|
||||
<xul:label anonid="name-overflow-ellipsis" xbl:inherits="selected"
|
||||
class="ac-ellipsis-after ac-comment" hidden="true"/>
|
||||
</xul:hbox>
|
||||
<xul:hbox>
|
||||
<xul:hbox anonid="identity-box" class="ac-url" flex="1"
|
||||
onunderflow="_doUnderflow('_identity');">
|
||||
<xul:description anonid="identity" class="ac-normal-text ac-url-text"
|
||||
xbl:inherits="selected"/>
|
||||
</xul:hbox>
|
||||
<xul:label anonid="identity-overflow-ellipsis" xbl:inherits="selected"
|
||||
class="ac-ellipsis-after ac-url-text" hidden="true"/>
|
||||
<xul:image anonid="type-image" class="ac-type-icon"/>
|
||||
</xul:hbox>
|
||||
</xul:vbox>
|
||||
</content>
|
||||
<implementation>
|
||||
<constructor>
|
||||
<![CDATA[
|
||||
let ellipsis = "\u2026";
|
||||
try {
|
||||
ellipsis = Services.prefs.getComplexValue("intl.ellipsis",
|
||||
Components.interfaces.nsIPrefLocalizedString).data;
|
||||
} catch (ex) {
|
||||
// Do nothing.. we already have a default
|
||||
}
|
||||
|
||||
this._identityOverflowEllipsis = document.getAnonymousElementByAttribute(this, "anonid", "identity-overflow-ellipsis");
|
||||
this._nameOverflowEllipsis = document.getAnonymousElementByAttribute(this, "anonid", "name-overflow-ellipsis");
|
||||
|
||||
this._identityOverflowEllipsis.value = ellipsis;
|
||||
this._nameOverflowEllipsis.value = ellipsis;
|
||||
|
||||
this._typeImage = document.getAnonymousElementByAttribute(this, "anonid", "type-image");
|
||||
|
||||
this._identityBox = document.getAnonymousElementByAttribute(this, "anonid", "identity-box");
|
||||
this._identity = document.getAnonymousElementByAttribute(this, "anonid", "identity");
|
||||
|
||||
this._nameBox = document.getAnonymousElementByAttribute(this, "anonid", "name-box");
|
||||
this._name = document.getAnonymousElementByAttribute(this, "anonid", "name");
|
||||
|
||||
this._picture = document.getAnonymousElementByAttribute(this, "anonid", "picture");
|
||||
|
||||
this._adjustAcItem();
|
||||
]]>
|
||||
</constructor>
|
||||
|
||||
<property name="label" readonly="true">
|
||||
<getter>
|
||||
<![CDATA[
|
||||
var identity = this.obj;
|
||||
return identity.accessibleLabel;
|
||||
]]>
|
||||
</getter>
|
||||
</property>
|
||||
|
||||
<method name="_adjustAcItem">
|
||||
<body>
|
||||
<![CDATA[
|
||||
var contact = this.obj;
|
||||
|
||||
if (contact == null)
|
||||
return;
|
||||
|
||||
var identity = contact.identities[0];
|
||||
|
||||
// I guess we should get the picture size from CSS or something?
|
||||
this._picture.src = identity.pictureURL(32);
|
||||
|
||||
// Emphasize the matching search terms for the description
|
||||
this._setUpDescription(this._name, contact.name);
|
||||
this._setUpDescription(this._identity, identity.value);
|
||||
|
||||
// Set up overflow on a timeout because the contents of the box
|
||||
// might not have a width yet even though we just changed them
|
||||
setTimeout(this._setUpOverflow, 0, this._nameBox, this._nameOverflowEllipsis);
|
||||
setTimeout(this._setUpOverflow, 0, this._identityBox, this._identityOverflowEllipsis);
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
</implementation>
|
||||
</binding>
|
||||
|
||||
<binding id="gloda-multi-item" extends="chrome://gloda/content/glodacomplete.xml#glodacomplete-base-richlistitem">
|
||||
<content orient="vertical">
|
||||
<xul:description anonid="explanation"/>
|
||||
<xul:hbox anonid="identity-holder" flex="1">
|
||||
</xul:hbox>
|
||||
</content>
|
||||
<implementation implements="nsIDOMXULSelectControlItemElement">
|
||||
<constructor>
|
||||
<![CDATA[
|
||||
this._explanation = document.getAnonymousElementByAttribute(this, "anonid", "explanation");
|
||||
this._identityHolder = document.getAnonymousElementByAttribute(this, "anonid", "identity-holder");
|
||||
|
||||
this._adjustAcItem();
|
||||
]]>
|
||||
</constructor>
|
||||
|
||||
<property name="label" readonly="true">
|
||||
<getter>
|
||||
<![CDATA[
|
||||
return this._explanation.value;
|
||||
]]>
|
||||
</getter>
|
||||
</property>
|
||||
|
||||
<method name="renderItem">
|
||||
<parameter name="aObj"/>
|
||||
<body>
|
||||
var node = document.createElementNS(
|
||||
"http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul",
|
||||
"richlistitem");
|
||||
|
||||
node.obj = aObj;
|
||||
node.setAttribute("type",
|
||||
"gloda-" + this.row.nounDef.name + "-chunk");
|
||||
|
||||
this._identityHolder.appendChild(node);
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<method name="_adjustAcItem">
|
||||
<body>
|
||||
<![CDATA[
|
||||
// clear out any lingering children
|
||||
while (this._identityHolder.hasChildNodes())
|
||||
this._identityHolder.lastChild.remove();
|
||||
|
||||
var row = this.row;
|
||||
if (row == null)
|
||||
return;
|
||||
|
||||
this._explanation.value = row.nounDef.name + "s " +
|
||||
row.criteriaType + "ed " + row.criteria;
|
||||
|
||||
// render anyone already in there
|
||||
for (let item of row.collection.items) {
|
||||
this.renderItem(item);
|
||||
}
|
||||
// listen up, yo.
|
||||
row.renderer = this;
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
</implementation>
|
||||
</binding>
|
||||
|
||||
|
||||
</bindings>
|
||||
6
mailnews/db/gloda/content/overlay.js
Normal file
6
mailnews/db/gloda/content/overlay.js
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
/* 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/. */
|
||||
|
||||
// get the core
|
||||
Components.utils.import("resource:///modules/gloda/public.js");
|
||||
9
mailnews/db/gloda/content/thunderbirdOverlay.xul
Normal file
9
mailnews/db/gloda/content/thunderbirdOverlay.xul
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- 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/. -->
|
||||
|
||||
<overlay id="gloda-overlay"
|
||||
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
||||
<script type="application/javascript" src="chrome://gloda/content/overlay.js"/>
|
||||
</overlay>
|
||||
Loading…
Add table
Add a link
Reference in a new issue