Bug #244325 --> Port new quick search from the aviary branch to the trunk

This commit is contained in:
scott%scott-macgregor.org 2004-06-29 07:22:18 +00:00
Родитель d135597d46
Коммит f41c4e0fbd
18 изменённых файлов: 989 добавлений и 51 удалений

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

@ -400,7 +400,6 @@ function SwitchView(command)
function SetSentFolderColumns(isSentFolder)
{
var tree = GetThreadTree();
var searchCriteria = document.getElementById("searchCriteria");
var lastFolderSent = tree.getAttribute("lastfoldersent") == "true";
if (isSentFolder != lastFolderSent)
@ -418,15 +417,9 @@ function SetSentFolderColumns(isSentFolder)
}
if(isSentFolder)
{
tree.setAttribute("lastfoldersent", "true");
searchCriteria.setAttribute("value", gMessengerBundle.getString("recipientSearchCriteria"));
}
else
{
tree.setAttribute("lastfoldersent", "false");
searchCriteria.setAttribute("value", gMessengerBundle.getString("senderSearchCriteria"));
}
}
function SetNewsFolderColumns()
@ -802,8 +795,6 @@ function FolderPaneSelectionChange()
UpdateMailToolbar("gAccountCentralLoaded");
else if (gFakeAccountPageLoaded)
UpdateMailToolbar("gFakeAccountPageLoaded");
else
document.getElementById('advancedButton').setAttribute("disabled" , !(IsCanSearchMessagesEnabled()));
if (gDisplayStartupPage)
{

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

@ -2062,6 +2062,14 @@ function ClearPendingReadTimer()
}
}
// this is called when layout is actually finished rendering a
// mail message. OnMsgLoaded is called when libmime is done parsing the message
function OnMsgParsed(aUrl)
{
if ("onQuickSearchNewMsgLoaded" in this)
onQuickSearchNewMsgLoaded();
}
function OnMsgLoaded(aUrl)
{
if (!aUrl)

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

@ -1805,13 +1805,29 @@
<menuitem id="createCustomView" value="7" label="&viewPickerCustomView.label;"/>
</menupopup>
</menulist>
<label id="searchCriteria" value="&SearchSubjectOrSender.label;" control="searchInput"
accesskey="&SearchSubjectOrSender.accesskey;"/>
<textbox id="searchInput" flex="5" onfocus="this.select();" onclick="this.select();" oninput="onSearchInput(false);" onkeypress="onSearchKeyPress(event);"/>
<spring flex="4"/>
<textbox id="searchInput" flex="1" onfocus="onSearchInputFocus(event);" onblur="onSearchInputBlur(event);" onclick="this.select();" oninput="onSearchInput(false);" onkeypress="onSearchKeyPress(event);">
<button id="search-button" type="menu">
<menupopup id="quick-search-menupopup" value="2" persist="value" popupalign="topleft" popupanchor="bottomleft">
<menuitem value="0" label="&searchSubjectMenu.label;" type="radio"
oncommand="changeQuickSearchMode(this)"/>
<menuitem value="1" label="&searchSenderMenu.label;" type="radio"
oncommand="changeQuickSearchMode(this)" />
<menuitem value="2" label="&searchSubjectOrSenderMenu.label;" type="radio"
checked="true" oncommand="changeQuickSearchMode(this)"/>
<menuitem value="3" label="&searchMessageBody.label;" type="radio"
oncommand="changeQuickSearchMode(this)"/>
<menuseparator/>
<menuitem value="4" label="&findInMessageMenu.label;" type="radio"
oncommand="changeQuickSearchMode(this)"/>
</menupopup>
</button>
</textbox>
<button id="clearButton" label="&clearButton.label;" disabled="true" tooltiptext="&clearButton.tooltip;" oncommand="onClearSearch();"
accesskey="&clearButton.accesskey;"/>
<button id="advancedButton" label="&advancedButton.label;" tooltiptext="&advancedButton.tooltip;" oncommand="onAdvancedSearch();"
accesskey="&advancedButton.accesskey;" hidden="true"/>
accesskey="&clearButton.accesskey;" hidden="true"/>
</hbox>
<hbox id="junkBar" collapsed="true" align="center">

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

@ -0,0 +1,92 @@
/*
* The contents of this file are subject to the Netscape 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/NPL/
*
* 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 Communicator client code, released
* March 31, 1998.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998-1999 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*
*/
/* ===== messenger.css ==================================================
== Content specific styles for Messenger.
======================================================================= */
@namespace url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul");
/* ::::: mail xbl bindings ::::: */
description[selectable="true"] {
-moz-binding: url("chrome://messenger/content/mailWidgets.xml#extdescription");
}
descriptionitem {
-moz-binding: url("chrome://messenger/content/mailWidgets.xml#descriptionitem");
}
.descriptionitem-iconic {
-moz-binding: url("chrome://messenger/content/mailWidgets.xml#descriptionitem-iconic");
}
mail-emailaddress {
-moz-binding: url("chrome://messenger/content/mailWidgets.xml#mail-emailaddress");
}
mail-emailheaderfield {
-moz-binding: url("chrome://messenger/content/mailWidgets.xml#mail-emailheaderfield");
}
mail-toggle-headerfield {
-moz-binding: url("chrome://messenger/content/mailWidgets.xml#mail-toggle-headerfield");
}
mail-multi-emailHeaderField {
-moz-binding: url("chrome://messenger/content/mailWidgets.xml#mail-multi-emailHeaderField");
}
mail-headerfield {
-moz-binding: url("chrome://messenger/content/mailWidgets.xml#mail-headerfield");
}
searchattribute {
-moz-binding: url("chrome://messenger/content/mailWidgets.xml#searchattribute");
}
searchoperator {
-moz-binding: url("chrome://messenger/content/mailWidgets.xml#searchoperator");
}
searchvalue {
display: -moz-deck;
-moz-binding: url("chrome://messenger/content/mailWidgets.xml#searchvalue");
}
searchterm {
-moz-binding: url("chrome://messenger/content/mailWidgets.xml#searchterm");
}
dummy.usesMailWidgets {
-moz-binding: url("chrome://messenger/content/mailWidgets.xml#dummy");
}
#searchInput {
-moz-binding: url("chrome://messenger/content/search.xml#searchbar");
}
#search-button {
-moz-binding: url("chrome://messenger/content/search.xml#searchBarDropMarker");
cursor: default;
}

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

