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:
Родитель
34234ba26a
Коммит
fdca7fbd42
|
@ -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;"
|
||||||
|
|
Загрузка…
Ссылка в новой задаче