!import
1 //@line 38 "/home/visbrero/mnt/roisin/rev_control/hg/mozilla/mail/components/addrbook/content/abCardOverlay.js"
2
3 const kNonVcardFields =
4 ["nickNameContainer", "secondaryEmailContainer", "screenNameContainer",
5 "homeAddressGroup", "customFields", "allowRemoteContent"];
6
7 const kPhoneticFields =
8 ["PhoneticLastName", "PhoneticLabel1", "PhoneticSpacer1",
9 "PhoneticFirstName", "PhoneticLabel2", "PhoneticSpacer2"];
10
11 // Item is |[dialogField, cardProperty]|.
12 const kVcardFields =
13 [ // Contact > Name
14 ["FirstName", "firstName"],
15 ["LastName", "lastName"],
16 ["DisplayName", "displayName"],
17 ["NickName", "nickName"],
18 // Contact > Internet
19 ["PrimaryEmail", "primaryEmail"],
20 ["SecondEmail", "secondEmail"],
21 ["ScreenName", "aimScreenName"], // NB: AIM.
22 // Contact > Phones
23 ["WorkPhone", "workPhone"],
24 ["HomePhone", "homePhone"],
25 ["FaxNumber", "faxNumber"],
26 ["PagerNumber", "pagerNumber"],
27 ["CellularNumber", "cellularNumber"],
28 // Address > Home
29 ["HomeAddress", "homeAddress"],
30 ["HomeAddress2", "homeAddress2"],
31 ["HomeCity", "homeCity"],
32 ["HomeState", "homeState"],
33 ["HomeZipCode", "homeZipCode"],
34 ["HomeCountry", "homeCountry"],
35 ["WebPage2", "webPage2"],
36 // Address > Work
37 ["JobTitle", "jobTitle"],
38 ["Department", "department"],
39 ["Company", "company"],
40 ["WorkAddress", "workAddress"],
41 ["WorkAddress2", "workAddress2"],
42 ["WorkCity", "workCity"],
43 ["WorkState", "workState"],
44 ["WorkZipCode", "workZipCode"],
45 ["WorkCountry", "workCountry"],
46 ["WebPage1", "webPage1"],
47 // Other > (custom)
48 ["Custom1", "custom1"],
49 ["Custom2", "custom2"],
50 ["Custom3", "custom3"],
51 ["Custom4", "custom4"],
52 // Other > Notes
53 ["Notes", "notes"]];
54
55 var gEditCard;
56 var gOnSaveListeners = new Array();
57 var gOkCallback = null;
58 var gHideABPicker = false;
59
OnLoadNewCard
60 function OnLoadNewCard()
61 {
62 InitEditCard();
63
64 gEditCard.card =
65 (("arguments" in window) && (window.arguments.length > 0) &&
66 (window.arguments[0] instanceof Components.interfaces.nsIAbCard))
67 ? window.arguments[0]
68 : Components.classes["@mozilla.org/addressbook/cardproperty;1"]
69 .createInstance(Components.interfaces.nsIAbCard);
70 gEditCard.titleProperty = "newCardTitle";
71 gEditCard.selectedAB = "";
72
73 if ("arguments" in window && window.arguments[0])
74 {
75 gEditCard.selectedAB = kPersonalAddressbookURI;
76
77 if ("selectedAB" in window.arguments[0]) {
78 // check if selected ab is a mailing list
79 var abURI = window.arguments[0].selectedAB;
80
81 var directory = GetDirectoryFromURI(abURI);
82 if (directory.isMailList) {
83 var parentURI = GetParentDirectoryFromMailingListURI(abURI);
84 if (parentURI)
85 gEditCard.selectedAB = parentURI;
86 }
87 else if (directory.operations & directory.opWrite)
88 gEditCard.selectedAB = window.arguments[0].selectedAB;
89 }
90
91 // we may have been given properties to pre-initialize the window with....
92 // we'll fill these in here...
93 if ("primaryEmail" in window.arguments[0])
94 gEditCard.card.primaryEmail = window.arguments[0].primaryEmail;
95 if ("displayName" in window.arguments[0]) {
96 gEditCard.card.displayName = window.arguments[0].displayName;
97 // if we've got a display name, don't generate
98 // a display name (and stomp on the existing display name)
99 // when the user types a first or last name
100 if (gEditCard.card.displayName.length)
101 gEditCard.generateDisplayName = false;
102 }
103 if ("aimScreenName" in window.arguments[0])
104 gEditCard.card.aimScreenName = window.arguments[0].aimScreenName;
105
106 if ("allowRemoteContent" in window.arguments[0]) {
107 gEditCard.card.allowRemoteContent = window.arguments[0].allowRemoteContent;
108 window.arguments[0].allowRemoteContent = false;
109 }
110
111 if ("okCallback" in window.arguments[0])
112 gOkCallback = window.arguments[0].okCallback;
113
114 if ("escapedVCardStr" in window.arguments[0]) {
115 // hide non vcard values
116 HideNonVcardFields();
117 gEditCard.card =
118 Components.classes["@mozilla.org/abmanager;1"]
119 .getService(Components.interfaces.nsIAbManager)
120 .escapedVCardToAbCard(window.arguments[0].escapedVCardStr);
121 }
122
123 if ("titleProperty" in window.arguments[0])
124 gEditCard.titleProperty = window.arguments[0].titleProperty;
125
126 if ("hideABPicker" in window.arguments[0])
127 gHideABPicker = window.arguments[0].hideABPicker;
128 }
129
130 // set popup with address book names
131 var abPopup = document.getElementById('abPopup');
132 abPopup.value = gEditCard.selectedAB || kPersonalAddressbookURI;
133
134 if (gHideABPicker && abPopup) {
135 abPopup.hidden = true;
136 document.getElementById("abPopupLabel").hidden = true;
137 }
138
139 SetCardDialogTitle(gEditCard.card.displayName);
140
141 GetCardValues(gEditCard.card, document);
142
143 // FIX ME - looks like we need to focus on both the text field and the tab widget
144 // probably need to do the same in the addressing widget
145
146 // focus on first or last name based on the pref
147 var focus = document.getElementById(gEditCard.displayLastNameFirst
148 ? "LastName" : "FirstName");
149 if ( focus ) {
150 // XXX Using the setTimeout hack until bug 103197 is fixed
anon:151:16
151 setTimeout( function(firstTextBox) { firstTextBox.focus(); }, 0, focus );
152 }
153 moveToAlertPosition();
154 }
155
156 // @Returns The index in addressLists for the card that is being saved;
157 // or |-1| if the card is not found.
findCardIndex
158 function findCardIndex(directory)
159 {
160 var i = directory.addressLists.Count();
161 while (i-- > 0) {
162 var card = directory.addressLists.QueryElementAt(i, Components.interfaces.nsIAbCard);
163 if (gEditCard.card.equals(card))
164 break;
165 }
166 return i;
167 }
168
EditCardOKButton
169 function EditCardOKButton()
170 {
171 if (!CheckCardRequiredDataPresence(document))
172 return false; // don't close window
173
174 // See if this card is in any mailing list
175 // if so then we need to update the addresslists of those mailing lists
176 var index = -1;
177 var directory = GetDirectoryFromURI(gEditCard.abURI);
178
179 // if the directory is a mailing list we need to search all the mailing lists
180 // in the parent directory if the card exists.
181 if (directory.isMailList) {
182 var parentURI = GetParentDirectoryFromMailingListURI(gEditCard.abURI);
183 directory = GetDirectoryFromURI(parentURI);
184 }
185
186 var listDirectoriesCount = directory.addressLists.Count();
187 var foundDirectories = new Array();
188 var foundDirectoriesCount = 0;
189 var i;
190 // create a list of mailing lists and the index where the card is at.
191 for ( i=0; i < listDirectoriesCount; i++ ) {
192 var subdirectory = directory.addressLists.QueryElementAt(i, Components.interfaces.nsIAbDirectory);
193 index = findCardIndex(subdirectory);
194 if (index > -1)
195 {
196 foundDirectories[foundDirectoriesCount] = {directory:subdirectory, index:index};
197 foundDirectoriesCount++;
198 }
199 }
200
201 CheckAndSetCardValues(gEditCard.card, document, false);
202
203 directory.modifyCard(gEditCard.card);
204
205 for (i=0; i < foundDirectoriesCount; i++) {
206 // Update the addressLists item for this card
207 foundDirectories[i].directory.addressLists.
208 SetElementAt(foundDirectories[i].index, gEditCard.card);
209 }
210
211 NotifySaveListeners(directory);
212
213 // callback to allow caller to update
214 if (gOkCallback)
215 gOkCallback();
216
217 return true; // close the window
218 }
219
OnLoadEditCard
220 function OnLoadEditCard()
221 {
222 InitEditCard();
223
224 gEditCard.titleProperty = "editCardTitle";
225
226 if (window.arguments && window.arguments[0])
227 {
228 if ( window.arguments[0].card )
229 gEditCard.card = window.arguments[0].card;
230 if ( window.arguments[0].okCallback )
231 gOkCallback = window.arguments[0].okCallback;
232 if ( window.arguments[0].abURI )
233 gEditCard.abURI = window.arguments[0].abURI;
234 }
235
236 // set global state variables
237 // if first or last name entered, disable generateDisplayName
238 if (gEditCard.generateDisplayName &&
239 (gEditCard.card.firstName.length +
240 gEditCard.card.lastName.length +
241 gEditCard.card.displayName.length > 0))
242 {
243 gEditCard.generateDisplayName = false;
244 }
245
246 GetCardValues(gEditCard.card, document);
247
248 SetCardDialogTitle(gEditCard.card.displayName);
249
250 // check if selectedAB is a writeable
251 // if not disable all the fields
252 if ("arguments" in window && window.arguments[0])
253 {
254 if ("abURI" in window.arguments[0]) {
255 var abURI = window.arguments[0].abURI;
256 var directory = GetDirectoryFromURI(abURI);
257
258 if (!(directory.operations & directory.opWrite))
259 {
260 // Set all the editable vcard fields to read only
261 for (var i = kVcardFields.length; i-- > 0; )
262 document.getElementById(kVcardFields[i][0]).readOnly = true;
263
264 // And the phonetic fields
265 document.getElementById(kPhoneticFields[0]).readOnly = true;
266 document.getElementById(kPhoneticFields[3]).readOnly = true;
267
268 // Also disable the mail format popup.
269 document.getElementById("PreferMailFormatPopup").disabled = true;
270
271 document.documentElement.buttons = "accept";
272 document.documentElement.removeAttribute("ondialogaccept");
273 }
274
275 // hide remote content in HTML field for remote directories
276 if (directory.isRemote)
277 document.getElementById('allowRemoteContent').hidden = true;
278 }
279 }
280 }
281
282 // this is used by people who extend the ab card dialog
283 // like Netscape does for screenname
RegisterSaveListener
284 function RegisterSaveListener(func)
285 {
286 gOnSaveListeners[gOnSaveListeners.length] = func;
287 }
288
289 // this is used by people who extend the ab card dialog
290 // like Netscape does for screenname
NotifySaveListeners
291 function NotifySaveListeners(directory)
292 {
293 if (!gOnSaveListeners.length)
294 return;
295
296 for ( var i = 0; i < gOnSaveListeners.length; i++ )
297 gOnSaveListeners[i]();
298
299 // the save listeners might have tweaked the card
300 // in which case we need to commit it.
301 directory.modifyCard(gEditCard.card);
302 }
303
InitPhoneticFields
304 function InitPhoneticFields()
305 {
306 var showPhoneticFields =
307 gPrefs.getComplexValue("mail.addr_book.show_phonetic_fields",
308 Components.interfaces.nsIPrefLocalizedString).data;
309
310 // hide phonetic fields if indicated by the pref
311 if (showPhoneticFields == "true")
312 {
313 for (var i = kPhoneticFields.length; i-- > 0; )
314 document.getElementById(kPhoneticFields[i]).hidden = false;
315 }
316 }
317
InitEditCard
318 function InitEditCard()
319 {
320 InitPhoneticFields();
321
322 InitCommonJS();
323
324 // Create gEditCard object that contains global variables for the current js
325 // file.
326 gEditCard = new Object();
327
328 gEditCard.prefs = gPrefs;
329
330 // get specific prefs that gEditCard will need
331 try {
332 var displayLastNameFirst =
333 gPrefs.getComplexValue("mail.addr_book.displayName.lastnamefirst",
334 Components.interfaces.nsIPrefLocalizedString).data;
335 gEditCard.displayLastNameFirst = (displayLastNameFirst == "true");
336 gEditCard.generateDisplayName =
337 gPrefs.getBoolPref("mail.addr_book.displayName.autoGeneration");
338 }
339 catch (ex) {
340 dump("ex: failed to get pref" + ex + "\n");
341 }
342 }
343
NewCardOKButton
344 function NewCardOKButton()
345 {
346 if (gOkCallback)
347 {
348 if (!CheckAndSetCardValues(gEditCard.card, document, true))
349 return false; // don't close window
350
351 gOkCallback(gEditCard.card.convertToEscapedVCard());
352 return true; // close the window
353 }
354
355 var popup = document.getElementById('abPopup');
356 if ( popup )
357 {
358 var uri = popup.getAttribute('value');
359
360 // FIX ME - hack to avoid crashing if no ab selected because of blank option bug from template
361 // should be able to just remove this if we are not seeing blank lines in the ab popup
362 if ( !uri )
363 return false; // don't close window
364 // -----
365
366 if (gEditCard.card)
367 {
368 if (!CheckAndSetCardValues(gEditCard.card, document, true))
369 return false; // don't close window
370
371 // replace gEditCard.card with the card we added
372 // so that save listeners can get / set attributes on
373 // the card that got created.
374 gEditCard.card = GetDirectoryFromURI(uri).addCard(gEditCard.card);
375 NotifySaveListeners();
376 if ("arguments" in window && window.arguments[0])
377 window.arguments[0].allowRemoteContent = gEditCard.card.allowRemoteContent;
378 }
379 }
380
381 return true; // close the window
382 }
383
384 // Move the data from the cardproperty to the dialog
GetCardValues
385 function GetCardValues(cardproperty, doc)
386 {
387 if (!cardproperty)
388 return;
389
390 for (var i = kVcardFields.length; i-- > 0; )
391 doc.getElementById(kVcardFields[i][0]).value =
392 cardproperty[kVcardFields[i][1]];
393
394 var popup = document.getElementById("PreferMailFormatPopup");
395 if (popup)
396 popup.value = cardproperty.preferMailFormat;
397
398 var allowRemoteContentEl = document.getElementById("allowRemoteContent");
399 if (allowRemoteContentEl)
400 allowRemoteContentEl.checked = cardproperty.allowRemoteContent;
401
402 // get phonetic fields if exist
403 try {
404 doc.getElementById("PhoneticFirstName").value = cardproperty.phoneticFirstName;
405 doc.getElementById("PhoneticLastName").value = cardproperty.phoneticLastName;
406 }
407 catch (ex) {}
408 }
409
410 // when the ab card dialog is being loaded to show a vCard,
411 // hide the fields which aren't supported
412 // by vCard so the user does not try to edit them.
HideNonVcardFields
413 function HideNonVcardFields()
414 {
415 for (var i = kNonVcardFields.length; i-- > 0; )
416 document.getElementById(kNonVcardFields[i]).collapsed = true;
417 }
418
419 // Move the data from the dialog to the cardproperty to be stored in the database
420 // @Returns false - Some required data are missing (card values were not set);
421 // true - Card values were set, or there is no card to set values on.
CheckAndSetCardValues
422 function CheckAndSetCardValues(cardproperty, doc, check)
423 {
424 // If requested, check the required data presence.
425 if (check && !CheckCardRequiredDataPresence(document))
426 return false;
427
428 if (!cardproperty)
429 return true;
430
431 for (var i = kVcardFields.length; i-- > 0; )
432 cardproperty[kVcardFields[i][1]] =
433 doc.getElementById(kVcardFields[i][0]).value;
434
435 var popup = document.getElementById("PreferMailFormatPopup");
436 if (popup)
437 cardproperty.preferMailFormat = popup.value;
438
439 var allowRemoteContentEl = document.getElementById("allowRemoteContent");
440 if (allowRemoteContentEl)
441 cardproperty.allowRemoteContent = allowRemoteContentEl.checked;
442
443 // set phonetic fields if exist
444 try {
445 cardproperty.phoneticFirstName = doc.getElementById("PhoneticFirstName").value;
446 cardproperty.phoneticLastName = doc.getElementById("PhoneticLastName").value;
447 }
448 catch (ex) {}
449
450 return true;
451 }
452
CleanUpWebPage
453 function CleanUpWebPage(webPage)
454 {
455 // no :// yet so we should add something
456 if ( webPage.length && webPage.search("://") == -1 )
457 {
458 // check for missing / on http://
459 if ( webPage.substr(0, 6) == "http:/" )
460 return( "http://" + webPage.substr(6) );
461 else
462 return( "http://" + webPage );
463 }
464 else
465 return(webPage);
466 }
467
468 // @Returns false - Some required data are missing;
469 // true - All required data are present.
CheckCardRequiredDataPresence
470 function CheckCardRequiredDataPresence(doc)
471 {
472 // Bug 314995 We require at least one of the following fields to be
473 // filled in: email address, first name, last name, display name,
474 // organization (company name).
475 var primaryEmail = doc.getElementById("PrimaryEmail");
476 if (primaryEmail.textLength == 0 &&
477 doc.getElementById("FirstName").textLength == 0 &&
478 doc.getElementById("LastName").textLength == 0 &&
479 doc.getElementById("DisplayName").textLength == 0 &&
480 doc.getElementById("Company").textLength == 0)
481 {
482 Components
483 .classes["@mozilla.org/embedcomp/prompt-service;1"]
484 .getService(Components.interfaces.nsIPromptService)
485 .alert(
486 window,
487 gAddressBookBundle.getString("cardRequiredDataMissingTitle"),
488 gAddressBookBundle.getString("cardRequiredDataMissingMessage"));
489
490 return false;
491 }
492
493 // Simple checks that the primary email should be of the form |user@host|.
494 // Note: if the length of the primary email is 0 then we skip the check
495 // as some other field must have something as per the check above.
496 if (primaryEmail.textLength != 0 && !/.@./.test(primaryEmail.value))
497 {
498 Components
499 .classes["@mozilla.org/embedcomp/prompt-service;1"]
500 .getService(Components.interfaces.nsIPromptService)
501 .alert(
502 window,
503 gAddressBookBundle.getString("incorrectEmailAddressFormatTitle"),
504 gAddressBookBundle.getString("incorrectEmailAddressFormatMessage"));
505
506 // Focus the dialog field, to help the user.
507 document.getElementById("abTabs").selectedIndex = 0;
508 primaryEmail.focus();
509
510 return false;
511 }
512
513 return true;
514 }
515
GenerateDisplayName
516 function GenerateDisplayName()
517 {
518 if (!gEditCard.generateDisplayName)
519 return;
520
521 var displayName;
522
523 var firstNameValue = document.getElementById("FirstName").value;
524 var lastNameValue = document.getElementById("LastName").value;
525 if (lastNameValue && firstNameValue) {
526 displayName = (gEditCard.displayLastNameFirst)
527 ? gAddressBookBundle.getFormattedString("lastFirstFormat", [lastNameValue, firstNameValue])
528 : gAddressBookBundle.getFormattedString("firstLastFormat", [firstNameValue, lastNameValue]);
529 }
530 else {
531 // one (or both) of these is empty, so this works.
532 displayName = firstNameValue + lastNameValue;
533 }
534
535 document.getElementById("DisplayName").value = displayName;
536
537 SetCardDialogTitle(displayName);
538 }
539
DisplayNameChanged
540 function DisplayNameChanged()
541 {
542 // turn off generateDisplayName if the user changes the display name
543 gEditCard.generateDisplayName = false;
544
545 SetCardDialogTitle(document.getElementById("DisplayName").value);
546 }
547
SetCardDialogTitle
548 function SetCardDialogTitle(displayName)
549 {
550 document.title = displayName
551 ? gAddressBookBundle.getFormattedString(gEditCard.titleProperty + "WithDisplayName", [displayName])
552 : gAddressBookBundle.getString(gEditCard.titleProperty);
553 }