pjs/mailnews/addrbook/resources/content/abCardOverlay.js

589 строки
20 KiB
JavaScript

/* -*- Mode: Java; 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.org code.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1998
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Seth Spitzer <sspitzer@netscape.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 ***** */
const kNonVcardFields =
["nickNameContainer", "secondaryEmailContainer", "screenNameContainer",
"homeAddressGroup", "customFields", "allowRemoteContent"];
const kPhoneticFields =
["PhoneticLastName", "PhoneticLabel1", "PhoneticSpacer1",
"PhoneticFirstName", "PhoneticLabel2", "PhoneticSpacer2"];
// Item is |[dialogField, cardProperty]|.
const kVcardFields =
[ // Contact > Name
["FirstName", "firstName"],
["LastName", "lastName"],
["DisplayName", "displayName"],
["NickName", "nickName"],
// Contact > Internet
["PrimaryEmail", "primaryEmail"],
["SecondEmail", "secondEmail"],
["ScreenName", "aimScreenName"], // NB: AIM.
// Contact > Phones
["WorkPhone", "workPhone"],
["HomePhone", "homePhone"],
["FaxNumber", "faxNumber"],
["PagerNumber", "pagerNumber"],
["CellularNumber", "cellularNumber"],
// Address > Home
["HomeAddress", "homeAddress"],
["HomeAddress2", "homeAddress2"],
["HomeCity", "homeCity"],
["HomeState", "homeState"],
["HomeZipCode", "homeZipCode"],
["HomeCountry", "homeCountry"],
["WebPage2", "webPage2"],
// Address > Work
["JobTitle", "jobTitle"],
["Department", "department"],
["Company", "company"],
["WorkAddress", "workAddress"],
["WorkAddress2", "workAddress2"],
["WorkCity", "workCity"],
["WorkState", "workState"],
["WorkZipCode", "workZipCode"],
["WorkCountry", "workCountry"],
["WebPage1", "webPage1"],
// Other > (custom)
["Custom1", "custom1"],
["Custom2", "custom2"],
["Custom3", "custom3"],
["Custom4", "custom4"],
// Other > Notes
["Notes", "notes"]];
var gEditCard;
var gOnSaveListeners = new Array();
var gOkCallback = null;
var gHideABPicker = false;
function OnLoadNewCard()
{
InitEditCard();
gEditCard.card =
(("arguments" in window) && (window.arguments.length > 0) &&
(window.arguments[0] instanceof Components.interfaces.nsIAbCard))
? window.arguments[0]
: Components.classes["@mozilla.org/addressbook/cardproperty;1"]
.createInstance(Components.interfaces.nsIAbCard);
gEditCard.titleProperty = "newCardTitle";
gEditCard.selectedAB = "";
if ("arguments" in window && window.arguments[0])
{
gEditCard.selectedAB = kPersonalAddressbookURI;
if ("selectedAB" in window.arguments[0]) {
// check if selected ab is a mailing list
var abURI = window.arguments[0].selectedAB;
var directory = GetDirectoryFromURI(abURI);
if (directory.isMailList) {
var parentURI = GetParentDirectoryFromMailingListURI(abURI);
if (parentURI)
gEditCard.selectedAB = parentURI;
}
else if (directory.operations & directory.opWrite)
gEditCard.selectedAB = window.arguments[0].selectedAB;
}
// we may have been given properties to pre-initialize the window with....
// we'll fill these in here...
if ("primaryEmail" in window.arguments[0])
gEditCard.card.primaryEmail = window.arguments[0].primaryEmail;
if ("displayName" in window.arguments[0]) {
gEditCard.card.displayName = window.arguments[0].displayName;
// if we've got a display name, don't generate
// a display name (and stomp on the existing display name)
// when the user types a first or last name
if (gEditCard.card.displayName.length)
gEditCard.generateDisplayName = false;
}
if ("aimScreenName" in window.arguments[0])
gEditCard.card.aimScreenName = window.arguments[0].aimScreenName;
if ("allowRemoteContent" in window.arguments[0]) {
gEditCard.card.allowRemoteContent = window.arguments[0].allowRemoteContent;
window.arguments[0].allowRemoteContent = false;
}
if ("okCallback" in window.arguments[0])
gOkCallback = window.arguments[0].okCallback;
if ("escapedVCardStr" in window.arguments[0]) {
// hide non vcard values
HideNonVcardFields();
gEditCard.card =
Components.classes["@mozilla.org/addressbook;1"]
.createInstance(Components.interfaces.nsIAddressBook)
.escapedVCardToAbCard(window.arguments[0].escapedVCardStr);
}
if ("titleProperty" in window.arguments[0])
gEditCard.titleProperty = window.arguments[0].titleProperty;
if ("hideABPicker" in window.arguments[0])
gHideABPicker = window.arguments[0].hideABPicker;
}
// set popup with address book names
var abPopup = document.getElementById('abPopup');
abPopup.value = gEditCard.selectedAB || kPersonalAddressbookURI;
if (gHideABPicker && abPopup) {
abPopup.hidden = true;
document.getElementById("abPopupLabel").hidden = true;
}
SetCardDialogTitle(gEditCard.card.displayName);
GetCardValues(gEditCard.card, document);
// FIX ME - looks like we need to focus on both the text field and the tab widget
// probably need to do the same in the addressing widget
// focus on first or last name based on the pref
var focus = document.getElementById(gEditCard.displayLastNameFirst
? "LastName" : "FirstName");
if ( focus ) {
// XXX Using the setTimeout hack until bug 103197 is fixed
setTimeout( function(firstTextBox) { firstTextBox.focus(); }, 0, focus );
}
moveToAlertPosition();
}
// @Returns The index in addressLists for the card that is being saved;
// or |-1| if the card is not found.
function findCardIndex(directory)
{
var i = directory.addressLists.Count();
while (i-- > 0) {
var card = directory.addressLists.QueryElementAt(i, Components.interfaces.nsIAbCard);
if (gEditCard.card.equals(card))
break;
}
return i;
}
function EditCardOKButton()
{
if (!CheckCardRequiredDataPresence(document))
return false; // don't close window
// See if this card is in any mailing list
// if so then we need to update the addresslists of those mailing lists
var index = -1;
var directory = GetDirectoryFromURI(gEditCard.abURI);
// if the directory is a mailing list we need to search all the mailing lists
// in the parent directory if the card exists.
if (directory.isMailList) {
var parentURI = GetParentDirectoryFromMailingListURI(gEditCard.abURI);
directory = GetDirectoryFromURI(parentURI);
}
var listDirectoriesCount = directory.addressLists.Count();
var foundDirectories = new Array();
var foundDirectoriesCount = 0;
var i;
// create a list of mailing lists and the index where the card is at.
for ( i=0; i < listDirectoriesCount; i++ ) {
var subdirectory = directory.addressLists.QueryElementAt(i, Components.interfaces.nsIAbDirectory);
index = findCardIndex(subdirectory);
if (index > -1)
{
foundDirectories[foundDirectoriesCount] = {directory:subdirectory, index:index};
foundDirectoriesCount++;
}
}
CheckAndSetCardValues(gEditCard.card, document, false);
directory.modifyCard(gEditCard.card);
for (i=0; i<foundDirectoriesCount; i++) {
// Update the addressLists item for this card
foundDirectories[i].directory.addressLists.
SetElementAt(foundDirectories[i].index, gEditCard.card);
}
NotifySaveListeners(directory);
// callback to allow caller to update
if (gOkCallback)
gOkCallback();
return true; // close the window
}
function OnLoadEditCard()
{
InitEditCard();
gEditCard.titleProperty = "editCardTitle";
if (window.arguments && window.arguments[0])
{
if ( window.arguments[0].card )
gEditCard.card = window.arguments[0].card;
if ( window.arguments[0].okCallback )
gOkCallback = window.arguments[0].okCallback;
if ( window.arguments[0].abURI )
gEditCard.abURI = window.arguments[0].abURI;
}
// set global state variables
// if first or last name entered, disable generateDisplayName
if (gEditCard.generateDisplayName &&
(gEditCard.card.firstName.length +
gEditCard.card.lastName.length +
gEditCard.card.displayName.length > 0))
{
gEditCard.generateDisplayName = false;
}
GetCardValues(gEditCard.card, document);
SetCardDialogTitle(gEditCard.card.displayName);
// check if selectedAB is a writeable
// if not disable all the fields
if ("arguments" in window && window.arguments[0])
{
if ("abURI" in window.arguments[0]) {
var abURI = window.arguments[0].abURI;
var directory = GetDirectoryFromURI(abURI);
if (!(directory.operations & directory.opWrite))
{
// Set all the editable vcard fields to read only
for (var i = kVcardFields.length; i-- > 0; )
document.getElementById(kVcardFields[i][0]).readOnly = true;
// And the phonetic fields
document.getElementById(kPhoneticFields[0]).readOnly = true;
document.getElementById(kPhoneticFields[3]).readOnly = true;
// Also disable the mail format popup.
document.getElementById("PreferMailFormatPopup").disabled = true;
document.documentElement.buttons = "accept";
document.documentElement.removeAttribute("ondialogaccept");
}
// hide remote content in HTML field for remote directories
if (directory.isRemote)
document.getElementById('allowRemoteContent').hidden = true;
}
}
}
// this is used by people who extend the ab card dialog
// like Netscape does for screenname
function RegisterSaveListener(func)
{
gOnSaveListeners[gOnSaveListeners.length] = func;
}
// this is used by people who extend the ab card dialog
// like Netscape does for screenname
function NotifySaveListeners(directory)
{
if (!gOnSaveListeners.length)
return;
for ( var i = 0; i < gOnSaveListeners.length; i++ )
gOnSaveListeners[i]();
// the save listeners might have tweaked the card
// in which case we need to commit it.
directory.modifyCard(gEditCard.card);
}
function InitPhoneticFields()
{
var showPhoneticFields =
gPrefs.getComplexValue("mail.addr_book.show_phonetic_fields",
Components.interfaces.nsIPrefLocalizedString).data;
// hide phonetic fields if indicated by the pref
if (showPhoneticFields == "true")
{
for (var i = kPhoneticFields.length; i-- > 0; )
document.getElementById(kPhoneticFields[i]).hidden = false;
}
}
function InitEditCard()
{
InitPhoneticFields();
InitCommonJS();
// Create gEditCard object that contains global variables for the current js
// file.
gEditCard = new Object();
gEditCard.prefs = gPrefs;
// get specific prefs that gEditCard will need
try {
var displayLastNameFirst =
gPrefs.getComplexValue("mail.addr_book.displayName.lastnamefirst",
Components.interfaces.nsIPrefLocalizedString).data;
gEditCard.displayLastNameFirst = (displayLastNameFirst == "true");
gEditCard.generateDisplayName =
gPrefs.getBoolPref("mail.addr_book.displayName.autoGeneration");
}
catch (ex) {
dump("ex: failed to get pref" + ex + "\n");
}
}
function NewCardOKButton()
{
if (gOkCallback)
{
if (!CheckAndSetCardValues(gEditCard.card, document, true))
return false; // don't close window
var addressbook = Components.classes["@mozilla.org/addressbook;1"].createInstance(Components.interfaces.nsIAddressBook);
gOkCallback(addressbook.abCardToEscapedVCard(gEditCard.card));
return true; // close the window
}
var popup = document.getElementById('abPopup');
if ( popup )
{
var uri = popup.getAttribute('value');
// FIX ME - hack to avoid crashing if no ab selected because of blank option bug from template
// should be able to just remove this if we are not seeing blank lines in the ab popup
if ( !uri )
return false; // don't close window
// -----
if (gEditCard.card)
{
if (!CheckAndSetCardValues(gEditCard.card, document, true))
return false; // don't close window
// replace gEditCard.card with the card we added
// so that save listeners can get / set attributes on
// the card that got created.
gEditCard.card = GetDirectoryFromURI(uri).addCard(gEditCard.card);
NotifySaveListeners();
if ("arguments" in window && window.arguments[0])
window.arguments[0].allowRemoteContent = gEditCard.card.allowRemoteContent;
}
}
return true; // close the window
}
// Move the data from the cardproperty to the dialog
function GetCardValues(cardproperty, doc)
{
if (!cardproperty)
return;
for (var i = kVcardFields.length; i-- > 0; )
doc.getElementById(kVcardFields[i][0]).value =
cardproperty[kVcardFields[i][1]];
var popup = document.getElementById("PreferMailFormatPopup");
if (popup)
popup.value = cardproperty.preferMailFormat;
var allowRemoteContentEl = document.getElementById("allowRemoteContent");
if (allowRemoteContentEl)
allowRemoteContentEl.checked = cardproperty.allowRemoteContent;
// get phonetic fields if exist
try {
doc.getElementById("PhoneticFirstName").value = cardproperty.phoneticFirstName;
doc.getElementById("PhoneticLastName").value = cardproperty.phoneticLastName;
}
catch (ex) {}
}
// when the ab card dialog is being loaded to show a vCard,
// hide the fields which aren't supported
// by vCard so the user does not try to edit them.
function HideNonVcardFields()
{
for (var i = kNonVcardFields.length; i-- > 0; )
document.getElementById(kNonVcardFields[i]).collapsed = true;
}
// Move the data from the dialog to the cardproperty to be stored in the database
// @Returns false - Some required data are missing (card values were not set);
// true - Card values were set, or there is no card to set values on.
function CheckAndSetCardValues(cardproperty, doc, check)
{
// If requested, check the required data presence.
if (check && !CheckCardRequiredDataPresence(document))
return false;
if (!cardproperty)
return true;
for (var i = kVcardFields.length; i-- > 0; )
cardproperty[kVcardFields[i][1]] =
doc.getElementById(kVcardFields[i][0]).value;
var popup = document.getElementById("PreferMailFormatPopup");
if (popup)
cardproperty.preferMailFormat = popup.value;
var allowRemoteContentEl = document.getElementById("allowRemoteContent");
if (allowRemoteContentEl)
cardproperty.allowRemoteContent = allowRemoteContentEl.checked;
// set phonetic fields if exist
try {
cardproperty.phoneticFirstName = doc.getElementById("PhoneticFirstName").value;
cardproperty.phoneticLastName = doc.getElementById("PhoneticLastName").value;
}
catch (ex) {}
return true;
}
function CleanUpWebPage(webPage)
{
// no :// yet so we should add something
if ( webPage.length && webPage.search("://") == -1 )
{
// check for missing / on http://
if ( webPage.substr(0, 6) == "http:/" )
return( "http://" + webPage.substr(6) );
else
return( "http://" + webPage );
}
else
return(webPage);
}
// @Returns false - Some required data are missing;
// true - All required data are present.
function CheckCardRequiredDataPresence(doc)
{
// Bug 314995 - We require at least one of the following fields to be
// filled in: email address, first name, last name, display name,
// organization (company name).
var primaryEmail = doc.getElementById("PrimaryEmail");
if (primaryEmail.textLength == 0 &&
doc.getElementById("FirstName").textLength == 0 &&
doc.getElementById("LastName").textLength == 0 &&
doc.getElementById("DisplayName").textLength == 0 &&
doc.getElementById("Company").textLength == 0)
{
Components
.classes["@mozilla.org/embedcomp/prompt-service;1"]
.getService(Components.interfaces.nsIPromptService)
.alert(
window,
gAddressBookBundle.getString("cardRequiredDataMissingTitle"),
gAddressBookBundle.getString("cardRequiredDataMissingMessage"));
return false;
}
// Simple checks that the primary email should be of the form |user@host|.
// Note: if the length of the primary email is 0 then we skip the check
// as some other field must have something as per the check above.
if (primaryEmail.textLength != 0 && !/.@./.test(primaryEmail.value))
{
Components
.classes["@mozilla.org/embedcomp/prompt-service;1"]
.getService(Components.interfaces.nsIPromptService)
.alert(
window,
gAddressBookBundle.getString("incorrectEmailAddressFormatTitle"),
gAddressBookBundle.getString("incorrectEmailAddressFormatMessage"));
// Focus the dialog field, to help the user.
document.getElementById("abTabs").selectedIndex = 0;
primaryEmail.focus();
return false;
}
return true;
}
function GenerateDisplayName()
{
if (!gEditCard.generateDisplayName)
return;
var displayName;
var firstNameValue = document.getElementById("FirstName").value;
var lastNameValue = document.getElementById("LastName").value;
if (lastNameValue && firstNameValue) {
displayName = (gEditCard.displayLastNameFirst)
? gAddressBookBundle.getFormattedString("lastFirstFormat", [lastNameValue, firstNameValue])
: gAddressBookBundle.getFormattedString("firstLastFormat", [firstNameValue, lastNameValue]);
}
else {
// one (or both) of these is empty, so this works.
displayName = firstNameValue + lastNameValue;
}
document.getElementById("DisplayName").value = displayName;
SetCardDialogTitle(displayName);
}
function DisplayNameChanged()
{
// turn off generateDisplayName if the user changes the display name
gEditCard.generateDisplayName = false;
SetCardDialogTitle(document.getElementById("DisplayName").value);
}
function SetCardDialogTitle(displayName)
{
document.title = displayName
? gAddressBookBundle.getFormattedString(gEditCard.titleProperty + "WithDisplayName", [displayName])
: gAddressBookBundle.getString(gEditCard.titleProperty);
}