Fix bug 1007040 - Autocomplete for event invitations: Use uppercase and lowercase of name like in addressbook card (regression). r=Decathlon

--HG--
extra : rebase_source : b0c9469e990f2c82d00e208f1367a56d4761b4a2
This commit is contained in:
Philipp Kewisch 2014-07-08 15:37:39 +02:00
Родитель 34234ba26a
Коммит fdca7fbd42
2 изменённых файлов: 117 добавлений и 105 удалений

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

@ -44,9 +44,10 @@
completedefaultindex="true" completedefaultindex="true"
forcecomplete="true" forcecomplete="true"
minresultsforpopup="1" minresultsforpopup="1"
onblur="if (this.localName == 'textbox') document.getBindingParent(this).onBlurInput(event);" onblur="if (this.localName == 'textbox') document.getBindingParent(this).returnHit(this, true)"
ignoreblurwhilesearching="true" ignoreblurwhilesearching="true"
oninput="this.setAttribute('dirty', 'true');"> oninput="this.setAttribute('dirty', 'true');"
ontextentered="document.getBindingParent(this).returnHit(this);">
</xul:textbox> </xul:textbox>
</xul:listcell> </xul:listcell>
</xul:listitem> </xul:listitem>
@ -66,6 +67,7 @@
<constructor><![CDATA[ <constructor><![CDATA[
Components.utils.import("resource://calendar/modules/calUtils.jsm"); Components.utils.import("resource://calendar/modules/calUtils.jsm");
Components.utils.import("resource://gre/modules/Services.jsm"); Components.utils.import("resource://gre/modules/Services.jsm");
Components.utils.import("resource:///modules/mailServices.js");
this.mMaxAttendees = 0; this.mMaxAttendees = 0;
@ -243,9 +245,9 @@
var inputValue = aAttendee.commonName; var inputValue = aAttendee.commonName;
var regexp = new RegExp("^mailto:(.*)", "i"); var regexp = new RegExp("^mailto:(.*)", "i");
if (inputValue) { if (inputValue) {
// Make the commonName appear in quotes if it // Make the commonName appear in quotes if it contains a
// contains a comma or semicolon. // character that could confuse the header parser
if (inputValue.search(/[,;]/) != -1) { if (inputValue.search(/[,;<>@]/) != -1) {
inputValue = '"' + inputValue + '"'; inputValue = '"' + inputValue + '"';
} }
var email = aAttendee.id; var email = aAttendee.id;
@ -390,19 +392,37 @@
]]></body> ]]></body>
</method> </method>
<property name="attendees"> <property name="attendees">
<getter><![CDATA[ <getter><![CDATA[
Components.utils.import("resource:///modules/mailServices.js");
let attendees = []; let attendees = [];
let inputField; let inputField;
function copyNameAttributes(email, name, attendee) {
// If the new address has no 'mailto'-prefix but seems
// to look like an email-address, we prepend the prefix.
// This also allows for non-email-addresses.
if (email.toLowerCase().indexOf("mailto:") != 0) {
if (email.indexOf("@") >= 0) {
email = "MAILTO:" + email;
}
}
attendee.id = email;
if (name && name.length > 0) {
attendee.commonName = name
}
return attendee;
}
for (let i = 1; inputField = this.getInputElement(i); i++) { for (let i = 1; inputField = this.getInputElement(i); i++) {
let fieldValue = inputField.value; if (inputField && inputField.value != "") {
if (fieldValue != "") {
// the inputfield already has a reference to the attendee // the inputfield already has a reference to the attendee
// object, we just need to fill in the name. // object, we just need to fill in the name.
let attendee = inputField.attendee.clone(); let attendee = inputField.attendee.clone();
if (attendee.isOrganizer) {
continue;
}
attendee.role = this.getRoleElement(i).getAttribute("role"); attendee.role = this.getRoleElement(i).getAttribute("role");
//attendee.participationStatus = this.getStatusElement(i).getAttribute("status"); //attendee.participationStatus = this.getStatusElement(i).getAttribute("status");
@ -414,29 +434,17 @@
let names = {}; let names = {};
let fullNames = {}; let fullNames = {};
MailServices.headerParser.parseHeadersWithArray(fieldValue, MailServices.headerParser.parseHeadersWithArray(inputField.value,
emailAddresses, emailAddresses,
names, names,
fullNames); fullNames);
if (emailAddresses.value.length > 0) { // We need to expand the attendees, this happens in case the
// If the new address has no 'mailto'-prefix but seems // user entered comma-separated attendees in one field and
// to look like an email-address, we prepend the prefix. // then clicked OK without switching to the next line.
// This also allows for non-email-addresses. for (var j = 0; j < emailAddresses.value.length; j++) {
let email = emailAddresses.value[0]; if (j > 0) attendee = attendee.clone();
if (email.toLowerCase().indexOf("mailto:") != 0) { copyNameAttributes(emailAddresses.value[j], names.value[j], attendee);
if (email.indexOf("@") >= 0) {
email = "MAILTO:" + email;
}
}
attendee.id = email;
}
if (names.value.length > 0) {
attendee.commonName = names.value[0];
}
// append the attendee object to the list of attendees.
if (!attendee.isOrganizer || i > 1) {
attendees.push(attendee); attendees.push(attendee);
} }
} }
@ -448,12 +456,9 @@
<property name="organizer"> <property name="organizer">
<getter><![CDATA[ <getter><![CDATA[
Components.utils.import("resource:///modules/mailServices.js");
let inputField; let inputField;
for (let i = 1; inputField = this.getInputElement(i); i++) { for (let i = 1; inputField = this.getInputElement(i); i++) {
let fieldValue = inputField.value; if (inputField && inputField.value != "") {
if (fieldValue != "") {
// The inputfield already has a reference to the attendee // The inputfield already has a reference to the attendee
// object, we just need to fill in the name. // object, we just need to fill in the name.
let attendee = inputField.attendee.clone(); let attendee = inputField.attendee.clone();
@ -468,7 +473,7 @@
let names = {}; let names = {};
let fullNames = {}; let fullNames = {};
MailServices.headerParser.parseHeadersWithArray(fieldValue, MailServices.headerParser.parseHeadersWithArray(inputField.value,
emailAddresses, emailAddresses,
names, names,
fullNames); fullNames);
@ -499,36 +504,9 @@
]]></getter> ]]></getter>
</property> </property>
<method name="onBlurInput">
<parameter name="event"/>
<body><![CDATA[
Components.utils.import("resource:///modules/mailServices.js");
let emailAddresses = {};
let names = {};
let fullNames = {};
MailServices.headerParser.parseHeadersWithArray(event.target.value,
emailAddresses,
names,
fullNames);
if (emailAddresses.value.length > 1) {
let firstFullName = fullNames.value.shift();
event.target.value = firstFullName;
let insertAfterItem = this.getListItem(this.getRowByInputElement(event.target));
for each (let full in fullNames.value) {
insertAfterItem = this.appendNewRow(false, insertAfterItem);
let textinput = this.getInputFromListitem(insertAfterItem);
textinput.value = full;
}
}
]]></body>
</method>
<method name="_resolveListByName"> <method name="_resolveListByName">
<parameter name="value"/> <parameter name="value"/>
<body><![CDATA[ <body><![CDATA[
Components.utils.import("resource:///modules/mailServices.js");
let emailAddresses = {}; let emailAddresses = {};
let names = {}; let names = {};
let fullNames = {}; let fullNames = {};
@ -546,8 +524,6 @@
<method name="_findListInAddrBooks"> <method name="_findListInAddrBooks">
<parameter name="entryname"/> <parameter name="entryname"/>
<body><![CDATA[ <body><![CDATA[
Components.utils.import("resource:///modules/mailServices.js");
let allAddressBooks = MailServices.ab.directories; let allAddressBooks = MailServices.ab.directories;
while (allAddressBooks.hasMoreElements()) { while (allAddressBooks.hasMoreElements()) {
@ -714,47 +690,45 @@
<method name="onModify"> <method name="onModify">
<body><![CDATA[ <body><![CDATA[
Components.utils.import("resource:///modules/mailServices.js");
let list = []; let list = [];
for (let i = 1; i <= this.mMaxAttendees; i++) { for (let i = 1; i <= this.mMaxAttendees; i++) {
// retrieve the string from the appropriate row // retrieve the string from the appropriate row
let input = this.getInputElement(i); let input = this.getInputElement(i);
let fieldValue = input.value; if (input && input.value) {
// parse the string to break this down to individual names and addresses
let email = "";
let emailAddresses = {};
let names = {};
let fullNames = {};
// parse the string to break this down to individual names and addresses MailServices.headerParser.parseHeadersWithArray(input.value,
let email = ""; emailAddresses,
let emailAddresses = {}; names,
let names = {}; fullNames);
let fullNames = {};
MailServices.headerParser.parseHeadersWithArray(fieldValue, if (emailAddresses.value.length > 0) {
emailAddresses, // if the new address has no 'mailto'-prefix but seems
names, // to look like an email-address, we prepend the prefix.
fullNames); // this also allows for non-email-addresses.
email = emailAddresses.value[0];
if (emailAddresses.value.length > 0) { if (email.toLowerCase().indexOf("mailto:") != 0) {
// if the new address has no 'mailto'-prefix but seems if (email.indexOf("@") >= 0) {
// to look like an email-address, we prepend the prefix. email = "MAILTO:" + email;
// this also allows for non-email-addresses. }
email = emailAddresses.value[0];
if (email.toLowerCase().indexOf("mailto:") != 0) {
if (email.indexOf("@") >= 0) {
email = "MAILTO:" + email;
} }
} }
}
let isdirty = false; let isdirty = false;
if (input.hasAttribute("dirty")) { if (input.hasAttribute("dirty")) {
isdirty = input.getAttribute("dirty"); isdirty = input.getAttribute("dirty");
}
input.removeAttribute("dirty");
let entry = {
dirty: isdirty,
calid: email
};
list.push(entry);
} }
input.removeAttribute("dirty");
let entry = {
dirty: isdirty,
calid: email
};
list.push(entry);
} }
let event = document.createEvent('Events'); let event = document.createEvent('Events');
@ -1061,6 +1035,54 @@
]]></setter> ]]></setter>
</property> </property>
<method name="returnHit">
<parameter name="element"/>
<parameter name="noAdvance"/>
<body><![CDATA[
function parseHeaderValue(email, name, fullname) {
if (name && name.match(/[<>@,]/)) {
return '"' + name + '" <' + email + '>';
} else if (email.length) {
return fullname;
} else {
return name;
}
}
let arrowLength = 1;
if (element.value.contains(",")) {
let strippedAddresses = element.value.replace(/.* >> /, "");
let emailAddresses = {};
let names = {};
let fullNames = {};
MailServices.headerParser.parseHeadersWithArray(strippedAddresses,
emailAddresses,
names,
fullNames);
emailAddresses = emailAddresses.value || [];
names = names.value || [];
fullNames = fullNames.value || [];
if (emailAddresses.length > 1) {
element.value = parseHeaderValue(emailAddresses[0], names[0], fullNames[0]);
let insertAfterItem = this.getListItem(this.getRowByInputElement(element));
for (let i = 1; i < fullNames.length; i++) {
insertAfterItem = this.appendNewRow(false, insertAfterItem);
let textinput = this.getInputFromListitem(insertAfterItem);
textinput.value = parseHeaderValue(emailAddresses[i], names[i], fullNames[i]);
}
}
arrowLength = emailAddresses.length;
}
if (!noAdvance) {
this.arrowHit(element, arrowLength);
}
]]></body>
</method>
<method name="arrowHit"> <method name="arrowHit">
<parameter name="aElement"/> <parameter name="aElement"/>
<parameter name="aDirection"/> <parameter name="aDirection"/>
@ -1088,7 +1110,7 @@
<parameter name="aElement"/> <parameter name="aElement"/>
<body><![CDATA[ <body><![CDATA[
// don't delete the row if it's the last one remaining // don't delete the row if it's the last one remaining
if (this.mMaxAttendees <= 1) { if (this.mMaxAttendees <= 2) {
return; return;
} }
@ -1210,11 +1232,6 @@
} }
event.stopPropagation(); event.stopPropagation();
break; break;
case KeyEvent.DOM_VK_RETURN:
this.arrowHit(event.originalTarget, 1);
event.stopPropagation();
event.preventDefault();
break;
} }
} }
]]></handler> ]]></handler>
@ -1240,12 +1257,6 @@
break; break;
case KeyEvent.DOM_VK_TAB: case KeyEvent.DOM_VK_TAB:
this.arrowHit(event.originalTarget, event.shiftKey ? -1 : +1); this.arrowHit(event.originalTarget, event.shiftKey ? -1 : +1);
event.stopPropagation();
event.preventDefault();
break;
case KeyEvent.DOM_VK_RETURN:
event.stopPropagation();
event.preventDefault();
break; break;
} }
} }

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

@ -20,6 +20,7 @@
onload="onLoad()" onload="onLoad()"
ondialogaccept="return onAccept();" ondialogaccept="return onAccept();"
ondialogcancel="return onCancel();" ondialogcancel="return onCancel();"
defaultButton="none"
persist="screenX screenY height width" persist="screenX screenY height width"
orient="vertical" orient="vertical"
style="padding-top: 8px; padding-bottom: 10px; -moz-padding-start: 8px; -moz-padding-end: 10px;" style="padding-top: 8px; padding-bottom: 10px; -moz-padding-start: 8px; -moz-padding-end: 10px;"