749 строки
24 KiB
JavaScript
749 строки
24 KiB
JavaScript
/* -*- Mode: javascript; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
|
* ***** 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):
|
|
* Jan Varga <varga@ku.sk>
|
|
* Håkan Waara (hwaara@chello.se)
|
|
* Christopher Thomas <cst@yecc.com>
|
|
*
|
|
* 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 ***** */
|
|
|
|
//This file stores variables common to mail windows
|
|
var messengerContractID = "@mozilla.org/messenger;1";
|
|
var statusFeedbackContractID = "@mozilla.org/messenger/statusfeedback;1";
|
|
var mailSessionContractID = "@mozilla.org/messenger/services/session;1";
|
|
var secureUIContractID = "@mozilla.org/secure_browser_ui;1";
|
|
|
|
|
|
var prefContractID = "@mozilla.org/preferences-service;1";
|
|
var msgWindowContractID = "@mozilla.org/messenger/msgwindow;1";
|
|
|
|
var messenger;
|
|
var pref;
|
|
var prefServices;
|
|
var statusFeedback;
|
|
var msgWindow;
|
|
|
|
var msgComposeService;
|
|
var accountManager;
|
|
var RDF;
|
|
var msgComposeType;
|
|
var msgComposeFormat;
|
|
|
|
var mailSession;
|
|
|
|
var gMessengerBundle;
|
|
var gBrandBundle;
|
|
|
|
var datasourceContractIDPrefix = "@mozilla.org/rdf/datasource;1?name=";
|
|
var accountManagerDSContractID = datasourceContractIDPrefix + "msgaccountmanager";
|
|
var folderDSContractID = datasourceContractIDPrefix + "mailnewsfolders";
|
|
|
|
var accountManagerDataSource;
|
|
var folderDataSource;
|
|
|
|
var accountCentralBox = null;
|
|
var gSearchBox = null;
|
|
var gAccountCentralLoaded = true;
|
|
var gFakeAccountPageLoaded = false;
|
|
//End progress and Status variables
|
|
|
|
var gOfflineManager;
|
|
|
|
// cache the last keywords
|
|
var gLastKeywords = "";
|
|
|
|
function OnMailWindowUnload()
|
|
{
|
|
RemoveMailOfflineObserver();
|
|
ClearPendingReadTimer();
|
|
|
|
var searchSession = GetSearchSession();
|
|
if (searchSession)
|
|
{
|
|
removeGlobalListeners();
|
|
if (gPreQuickSearchView) //close the cached pre quick search view
|
|
gPreQuickSearchView.close();
|
|
}
|
|
|
|
var dbview = GetDBView();
|
|
if (dbview) {
|
|
dbview.close();
|
|
}
|
|
|
|
var mailSession = Components.classes[mailSessionContractID].getService();
|
|
if(mailSession)
|
|
{
|
|
mailSession = mailSession.QueryInterface(Components.interfaces.nsIMsgMailSession);
|
|
if(mailSession)
|
|
{
|
|
mailSession.RemoveFolderListener(folderListener);
|
|
}
|
|
}
|
|
|
|
mailSession.RemoveMsgWindow(msgWindow);
|
|
messenger.setWindow(null, null);
|
|
|
|
var msgDS = folderDataSource.QueryInterface(Components.interfaces.nsIMsgRDFDataSource);
|
|
msgDS.window = null;
|
|
|
|
msgDS = accountManagerDataSource.QueryInterface(Components.interfaces.nsIMsgRDFDataSource);
|
|
msgDS.window = null;
|
|
msgWindow.closeWindow();
|
|
}
|
|
|
|
function CreateMessenger()
|
|
{
|
|
messenger = Components.classes[messengerContractID].createInstance();
|
|
messenger = messenger.QueryInterface(Components.interfaces.nsIMessenger);
|
|
}
|
|
|
|
function CreateMailWindowGlobals()
|
|
{
|
|
// get the messenger instance
|
|
CreateMessenger();
|
|
|
|
prefServices = Components.classes[prefContractID].getService(Components.interfaces.nsIPrefService);
|
|
pref = prefServices.getBranch(null);
|
|
|
|
//Create windows status feedback
|
|
// set the JS implementation of status feedback before creating the c++ one..
|
|
window.MsgStatusFeedback = new nsMsgStatusFeedback();
|
|
// double register the status feedback object as the xul browser window implementation
|
|
window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
|
|
.getInterface(Components.interfaces.nsIWebNavigation)
|
|
.QueryInterface(Components.interfaces.nsIDocShellTreeItem).treeOwner
|
|
.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
|
|
.getInterface(Components.interfaces.nsIXULWindow)
|
|
.XULBrowserWindow = window.MsgStatusFeedback;
|
|
|
|
statusFeedback = Components.classes[statusFeedbackContractID].createInstance();
|
|
statusFeedback = statusFeedback.QueryInterface(Components.interfaces.nsIMsgStatusFeedback);
|
|
statusFeedback.setWrappedStatusFeedback(window.MsgStatusFeedback);
|
|
|
|
/*
|
|
not in use unless we want the lock button back
|
|
|
|
// try to create and register ourselves with a security icon...
|
|
var securityIcon = document.getElementById("security-button");
|
|
if (securityIcon) {
|
|
// if the client isn't built with psm enabled then we won't have a secure UI to monitor the lock icon
|
|
// so be sure to wrap this in a try / catch clause...
|
|
try {
|
|
var secureUI;
|
|
// we may not have a secure UI if psm isn't installed!
|
|
if (secureUIContractID in Components.classes) {
|
|
secureUI = Components.classes[secureUIContractID].createInstance();
|
|
if (secureUI) {
|
|
secureUI = secureUI.QueryInterface(Components.interfaces.nsISecureBrowserUI);
|
|
secureUI.init(content, securityIcon);
|
|
}
|
|
}
|
|
}
|
|
catch (ex) {}
|
|
}
|
|
*/
|
|
|
|
window.MsgWindowCommands = new nsMsgWindowCommands();
|
|
|
|
//Create message window object
|
|
msgWindow = Components.classes[msgWindowContractID].createInstance();
|
|
msgWindow = msgWindow.QueryInterface(Components.interfaces.nsIMsgWindow);
|
|
|
|
msgComposeService = Components.classes['@mozilla.org/messengercompose;1'].getService();
|
|
msgComposeService = msgComposeService.QueryInterface(Components.interfaces.nsIMsgComposeService);
|
|
|
|
mailSession = Components.classes["@mozilla.org/messenger/services/session;1"].getService(Components.interfaces.nsIMsgMailSession);
|
|
|
|
accountManager = Components.classes["@mozilla.org/messenger/account-manager;1"].getService(Components.interfaces.nsIMsgAccountManager);
|
|
|
|
RDF = Components.classes['@mozilla.org/rdf/rdf-service;1'].getService();
|
|
RDF = RDF.QueryInterface(Components.interfaces.nsIRDFService);
|
|
|
|
msgComposeType = Components.interfaces.nsIMsgCompType;
|
|
msgComposeFormat = Components.interfaces.nsIMsgCompFormat;
|
|
|
|
gMessengerBundle = document.getElementById("bundle_messenger");
|
|
gBrandBundle = document.getElementById("bundle_brand");
|
|
|
|
//Create datasources
|
|
accountManagerDataSource = Components.classes[accountManagerDSContractID].getService();
|
|
folderDataSource = Components.classes[folderDSContractID].getService();
|
|
|
|
msgWindow.notificationCallbacks = new nsMsgBadCertHandler();
|
|
}
|
|
|
|
function InitMsgWindow()
|
|
{
|
|
msgWindow.windowCommands = new nsMsgWindowCommands();
|
|
// set the domWindow before setting the status feedback and header sink objects
|
|
msgWindow.domWindow = window;
|
|
msgWindow.statusFeedback = statusFeedback;
|
|
msgWindow.msgHeaderSink = messageHeaderSink;
|
|
mailSession.AddMsgWindow(msgWindow);
|
|
|
|
var messagepane = document.getElementById("messagepane");
|
|
messagepane.docShell.allowAuth = false;
|
|
msgWindow.rootDocShell.allowAuth = true;
|
|
msgWindow.rootDocShell.appType = Components.interfaces.nsIDocShell.APP_TYPE_MAIL;
|
|
// Ensure we don't load xul error pages into the main window
|
|
msgWindow.rootDocShell.useErrorPages = false;
|
|
}
|
|
|
|
function messagePaneOnResize(event)
|
|
{
|
|
// scale any overflowing images
|
|
var messagepane = document.getElementById("messagepane");
|
|
var doc = messagepane.contentDocument;
|
|
var imgs = doc.images;
|
|
for each (var img in imgs)
|
|
{
|
|
if (img.className == "moz-attached-image")
|
|
{
|
|
if (img.naturalWidth <= doc.width)
|
|
{
|
|
img.removeAttribute("isshrunk");
|
|
img.removeAttribute("overflowing");
|
|
}
|
|
else if (img.hasAttribute("shrinktofit"))
|
|
{
|
|
img.setAttribute("isshrunk", "true");
|
|
img.removeAttribute("overflowing");
|
|
}
|
|
else
|
|
{
|
|
img.setAttribute("overflowing", "true");
|
|
img.removeAttribute("isshrunk");
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
function messagePaneOnClick(event)
|
|
{
|
|
// if this is stand alone mail (no browser)
|
|
// or this isn't a simple left click, do nothing, and let the normal code execute
|
|
if (event.button != 0 || event.metaKey || event.ctrlKey || event.shiftKey || event.altKey)
|
|
return contentAreaClick(event);
|
|
|
|
// try to determine the href for what you are clicking on.
|
|
// for example, it might be "" if you aren't left clicking on a link
|
|
var ceParams = hrefAndLinkNodeForClickEvent(event);
|
|
if (!ceParams && !event.button)
|
|
{
|
|
var target = event.target;
|
|
// is this an image that we might want to scale?
|
|
if (target instanceof Components.interfaces.nsIImageLoadingContent)
|
|
{
|
|
// make sure it loaded successfully
|
|
var req = target.getRequest(Components.interfaces.nsIImageLoadingContent.CURRENT_REQUEST);
|
|
if (!req || req.imageStatus & Components.interfaces.imgIRequest.STATUS_ERROR)
|
|
return true;
|
|
// is it an inline attachment?
|
|
if (/^moz-attached-image/.test(target.className))
|
|
{
|
|
if (target.hasAttribute("isshrunk"))
|
|
{
|
|
// currently shrunk to fit, so unshrink it
|
|
target.removeAttribute("isshrunk");
|
|
target.removeAttribute("shrinktofit");
|
|
target.setAttribute("overflowing", "true");
|
|
}
|
|
else if (target.hasAttribute("overflowing"))
|
|
{
|
|
// user wants to shrink now
|
|
target.setAttribute("isshrunk", "true");
|
|
target.setAttribute("shrinktofit", "true");
|
|
target.removeAttribute("overflowing");
|
|
}
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
var href = ceParams.href;
|
|
|
|
// we know that http://, https://, ftp://, file://, chrome://,
|
|
// resource://, about:, and gopher:// (as if),
|
|
// should load in a browser. but if we don't have one of those
|
|
// (examples are mailto, imap, news, mailbox, snews, nntp, ldap,
|
|
// and externally handled schemes like aim)
|
|
// we may or may not want a browser window, in which case we return here
|
|
// and let the normal code handle it
|
|
var needABrowser = /(^http(s)?:|^ftp:|^file:|^gopher:|^chrome:|^resource:|^about:)/i;
|
|
if (href.search(needABrowser) == -1)
|
|
return true;
|
|
|
|
// however, if the protocol should not be loaded internally, then we should
|
|
// not put up a new browser window. we should just let the usual processing
|
|
// take place.
|
|
try {
|
|
var extProtService = Components.classes["@mozilla.org/uriloader/external-protocol-service;1"].getService();
|
|
extProtService = extProtService.QueryInterface(Components.interfaces.nsIExternalProtocolService);
|
|
var scheme = href.substring(0, href.indexOf(":"));
|
|
if (!extProtService.isExposedProtocol(scheme))
|
|
return true;
|
|
}
|
|
catch (ex) {} // ignore errors, and just assume that we can proceed.
|
|
|
|
// if you get here, the user did a simple left click on a link
|
|
// that we know should be in a browser window.
|
|
// since we are in the message pane, send it to the top most browser window
|
|
// (or open one) right away, instead of waiting for us to get some data and
|
|
// determine the content type, and then open a browser window
|
|
// we want to preventDefault, so that in
|
|
// nsGenericHTMLElement::HandleDOMEventForAnchors(), we don't try to handle the click again
|
|
event.preventDefault();
|
|
if (isPhishingURL(ceParams.linkNode, false, href))
|
|
return false;
|
|
|
|
openAsExternal(href);
|
|
return true;
|
|
}
|
|
|
|
function AddDataSources()
|
|
{
|
|
accountManagerDataSource = accountManagerDataSource.QueryInterface(Components.interfaces.nsIRDFDataSource);
|
|
folderDataSource = folderDataSource.QueryInterface(Components.interfaces.nsIRDFDataSource);
|
|
|
|
SetupMoveCopyMenus('moveMenu', accountManagerDataSource, folderDataSource);
|
|
SetupMoveCopyMenus('copyMenu', accountManagerDataSource, folderDataSource);
|
|
SetupMoveCopyMenus('button-file', accountManagerDataSource, folderDataSource);
|
|
SetupMoveCopyMenus('mailContext-copyMenu', accountManagerDataSource, folderDataSource);
|
|
SetupMoveCopyMenus('mailContext-moveMenu', accountManagerDataSource, folderDataSource);
|
|
|
|
//Add statusFeedback
|
|
var msgDS = folderDataSource.QueryInterface(Components.interfaces.nsIMsgRDFDataSource);
|
|
msgDS.window = msgWindow;
|
|
|
|
msgDS = accountManagerDataSource.QueryInterface(Components.interfaces.nsIMsgRDFDataSource);
|
|
msgDS.window = msgWindow;
|
|
|
|
}
|
|
|
|
function SetupMoveCopyMenus(menuid, accountManagerDataSource, folderDataSource)
|
|
{
|
|
var menu = document.getElementById(menuid);
|
|
if(menu)
|
|
{
|
|
menu.database.AddDataSource(accountManagerDataSource);
|
|
menu.database.AddDataSource(folderDataSource);
|
|
menu.setAttribute('ref', 'msgaccounts:/');
|
|
}
|
|
}
|
|
|
|
// We're going to implement our status feedback for the mail window in JS now.
|
|
// the following contains the implementation of our status feedback object
|
|
|
|
function nsMsgStatusFeedback()
|
|
{
|
|
}
|
|
|
|
nsMsgStatusFeedback.prototype =
|
|
{
|
|
// global variables for status / feedback information....
|
|
statusTextFld : null,
|
|
statusBar : null,
|
|
statusPanel : null,
|
|
throbber : null,
|
|
stopCmd : null,
|
|
startTimeoutID : null,
|
|
stopTimeoutID : null,
|
|
pendingStartRequests : 0,
|
|
meteorsSpinning : false,
|
|
myDefaultStatus : null,
|
|
|
|
ensureStatusFields : function()
|
|
{
|
|
if (!this.statusTextFld ) this.statusTextFld = document.getElementById("statusText");
|
|
if (!this.statusBar) this.statusBar = document.getElementById("statusbar-icon");
|
|
if (!this.statusPanel) this.statusPanel = document.getElementById("statusbar-progresspanel");
|
|
if (!this.throbber) this.throbber = document.getElementById("navigator-throbber");
|
|
if (!this.stopCmd) this.stopCmd = document.getElementById("cmd_stop");
|
|
},
|
|
|
|
// nsIXULBrowserWindow implementation
|
|
setJSStatus : function(status)
|
|
{
|
|
if (status.length > 0)
|
|
this.showStatusString(status);
|
|
},
|
|
setJSDefaultStatus : function(status)
|
|
{
|
|
if (status.length > 0)
|
|
{
|
|
this.myDefaultStatus = status;
|
|
this.statusTextFld.label = status;
|
|
}
|
|
},
|
|
setOverLink : function(link, context)
|
|
{
|
|
this.ensureStatusFields();
|
|
this.statusTextFld.label = link;
|
|
},
|
|
QueryInterface : function(iid)
|
|
{
|
|
if (iid.equals(Components.interfaces.nsIMsgStatusFeedback) ||
|
|
iid.equals(Components.interfaces.nsIXULBrowserWindow) ||
|
|
iid.equals(Components.interfaces.nsISupportsWeakReference) ||
|
|
iid.equals(Components.interfaces.nsISupports))
|
|
return this;
|
|
throw Components.results.NS_NOINTERFACE;
|
|
},
|
|
|
|
// nsIMsgStatusFeedback implementation.
|
|
showStatusString : function(statusText)
|
|
{
|
|
this.ensureStatusFields();
|
|
if ( !statusText.length )
|
|
statusText = this.myDefaultStatus;
|
|
else
|
|
this.myDefaultStatus = "";
|
|
this.statusTextFld.label = statusText;
|
|
},
|
|
_startMeteors : function()
|
|
{
|
|
this.ensureStatusFields();
|
|
|
|
this.meteorsSpinning = true;
|
|
this.startTimeoutID = null;
|
|
|
|
// Show progress meter
|
|
this.statusPanel.collapsed = false;
|
|
|
|
// Turn progress meter on.
|
|
this.statusBar.setAttribute("mode","undetermined");
|
|
|
|
// start the throbber
|
|
if (this.throbber)
|
|
this.throbber.setAttribute("busy", true);
|
|
|
|
//turn on stop button and menu
|
|
if (this.stopCmd)
|
|
this.stopCmd.removeAttribute("disabled");
|
|
},
|
|
startMeteors : function()
|
|
{
|
|
this.pendingStartRequests++;
|
|
// if we don't already have a start meteor timeout pending
|
|
// and the meteors aren't spinning, then kick off a start
|
|
if (!this.startTimeoutID && !this.meteorsSpinning && window.MsgStatusFeedback)
|
|
this.startTimeoutID = setTimeout('window.MsgStatusFeedback._startMeteors();', 500);
|
|
|
|
// since we are going to start up the throbber no sense in processing
|
|
// a stop timeout...
|
|
if (this.stopTimeoutID)
|
|
{
|
|
clearTimeout(this.stopTimeoutID);
|
|
this.stopTimeoutID = null;
|
|
}
|
|
},
|
|
_stopMeteors : function()
|
|
{
|
|
if(gTimelineEnabled){
|
|
gTimelineService.stopTimer("FolderLoading");
|
|
gTimelineService.markTimer("FolderLoading");
|
|
gTimelineService.resetTimer("FolderLoading");
|
|
}
|
|
this.ensureStatusFields();
|
|
this.showStatusString(defaultStatus);
|
|
|
|
// stop the throbber
|
|
if (this.throbber)
|
|
this.throbber.setAttribute("busy", false);
|
|
|
|
// Turn progress meter off.
|
|
this.statusPanel.collapsed = true;
|
|
this.statusBar.setAttribute("mode","normal");
|
|
this.statusBar.value = 0; // be sure to clear the progress bar
|
|
this.statusBar.label = "";
|
|
if (this.stopCmd)
|
|
this.stopCmd.setAttribute("disabled", "true");
|
|
|
|
this.meteorsSpinning = false;
|
|
this.stopTimeoutID = null;
|
|
},
|
|
stopMeteors : function()
|
|
{
|
|
if (this.pendingStartRequests > 0)
|
|
this.pendingStartRequests--;
|
|
|
|
// if we are going to be starting the meteors, cancel the start
|
|
if (this.pendingStartRequests == 0 && this.startTimeoutID)
|
|
{
|
|
clearTimeout(this.startTimeoutID);
|
|
this.startTimeoutID = null;
|
|
}
|
|
|
|
// if we have no more pending starts and we don't have a stop timeout already in progress
|
|
// AND the meteors are currently running then fire a stop timeout to shut them down.
|
|
if (this.pendingStartRequests == 0 && !this.stopTimeoutID)
|
|
{
|
|
if (this.meteorsSpinning && window.MsgStatusFeedback)
|
|
this.stopTimeoutID = setTimeout('window.MsgStatusFeedback._stopMeteors();', 500);
|
|
}
|
|
},
|
|
showProgress : function(percentage)
|
|
{
|
|
this.ensureStatusFields();
|
|
if (percentage >= 0)
|
|
{
|
|
this.statusBar.setAttribute("mode", "normal");
|
|
this.statusBar.value = percentage;
|
|
this.statusBar.label = Math.round(percentage) + "%";
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
function nsMsgWindowCommands()
|
|
{
|
|
}
|
|
|
|
nsMsgWindowCommands.prototype =
|
|
{
|
|
QueryInterface : function(iid)
|
|
{
|
|
if (iid.equals(Components.interfaces.nsIMsgWindowCommands) ||
|
|
iid.equals(Components.interfaces.nsISupports))
|
|
return this;
|
|
throw Components.results.NS_NOINTERFACE;
|
|
},
|
|
|
|
selectFolder: function(folderUri)
|
|
{
|
|
SelectFolder(folderUri);
|
|
},
|
|
|
|
selectMessage: function(messageUri)
|
|
{
|
|
SelectMessage(messageUri);
|
|
},
|
|
|
|
clearMsgPane: function()
|
|
{
|
|
if (gDBView)
|
|
setTitleFromFolder(gDBView.msgFolder,null);
|
|
else
|
|
setTitleFromFolder(null,null);
|
|
ClearMessagePane();
|
|
}
|
|
}
|
|
|
|
function StopUrls()
|
|
{
|
|
msgWindow.StopUrls();
|
|
}
|
|
|
|
function loadStartPage()
|
|
{
|
|
try
|
|
{
|
|
gMessageNotificationBar.clearMsgNotifications();
|
|
|
|
var startpageenabled = pref.getBoolPref("mailnews.start_page.enabled");
|
|
if (startpageenabled)
|
|
{
|
|
var startpage = pref.getComplexValue("mailnews.start_page.url",
|
|
Components.interfaces.nsIPrefLocalizedString).data;
|
|
if (startpage)
|
|
{
|
|
// first, clear out the charset setting.
|
|
messenger.setDisplayCharset("");
|
|
GetMessagePaneFrame().location.href = startpage;
|
|
//dump("start message pane with: " + startpage + "\n");
|
|
ClearMessageSelection();
|
|
}
|
|
}
|
|
}
|
|
catch (ex)
|
|
{
|
|
dump("Error loading start page.\n");
|
|
return;
|
|
}
|
|
}
|
|
|
|
// When the ThreadPane is hidden via the displayDeck, we should collapse the
|
|
// elements that are only meaningful to the thread pane. When AccountCentral is
|
|
// shown via the displayDeck, we need to switch the displayDeck to show the
|
|
// accountCentralBox, and load the iframe in the AccountCentral box with
|
|
// corresponding page.
|
|
function ShowAccountCentral()
|
|
{
|
|
try
|
|
{
|
|
document.getElementById("displayDeck").selectedPanel = accountCentralBox;
|
|
var acctCentralPage = pref.getComplexValue("mailnews.account_central_page.url",
|
|
Components.interfaces.nsIPrefLocalizedString).data;
|
|
window.frames["accountCentralPane"].location.href = acctCentralPage;
|
|
}
|
|
catch (ex)
|
|
{
|
|
dump("Error loading AccountCentral page -> " + ex + "\n");
|
|
return;
|
|
}
|
|
}
|
|
|
|
function ShowingAccountCentral()
|
|
{
|
|
if (!IsFolderPaneCollapsed())
|
|
GetFolderTree().focus();
|
|
gAccountCentralLoaded = true;
|
|
}
|
|
|
|
function HidingAccountCentral()
|
|
{
|
|
gAccountCentralLoaded = false;
|
|
}
|
|
|
|
function ShowThreadPane()
|
|
{
|
|
document.getElementById("displayDeck").selectedPanel =
|
|
document.getElementById("threadPaneBox");
|
|
}
|
|
|
|
function ShowingThreadPane()
|
|
{
|
|
gSearchBox.collapsed = false;
|
|
var threadPaneSplitter = document.getElementById("threadpane-splitter");
|
|
threadPaneSplitter.collapsed = false;
|
|
if (!threadPaneSplitter.hidden && threadPaneSplitter.getAttribute("state") != "collapsed")
|
|
{
|
|
GetMessagePane().collapsed = false;
|
|
// XXX We need to force the tree to refresh its new height
|
|
// so that it will correctly scroll to the newest message
|
|
GetThreadTree().boxObject.height;
|
|
}
|
|
document.getElementById("key_toggleMessagePane").removeAttribute("disabled");
|
|
}
|
|
|
|
function HidingThreadPane()
|
|
{
|
|
ClearThreadPane();
|
|
GetUnreadCountElement().hidden = true;
|
|
GetTotalCountElement().hidden = true;
|
|
GetMessagePane().collapsed = true;
|
|
document.getElementById("threadpane-splitter").collapsed = true;
|
|
gSearchBox.collapsed = true;
|
|
document.getElementById("key_toggleMessagePane").setAttribute("disabled", "true");
|
|
}
|
|
|
|
function ObserveDisplayDeckChange(event)
|
|
{
|
|
var selectedPanel = document.getElementById("displayDeck").selectedPanel;
|
|
var nowSelected = selectedPanel ? selectedPanel.id : "";
|
|
|
|
if (nowSelected == "threadPaneBox")
|
|
ShowingThreadPane();
|
|
else
|
|
HidingThreadPane();
|
|
|
|
if (nowSelected == "accountCentralBox")
|
|
ShowingAccountCentral();
|
|
else
|
|
HidingAccountCentral();
|
|
}
|
|
|
|
// Given the server, open the twisty and the set the selection
|
|
// on inbox of that server.
|
|
// prompt if offline.
|
|
function OpenInboxForServer(server)
|
|
{
|
|
try {
|
|
ShowThreadPane();
|
|
var inboxFolder = GetInboxFolder(server);
|
|
SelectFolder(inboxFolder.URI);
|
|
|
|
if(CheckOnline()) {
|
|
if (server.type != "imap")
|
|
GetMessagesForInboxOnServer(server);
|
|
}
|
|
else if (DoGetNewMailWhenOffline()) {
|
|
GetMessagesForInboxOnServer(server);
|
|
}
|
|
}
|
|
catch (ex) {
|
|
dump("Error opening inbox for server -> " + ex + "\n");
|
|
return;
|
|
}
|
|
}
|
|
|
|
function GetSearchSession()
|
|
{
|
|
if (("gSearchSession" in top) && gSearchSession)
|
|
return gSearchSession;
|
|
else
|
|
return null;
|
|
}
|
|
|
|
function SetKeywords(aKeywords)
|
|
{
|
|
// we cache the last keywords.
|
|
// if there is no chagne, we do nothing.
|
|
// most of the time, this will be the case.
|
|
if (aKeywords == gLastKeywords)
|
|
return;
|
|
|
|
// these are the UI elements who care about keywords
|
|
var elements = document.getElementsByAttribute("keywordrelated","true");
|
|
var len = elements.length;
|
|
for (var i=0; i<len; i++) {
|
|
var element = elements[i];
|
|
var originalclass = element.getAttribute("originalclass");
|
|
|
|
// we use XBL for certain headers.
|
|
// if the element has keywordrelated="true"
|
|
// but no original class, it's an XBL widget
|
|
// so to get the real element, use getAnonymousElementByAttribute()
|
|
if (!originalclass) {
|
|
element = document.getAnonymousElementByAttribute(element, "keywordrelated", "true");
|
|
originalclass = element.getAttribute("originalclass");
|
|
}
|
|
|
|
if (aKeywords) {
|
|
if (element.getAttribute("appendoriginalclass") == "true") {
|
|
aKeywords += " " + originalclass;
|
|
}
|
|
element.setAttribute("class", aKeywords);
|
|
}
|
|
else {
|
|
// if no keywords, reset class to the original class
|
|
element.setAttribute("class", originalclass);
|
|
}
|
|
}
|
|
|
|
// cache the keywords
|
|
gLastKeywords = aKeywords;
|
|
}
|