@ -429,6 +429,7 @@ var messageHeaderSink = {
onEndMsgDownload: function(url)
{
OnMsgParsed(url);
},
onEndMsgHeaders: function(url)

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

@ -695,6 +695,7 @@ function OnLoadMessenger()
// update the pane config before we exit onload otherwise the user may see a flicker if we poke the document
// in delayedOnLoadMessenger...
UpdateMailPaneConfig(false);
document.loadBindingDocument('chrome://global/content/bindings/textbox.xml');
// Set a sane starting width/height for all resolutions on new profiles. Do this before the window loads
if (!document.documentElement.hasAttribute("width"))

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

@ -0,0 +1,97 @@
<?xml version="1.0"?>
# -*- Mode: HTML -*-
# ***** 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 Communicator client code, released
# March 31, 1998.
#
# The Initial Developer of the Original Code is
# Netscape Communications Corporation.
# Portions created by the Initial Developer are Copyright (C) 1998-1999
# the Initial Developer. All Rights Reserved.
#
# Contributor(s):
# Scott MacGregor <mscott@mozilla.org>
#
# Alternatively, the contents of this file may be used under the terms of
# either of 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 *****
<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">
<binding id="searchbar" extends="chrome://global/content/bindings/textbox.xml#textbox">
<content>
<children/>
<xul:hbox class="textbox-input-box" flex="1">
<html:input class="textbox-input" flex="1" anonid="input" allowevents="true"
xbl:inherits="onfocus,onblur,value,type,maxlength,disabled,size,readonly,tabindex,accesskey"/>
</xul:hbox>
</content>
<implementation>
<constructor><![CDATA[
// initialize the quick search mode based on the checked menu item
var selectedMenuItemVal = document.getElementById('quick-search-menupopup').getAttribute('value');
var menuItems = document.getElementById('quick-search-menupopup').getElementsByAttribute('value', selectedMenuItemVal);
this.mQuickSearchMode = menuItems[0].value; // the checked menu item
this.setSearchCriteriaText();
]]></constructor>
<property name="showingSearchCriteria" onget="return this.getAttribute('searchCriteria') == 'true';"
onset="this.setAttribute('searchCriteria', val); return val;"/>
<field name="mQuickSearchMode">0</field>
<property name="searchMode" onget="return this.mQuickSearchMode;"
onset="this.mQuickSearchMode = val; document.getElementById('quick-search-menupopup').setAttribute('value', val);"/>
<method name="setSearchCriteriaText">
<body><![CDATA[
this.showingSearchCriteria = true;
// extract the label value from the menu item
var menuItems = document.getElementById('quick-search-menupopup').getElementsByAttribute('value', this.searchMode);
this.inputField.value = menuItems[0].getAttribute('label');
]]></body>
</method>
</implementation>
</binding>
<binding id="searchBarDropMarker">
<content xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
xmlns:xbl="http://www.mozilla.org/xbl" popup="_child">
<children/>
<xul:stack flex="1">
<xul:hbox align="center">
<xul:image class="search-button-image" xbl:inherits="src"/>
</xul:hbox>
<xul:image class="search-button-dropmarker"/>
</xul:stack>
</content>
</binding>
</bindings>

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

@ -0,0 +1,688 @@
# -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
# ***** 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 Communicator client code, released
# March 31, 1998.
#
# The Initial Developer of the Original Code is
# Netscape Communications Corporation.
# Portions created by the Initial Developer are Copyright (C) 1998-1999
# the Initial Developer. All Rights Reserved.
#
# Contributor(s):
# Seth Spitzer <sspitzer@netscape.com>
# Scott MacGregor <mscott@mozilla.org>
#
# Alternatively, the contents of this file may be used under the terms of
# either of 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 *****
var gSearchSession = null;
var gPreQuickSearchView = null;
var gSearchTimer = null;
var gViewSearchListener;
var gSearchBundle;
var gStatusBar = null;
var gSearchInProgress = false;
var gSearchInput = null;
var gClearButton = null;
var gDefaultSearchViewTerms = null;
var gQSViewIsDirty = false;
var gHighlightedMessageText = false;
// search criteria mode values
// Note: If you change these constants, please update the menuitem values in
// quick-search-menupopup. Note: These values are stored in localstore.rdf so we
// can remember the users last quick search state. If you add values here, you must add
// them to the end of the list!
const kQuickSearchSubject = 0;
const kQuickSearchSender = 1;
const kQuickSearchSenderOrSubject = 2;
const kQuickSearchBody = 3;
const kQuickSearchHighlight = 4;
var gFinder = Components.classes["@mozilla.org/embedcomp/rangefind;1"].createInstance()
.QueryInterface(Components.interfaces.nsIFind);
// Colors for highlighting
var gHighlightColors = new Array("yellow", "lightpink", "aquamarine",
"darkgoldenrod", "darkseagreen", "lightgreen",
"rosybrown", "seagreen", "chocolate", "violet");
function SetQSStatusText(aNumHits)
{
var statusMsg;
// if there are no hits, it means no matches were found in the search.
if (aNumHits == 0)
statusMsg = gSearchBundle.getString("searchFailureMessage");
else
{
if (aNumHits == 1)
statusMsg = gSearchBundle.getString("searchSuccessMessage");
else
statusMsg = gSearchBundle.getFormattedString("searchSuccessMessages", [aNumHits]);
}
statusFeedback.showStatusString(statusMsg);
}
// nsIMsgSearchNotify object
var gSearchNotificationListener =
{
onSearchHit: function(header, folder)
{
// XXX todo
// update status text?
},
onSearchDone: function(status)
{
SetQSStatusText(gDBView.QueryInterface(Components.interfaces.nsITreeView).rowCount)
statusFeedback.showProgress(0);
gStatusBar.setAttribute("mode","normal");
gSearchInProgress = false;
},
onNewSearch: function()
{
statusFeedback.showProgress(0);
statusFeedback.showStatusString(gSearchBundle.getString("searchingMessage"));
gStatusBar.setAttribute("mode","undetermined");
gSearchInProgress = true;
}
}
function getDocumentElements()
{
gSearchBundle = document.getElementById("bundle_search");
gStatusBar = document.getElementById('statusbar-icon');
gClearButton = document.getElementById('clearButton');
GetSearchInput();
}
function addListeners()
{
gViewSearchListener = gDBView.QueryInterface(Components.interfaces.nsIMsgSearchNotify);
gSearchSession.registerListener(gViewSearchListener);
}
function removeListeners()
{
gSearchSession.unregisterListener(gViewSearchListener);
}
function removeGlobalListeners()
{
removeListeners();
gSearchSession.unregisterListener(gSearchNotificationListener);
}
function initializeGlobalListeners()
{
// Setup the javascript object as a listener on the search results
gSearchSession.registerListener(gSearchNotificationListener);
}
function createQuickSearchView()
{
if (gDBView.viewType != nsMsgViewType.eShowQuickSearchResults) //otherwise we are already in quick search view
{
var treeView = gDBView.QueryInterface(Components.interfaces.nsITreeView); //clear selection
treeView.selection.clearSelection();
gPreQuickSearchView = gDBView;
CreateDBView(gDBView.msgFolder, nsMsgViewType.eShowQuickSearchResults, nsMsgViewFlagsType.kNone, gDBView.sortType, gDBView.sortOrder);
}
}
function initializeSearchBar()
{
createQuickSearchView();
if (!gSearchSession)
{
getDocumentElements();
var searchSessionContractID = "@mozilla.org/messenger/searchSession;1";
gSearchSession = Components.classes[searchSessionContractID].createInstance(Components.interfaces.nsIMsgSearchSession);
initializeGlobalListeners();
}
else
{
if (gSearchInProgress)
{
onSearchStop();
gSearchInProgress = false;
}
removeListeners();
}
addListeners();
}
function onEnterInSearchBar()
{
if (gSearchInput.value == "")
{
if (gSearchInput.searchMode == kQuickSearchHighlight)
removeHighlighting();
if (gDBView.viewType == nsMsgViewType.eShowQuickSearchResults)
{
statusFeedback.showStatusString("");
disableQuickSearchClearButton();
if (gDefaultSearchViewTerms)
{
if (gQSViewIsDirty)
{
initializeSearchBar();
onSearch(gDefaultSearchViewTerms);
}
}
else
restorePreSearchView();
}
gSearchInput.showingSearchCriteria = true;
gQSViewIsDirty = false;
return;
}
if (gSearchInput.searchMode == kQuickSearchHighlight)
highlightMessage(true);
else
{
initializeSearchBar();
gClearButton.setAttribute("disabled", false); //coming into search enable clear button
ClearThreadPaneSelection();
ClearMessagePane();
onSearch(null);
gQSViewIsDirty = false;
}
}
function restorePreSearchView()
{
var selectedHdr = null;
//save selection
try
{
selectedHdr = gDBView.hdrForFirstSelectedMessage;
}
catch (ex)
{}
//we might have to sort the view coming out of quick search
var sortType = gDBView.sortType;
var sortOrder = gDBView.sortOrder;
var viewFlags = gDBView.viewFlags;
var folder = gDBView.msgFolder;
gDBView.close();
gDBView = null;
if (gPreQuickSearchView)
{
gDBView = gPreQuickSearchView;
if (sortType != gDBView.sortType || sortOrder != gDBView.sortOrder)
{
gDBView.sort(sortType, sortOrder);
}
UpdateSortIndicators(sortType, sortOrder);
gPreQuickSearchView = null;
}
else //create default view type
CreateDBView(folder, nsMsgViewType.eShowAllThreads, viewFlags, sortType, sortOrder);
RerootThreadPane();
var scrolled = false;
// now restore selection
if (selectedHdr)
{
gDBView.selectMsgByKey(selectedHdr.messageKey);
var treeView = gDBView.QueryInterface(Components.interfaces.nsITreeView);
var selectedIndex = treeView.selection.currentIndex;
if (selectedIndex >= 0)
{
// scroll
EnsureRowInThreadTreeIsVisible(selectedIndex);
scrolled = true;
}
else
ClearMessagePane();
}
// NOTE,
// if you change the scrolling code below,
// double check the scrolling logic in
// msgMail3PaneWindow.js, "FolderLoaded" event code
if (!scrolled)
{
// if we didn't just scroll,
// scroll to the first new message
// but don't select it
scrolled = ScrollToMessage(nsMsgNavigationType.firstNew, true, false /* selectMessage */);
if (!scrolled)
{
// if we still haven't scrolled,
// scroll to the newest, which might be the top or the bottom
// depending on our sort order and sort type
if (sortOrder == nsMsgViewSortOrder.ascending)
{
switch (sortType)
{
case nsMsgViewSortType.byDate:
case nsMsgViewSortType.byId:
case nsMsgViewSortType.byThread:
scrolled = ScrollToMessage(nsMsgNavigationType.lastMessage, true, false /* selectMessage */);
break;
}
}
// if still we haven't scrolled,
// scroll to the top.
if (!scrolled)
EnsureRowInThreadTreeIsVisible(0);
}
}
// NOTE,
// if you change the scrolling code above,
// double check the scrolling logic in
// msgMail3PaneWindow.js, "FolderLoaded" event code
}
function onSearch(aSearchTerms)
{
RerootThreadPane();
if (aSearchTerms)
createSearchTermsWithList(aSearchTerms);
else
createSearchTerms();
gDBView.searchSession = gSearchSession;
try
{
gSearchSession.search(msgWindow);
}
catch(ex)
{
dump("Search Exception\n");
}
}
function createSearchTermsWithList(aTermsArray)
{
var nsMsgSearchScope = Components.interfaces.nsMsgSearchScope;
var nsMsgSearchAttrib = Components.interfaces.nsMsgSearchAttrib;
var nsMsgSearchOp = Components.interfaces.nsMsgSearchOp;
gSearchSession.clearScopes();
var searchTerms = gSearchSession.searchTerms;
var searchTermsArray = searchTerms.QueryInterface(Components.interfaces.nsISupportsArray);
searchTermsArray.Clear();
var selectedFolder = GetThreadPaneFolder();
gSearchSession.addScopeTerm(nsMsgSearchScope.offlineMail, selectedFolder);
// add each item in termsArray to the search session
var termsArray = aTermsArray.QueryInterface(Components.interfaces.nsISupportsArray);
for (var i = 0; i < termsArray.Count(); i++)
gSearchSession.appendTerm(termsArray.GetElementAt(i).QueryInterface(Components.interfaces.nsIMsgSearchTerm));
}
function createSearchTerms()
{
var nsMsgSearchScope = Components.interfaces.nsMsgSearchScope;
var nsMsgSearchAttrib = Components.interfaces.nsMsgSearchAttrib;
var nsMsgSearchOp = Components.interfaces.nsMsgSearchOp;
// create an i supports array to store our search terms
var searchTermsArray = Components.classes["@mozilla.org/supports-array;1"].createInstance(Components.interfaces.nsISupportsArray);
var selectedFolder = GetThreadPaneFolder();
var searchAttrib = (IsSpecialFolder(selectedFolder, MSG_FOLDER_FLAG_SENTMAIL | MSG_FOLDER_FLAG_DRAFTS | MSG_FOLDER_FLAG_QUEUE)) ? nsMsgSearchAttrib.ToOrCC : nsMsgSearchAttrib.Sender;
// implement | for QS
// does this break if the user types "foo|bar" expecting to see subjects with that string?
// I claim no, since "foo|bar" will be a hit for "foo" || "bar"
// they just might get more false positives
var termList = gSearchInput.value.split("|");
for (var i = 0; i < termList.length; i ++)
{
// if the term is empty, skip it
if (termList[i] == "")
continue;
// create, fill, and append the subject term
var term;
var value;
// if our search criteria is subject or subject|sender then add a term for the subject
if (gSearchInput.searchMode == kQuickSearchSubject || gSearchInput.searchMode == kQuickSearchSenderOrSubject)
{
term = gSearchSession.createTerm();
value = term.value;
value.str = termList[i];
term.value = value;
term.attrib = nsMsgSearchAttrib.Subject;
term.op = nsMsgSearchOp.Contains;
term.booleanAnd = false;
searchTermsArray.AppendElement(term);
}
if (gSearchInput.searchMode == kQuickSearchBody)
{
// what do we do for news and imap users that aren't configured for offline use?
// in these cases the body search will never return any matches. Should we try to
// see if body is a valid search scope in this particular case before doing the search?
// should we switch back to a subject/sender search behind the scenes?
term = gSearchSession.createTerm();
value = term.value;
value.str = termList[i];
term.value = value;
term.attrib = nsMsgSearchAttrib.Body;
term.op = nsMsgSearchOp.Contains;
term.booleanAnd = false;
searchTermsArray.AppendElement(term);
}
// create, fill, and append the sender (or recipient) term
if (gSearchInput.searchMode == kQuickSearchSender || gSearchInput.searchMode == kQuickSearchSenderOrSubject)
{
term = gSearchSession.createTerm();
value = term.value;
value.str = termList[i];
term.value = value;
term.attrib = searchAttrib;
term.op = nsMsgSearchOp.Contains;
term.booleanAnd = false;
searchTermsArray.AppendElement(term);
}
}
// now append the default view criteria to the quick search so we don't lose any default
// view information
if (gDefaultSearchViewTerms)
{
var isupports = null;
var searchTerm;
var termsArray = gDefaultSearchViewTerms.QueryInterface(Components.interfaces.nsISupportsArray);
for (i = 0; i < termsArray.Count(); i++)
{
isupports = termsArray.GetElementAt(i);
searchTerm = isupports.QueryInterface(Components.interfaces.nsIMsgSearchTerm);
searchTermsArray.AppendElement(searchTerm);
}
}
createSearchTermsWithList(searchTermsArray);
// now that we've added the terms, clear out our input array
searchTermsArray.Clear();
}
function onAdvancedSearch()
{
MsgSearchMessages();
}
function onSearchStop()
{
gSearchSession.interruptSearch();
}
function onSearchKeyPress(event)
{
if (gSearchInput.showingSearchCriteria)
gSearchInput.showingSearchCriteria = false;
// 13 == return
if (event && event.keyCode == 13)
onSearchInput(true);
}
function onSearchInputFocus(event)
{
// search bar has focus, ...clear the showing search criteria flag
if (gSearchInput.showingSearchCriteria)
{
gSearchInput.value = "";
gSearchInput.showingSearchCriteria = false;
}
gSearchInput.select();
}
function onSearchInputBlur(event)
{
if (!gSearchInput.value)
gSearchInput.showingSearchCriteria = true;
if (gSearchInput.showingSearchCriteria)
gSearchInput.setSearchCriteriaText();
}
function onSearchInput(returnKeyHit)
{
if (gSearchInput.showingSearchCriteria)
return;
if (gSearchTimer) {
clearTimeout(gSearchTimer);
gSearchTimer = null;
}
// only select the text when the return key was hit
if (returnKeyHit) {
GetSearchInput();
gSearchInput.select();
onEnterInSearchBar();
}
else {
gSearchTimer = setTimeout("onEnterInSearchBar();", 800);
}
}
function onClearSearch()
{
var focusedElement = gLastFocusedElement; //save of the last focused element so that focus can be restored
Search("");
focusedElement.focus();
}
function disableQuickSearchClearButton()
{
if (gClearButton)
gClearButton.setAttribute("disabled", true); //going out of search disable clear button
}
function ClearQSIfNecessary()
{
GetSearchInput();
if (gSearchInput.value == "")
return;
Search("");
}
function Search(str)
{
if (gSearchInput.showingSearchCriteria)
return;
GetSearchInput();
if (str != gSearchInput.value)
gQSViewIsDirty = true;
gSearchInput.value = str; //on input does not get fired for some reason
onSearchInput(true);
}
// this notification gets generated from layout when it finishes laying out a message
// in the message pane.
function onQuickSearchNewMsgLoaded()
{
// if we are in highlighting mode and we have highlight text in the search box then
// re-highlight this new message.
// Optimization: We'll special case Message Body quick searches and highlight those as well as find in message
// searches.
if ( (gSearchInput.searchMode == kQuickSearchHighlight || gSearchInput.searchMode == kQuickSearchBody)
&& gSearchInput.value && !gSearchInput.showingSearchCriteria)
{
highlightMessage(false);
}
}
// helper methods for the quick search drop down menu
function changeQuickSearchMode(aMenuItem)
{
// extract the label and set the search input to match it
var oldSearchMode = gSearchInput.searchMode;
gSearchInput.searchMode = aMenuItem.value;
if (gSearchInput.value == "")
gSearchInput.showingSearchCriteria = true;
else if (oldSearchMode != gSearchInput.searchMode) // the search mode just changed so we need to redo the quick search
{
if (gHighlightedMessageText)
removeHighlighting(); // remove any existing highlighting in the message before switching gears
onEnterInSearchBar();
}
}
// Methods to support highlighting. Most of this was shamelessly copied from the mozdev google toolbar project
function highlightMessage(removeExistingHighlighting)
{
// remove any existing highlighting
if (removeExistingHighlighting)
removeHighlighting();
// wanted to use selection to extend to the word
// and compare with the found range, in order to match
// only whole words
// Save selection
// XXX: Note to self, we may want to break on | and white space here
// even though normal quick searches treat white spaces as signficant
var termList = gSearchInput.value.split("|");
for (var i = 0; i < termList.length; i++)
highlight(termList[i], gHighlightColors[i %10]);
gHighlightedMessageText = true;
}
function removeHighlighting()
{
if (!gHighlightedMessageText)
return;
var msgDocument = window.top.content;
var doc = msgDocument.document;
var elem = null;
while ((elem = doc.getElementById('mail-highlight-id')))
{
var child = null;
var docfrag = doc.createDocumentFragment();
var next = elem.nextSibling;
var parent = elem.parentNode;
while((child = elem.firstChild))
docfrag.appendChild(child);
parent.removeChild(elem);
parent.insertBefore(docfrag, next);
}
gHighlightedMessageText = false;
return;
}
function highlight(word, color)
{
var msgDocument = window.top.content;
var doc = msgDocument.document;
if (!doc)
return;
if (!("body" in doc))
return;
var body = doc.body;
var count = body.childNodes.length;
searchRange = doc.createRange();
startPt = doc.createRange();
endPt = doc.createRange();
var baseNode = doc.createElement("span");
baseNode.setAttribute("style", "background-color: " + color + ";");
baseNode.setAttribute("id", "mail-highlight-id");
searchRange.setStart(body, 0);
searchRange.setEnd(body, count);
startPt.setStart(body, 0);
startPt.setEnd(body, 0);
endPt.setStart(body, count);
endPt.setEnd(body, count);
highlightText(word, baseNode);
}
// search through the message looking for occurrences of word
// and highlighting them.
function highlightText(word, baseNode)
{
var retRange = null;
while((retRange = gFinder.Find(word, searchRange, startPt, endPt)))
{
// Highlight
var nodeSurround = baseNode.cloneNode(true);
var node = highlightRange(retRange, nodeSurround);
startPt = node.ownerDocument.createRange();
startPt.setStart(node, node.childNodes.length);
startPt.setEnd(node, node.childNodes.length);
}
}
function highlightRange(range, node)
{
var startContainer = range.startContainer;
var startOffset = range.startOffset;
var endOffset = range.endOffset;
var docfrag = range.extractContents();
var before = startContainer.splitText(startOffset);
var parent = before.parentNode;
node.appendChild(docfrag);
parent.insertBefore(node, before);
return node;
}

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

@ -8,7 +8,7 @@ messenger.jar:
+ content/messenger/mailOverlay.xul (content/mailOverlay.xul)
*+ content/messenger/messageWindow.xul (content/messageWindow.xul)
*+ content/messenger/messageWindow.js (content/messageWindow.js)
*+ content/messenger/mailContextMenus.js (content/mailContextMenus.js)
*+ content/messenger/mailContextMenus.js (content/mailContextMenus.js)
*+ content/messenger/messenger.xul (content/messenger.xul)
* content/messenger/hiddenWindow.xul (content/hiddenWindow.xul)
* content/messenger/hiddenWindow.js (content/hiddenWindow.js)
@ -29,11 +29,14 @@ messenger.jar:
*+ content/messenger/junkMail.js (content/junkMail.js)
*+ content/messenger/msgSelectOffline.xul (content/msgSelectOffline.xul)
*+ content/messenger/msgPrintEngine.xul (content/msgPrintEngine.xul)
*+ content/messenger/searchBar.js (content/searchBar.js)
*+ content/messenger-views/contents.rdf (content/messenger-views.rdf)
content/messenger/about-thunderbird.png (content/about-thunderbird.png)
content/messenger/about-credits.png (content/about-credits.png)
content/messenger/about-footer.png (content/about-footer.png)
content/messenger/aboutDialog.css (content/aboutDialog.css)
+ content/messenger/messenger.css (content/messenger.css)
* content/messenger/search.xml (content/search.xml)
comm.jar:
* content/help/contents.rdf (content/help.rdf)

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

@ -494,15 +494,18 @@
<!ENTITY viewPickerAll.label "All">
<!ENTITY viewPickerUnread.label "Unread">
<!ENTITY viewPickerCustomView.label "Customize...">
<!ENTITY SearchSubjectOrSender.label "Subject or Sender contains:">
<!ENTITY SearchSubjectOrSender.accesskey "S">
<!ENTITY SearchNameOrEmail.label "Name or Email contains:">
<!ENTITY SearchNameOrEmail.accesskey "N">
<!ENTITY advancedButton.label "Advanced...">
<!ENTITY advancedButton.accesskey "A">
<!ENTITY clearButton.label "Clear">
<!ENTITY clearButton.accesskey "C">
<!-- Quick Search Menu Bar -->
<!ENTITY searchSubjectMenu.label "Subject">
<!ENTITY searchSenderMenu.label "Sender">
<!ENTITY searchSubjectOrSenderMenu.label "Subject Or Sender">
<!ENTITY searchMessageBody.label "Message Body">
<!ENTITY findInMessageMenu.label "Find In Message">
<!-- Thread Pane -->
<!ENTITY threadColumn.label "Thread">
<!ENTITY senderColumn.label "Sender">

Двоичные данные
mail/base/skin/icons/Search-bar.png Normal file

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

После

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

Двоичные данные
mail/base/skin/icons/search-arrow.gif Normal file

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

После

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

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

@ -67,6 +67,8 @@ classic.jar:
skin/classic/messenger/icons/message-news-new.png (icons/message-news-new.png)
skin/classic/messenger/icons/readcol.png (icons/readcol.png)
skin/classic/messenger/icons/unreadmail.png (icons/unreadmail.png)
skin/classic/messenger/icons/Search-bar.png (icons/Search-bar.png)
skin/classic/messenger/icons/search-arrow.gif (icons/search-arrow.gif)
skin/classic/communicator/icons/smileys/smiley-smile.png (icons/smileys/smiley-smile.png)
skin/classic/communicator/icons/smileys/smiley-frown.png (icons/smileys/smiley-frown.png)
skin/classic/communicator/icons/smileys/smiley-wink.png (icons/smileys/smiley-wink.png)

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

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

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

@ -37,6 +37,8 @@ classic.jar:
skin/classic/messenger/icons/SearchBarLeft.png (icons/SearchBarLeft.png)
skin/classic/messenger/icons/SearchBarMiddle.png (icons/SearchBarMiddle.png)
skin/classic/messenger/icons/SearchBarRight.png (icons/SearchBarRight.png)
skin/classic/messenger/icons/search-bar-background.png (icons/search-bar-background.png)
skin/classic/messenger/icons/Search-bar.png (icons/Search-bar.png)
skin/classic/messenger/icons/attach.png (icons/attach.png)
skin/classic/messenger/icons/attachment-col.png (icons/attachment-col.png)
skin/classic/messenger/icons/attachment-selected.png (icons/attachment-selected.png)

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

@ -192,7 +192,11 @@ treechildren::-moz-tree-cell-text(folderNameCol, noSelect-true) {
list-style-image: none;
}
#folderUnreadCol, #folderTotalCol, #folderSizeCol { text-align: right; }
#folderUnreadCol,
#folderTotalCol,
#folderSizeCol {
text-align: right;
}
#folderNameCol [sortDirection="ascending"],
#folderNameCol [sortDirection="descending"] {
@ -955,46 +959,49 @@ splitter {
border: 1px solid transparent;
}
#searchBox {
padding: 2px 0px;
margin: 0px;
}
#searchInput[searchCriteria="true"] {
color: grey;
}
#search-button {
min-width: 22px;
margin: 0px 3px 0px 5px;
}
.search-button-image {
padding: 0px;
list-style-image: url("chrome://messenger/skin/icons/Search-bar.png");
}
.search-button-dropmarker {
padding: 6px 0px 5px 17px;
list-style-image: url("chrome://global/skin/arrow/arrow-dn.png");
}
#searchInput {
background: url("chrome://messenger/skin/icons/search-bar-background.png") no-repeat;
margin: 4px 3px 4px 3px;
-moz-appearance: none;
background: url("chrome://messenger/skin/icons/SearchBarLeft.png") left center no-repeat;
margin: 0px !important;
border: 0px;
height: 21px !important;
padding-left: 22px;
font: icon;
height: 22px !important;
width: 182px !important;
border: none !important;
}
#searchInput > .textbox-input-box {
border: 0px;
background: url("chrome://messenger/skin/icons/SearchBarMiddle.png") center repeat-x;
height: 21px !important;
padding-top: 4px;
border: none;
padding-right: 10px; padding-top: 3px;
height: 21px !important;
margin: 0px;
}
#clearButton {
-moz-appearance: none;
background: url("chrome://messenger/skin/icons/SearchBarRight.png") right center no-repeat;
list-style-image: url("chrome://global/skin/icons/closetab.png");
margin: 0px 6px 0px 0px !important;
height: 21px !important;
padding: 0px 4px 0px 0px;
min-width: 21px;
}
#clearButton[disabled="true"] {
list-style-image: none;
}
#clearButton > hbox > label {
display: none;
}
/* ..... message pane adjustments ..... */

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

@ -949,7 +949,7 @@ treechildren::-moz-tree-cell-text(lc-black, selected) {
}
#folderPaneHeader {
height: 27px;
height: 29px;
border-bottom: none;
border-top: none;
}
@ -973,12 +973,39 @@ treechildren::-moz-tree-cell-text(lc-black, selected) {
/* ..... tree adjustments ..... */
.textbox-input-box
{
padding-top: 1px;
}
#accountCentralBox {
border: 1px solid ThreeDShadow;
}
#searchBox {
border-top: 1px solid ThreeDHighlight;
height: 30px;
}
#searchInput[searchCriteria="true"] {
color: grey;
}
#search-button {
margin-top: 1px;
margin-bottom: 1px;
margin-right: 2px;
}
.search-button-image {
margin: 0px;
list-style-image: url("chrome://messenger/skin/icons/Search-bar.png");
}
.search-button-dropmarker {
margin-left: 12px;
margin-top: 8px;
list-style-image: url("chrome://messenger/skin/icons/search-arrow.gif");
}
/* ..... message pane adjustments ..... */