mirror of
https://github.com/moparisthebest/mail
synced 2024-11-22 17:02:17 -05:00
[WO-201] fix address input for multiple recipients in writer
This commit is contained in:
parent
798b68cc7e
commit
7bede604c6
@ -88,19 +88,7 @@ define(function(require) {
|
|||||||
* This event is fired when editing the email address headers. It checks is space is pressed and if so, creates a new address field.
|
* This event is fired when editing the email address headers. It checks is space is pressed and if so, creates a new address field.
|
||||||
*/
|
*/
|
||||||
$scope.onAddressUpdate = function(field, index) {
|
$scope.onAddressUpdate = function(field, index) {
|
||||||
var recipient = field[index],
|
var recipient = field[index];
|
||||||
address = recipient.address;
|
|
||||||
|
|
||||||
// handle number of email inputs for multiple recipients
|
|
||||||
if (address.indexOf(' ') !== -1) {
|
|
||||||
recipient.address = address.replace(' ', '');
|
|
||||||
field.push({
|
|
||||||
address: ''
|
|
||||||
});
|
|
||||||
} else if (address.length === 0 && field.length > 1) {
|
|
||||||
field.splice(field.indexOf(recipient), 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
$scope.verify(recipient);
|
$scope.verify(recipient);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -319,9 +307,9 @@ define(function(require) {
|
|||||||
return {
|
return {
|
||||||
//scope: true, // optionally create a child scope
|
//scope: true, // optionally create a child scope
|
||||||
link: function(scope, element) {
|
link: function(scope, element) {
|
||||||
element[0].onclick = function() {
|
element.on('click', function() {
|
||||||
element[0].children[0].focus();
|
element[0].children[0].focus();
|
||||||
};
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
@ -330,6 +318,7 @@ define(function(require) {
|
|||||||
return {
|
return {
|
||||||
require: 'ngModel',
|
require: 'ngModel',
|
||||||
link: function(scope, elm, attrs) {
|
link: function(scope, elm, attrs) {
|
||||||
|
// resize text input depending on value length
|
||||||
var model = $parse(attrs.autoSize);
|
var model = $parse(attrs.autoSize);
|
||||||
scope.$watch(model, function(value) {
|
scope.$watch(model, function(value) {
|
||||||
var width;
|
var width;
|
||||||
@ -346,21 +335,88 @@ define(function(require) {
|
|||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
ngModule.directive('addressInput', function($timeout) {
|
function addInput(field, scope) {
|
||||||
|
field.push({
|
||||||
|
address: ''
|
||||||
|
});
|
||||||
|
scope.$apply();
|
||||||
|
}
|
||||||
|
|
||||||
|
function checkForEmptyInput(field) {
|
||||||
|
var emptyFieldExists = false;
|
||||||
|
field.forEach(function(recipient) {
|
||||||
|
if (!recipient.address) {
|
||||||
|
emptyFieldExists = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return emptyFieldExists;
|
||||||
|
}
|
||||||
|
|
||||||
|
ngModule.directive('field', function() {
|
||||||
|
return {
|
||||||
|
//scope: true, // optionally create a child scope
|
||||||
|
link: function(scope, element, attrs) {
|
||||||
|
element.on('click', function() {
|
||||||
|
var fieldName = attrs.field;
|
||||||
|
var field = scope[fieldName];
|
||||||
|
|
||||||
|
if (!checkForEmptyInput(field)) {
|
||||||
|
// create new field input if no empy one exists
|
||||||
|
addInput(field, scope);
|
||||||
|
}
|
||||||
|
|
||||||
|
// focus on last input when clicking on field
|
||||||
|
var id = fieldName + (field.length - 1);
|
||||||
|
document.getElementById(id).focus();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
ngModule.directive('addressInput', function() {
|
||||||
return {
|
return {
|
||||||
//scope: true, // optionally create a child scope
|
//scope: true, // optionally create a child scope
|
||||||
link: function(scope, element, attrs) {
|
link: function(scope, element, attrs) {
|
||||||
// get prefix for id
|
// get prefix for id
|
||||||
var idPrefix = attrs.addressInput;
|
var fieldName = attrs.addressInput;
|
||||||
element.bind('keydown', function(e) {
|
var field = scope[fieldName];
|
||||||
if (e.keyCode === 32) {
|
var index = parseInt(attrs.id.replace(fieldName, ''), 10);
|
||||||
// space -> go to next input
|
|
||||||
$timeout(function() {
|
element.on('click', function(e) {
|
||||||
// find next input and focus
|
// focus on this one and dont bubble to field click handler
|
||||||
var index = attrs.id.replace(idPrefix, '');
|
e.stopPropagation();
|
||||||
var nextId = idPrefix + (parseInt(index, 10) + 1);
|
});
|
||||||
document.getElementById(nextId).focus();
|
|
||||||
}, 100);
|
element.on('blur', function() {
|
||||||
|
if (!checkForEmptyInput(field)) {
|
||||||
|
// create new field input
|
||||||
|
addInput(field, scope);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
element.on('keydown', function(e) {
|
||||||
|
var code = e.keyCode;
|
||||||
|
|
||||||
|
if (code === 32 || code === 188 || code === 186) {
|
||||||
|
// catch space, comma, semicolon
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
// create new field input
|
||||||
|
addInput(field, scope);
|
||||||
|
// find next input and focus
|
||||||
|
var nextId = fieldName + (index + 1);
|
||||||
|
document.getElementById(nextId).focus();
|
||||||
|
|
||||||
|
} else if ((code === 8 || code === 46) && !field[index].address && field.length > 1) {
|
||||||
|
// backspace, delete on empty input
|
||||||
|
// remove input
|
||||||
|
e.preventDefault();
|
||||||
|
field.splice(index, 1);
|
||||||
|
scope.$apply();
|
||||||
|
// focus on previous id
|
||||||
|
var previousId = fieldName + (index - 1);
|
||||||
|
document.getElementById(previousId).focus();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -24,6 +24,7 @@
|
|||||||
p {
|
p {
|
||||||
margin: 0.2em 0;
|
margin: 0.2em 0;
|
||||||
padding: 0.2em 0;
|
padding: 0.2em 0;
|
||||||
|
cursor: text;
|
||||||
}
|
}
|
||||||
|
|
||||||
span {
|
span {
|
||||||
|
@ -7,13 +7,13 @@
|
|||||||
|
|
||||||
<div class="view-write">
|
<div class="view-write">
|
||||||
<div class="headers">
|
<div class="headers">
|
||||||
<p>
|
<p field="to">
|
||||||
<span>To:</span>
|
<span>To:</span>
|
||||||
<span ng-repeat="recipient in to track by $index">
|
<span ng-repeat="recipient in to track by $index">
|
||||||
<input id="to{{$index}}" value="{{recipient.address}}" ng-model="recipient.address" ng-trim="false" ng-class="{'label': recipient.secure === true, 'label label-primary': recipient.secure === false && recipient.valid !== true}" auto-size="recipient.address" spellcheck="false" ng-change="onAddressUpdate(to, $index)" address-input="to" tabindex="1" focus-me="state.writer.open && writerTitle !== 'Reply'">
|
<input id="to{{$index}}" value="{{recipient.address}}" ng-model="recipient.address" ng-trim="false" ng-class="{'label': recipient.secure === true, 'label label-primary': recipient.secure === false && recipient.valid !== true}" auto-size="recipient.address" spellcheck="false" ng-change="onAddressUpdate(to, $index)" address-input="to" tabindex="1" focus-me="state.writer.open && writerTitle !== 'Reply'">
|
||||||
</span>
|
</span>
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p field="cc">
|
||||||
<span>Cc:</span>
|
<span>Cc:</span>
|
||||||
<span ng-repeat="recipient in cc track by $index">
|
<span ng-repeat="recipient in cc track by $index">
|
||||||
<input id="cc{{$index}}" value="{{recipient.address}}" ng-model="recipient.address" ng-trim="false" ng-class="{'label': recipient.secure === true, 'label label-primary': recipient.secure === false && recipient.valid !== true}" auto-size="recipient.address" spellcheck="false" ng-change="onAddressUpdate(cc, $index)" address-input="cc" tabindex="1">
|
<input id="cc{{$index}}" value="{{recipient.address}}" ng-model="recipient.address" ng-trim="false" ng-class="{'label': recipient.secure === true, 'label label-primary': recipient.secure === false && recipient.valid !== true}" auto-size="recipient.address" spellcheck="false" ng-change="onAddressUpdate(cc, $index)" address-input="cc" tabindex="1">
|
||||||
|
@ -126,42 +126,6 @@ define(function(require) {
|
|||||||
scope.verify.restore();
|
scope.verify.restore();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should add new field item if space is pressed', function() {
|
|
||||||
var to = [{
|
|
||||||
address: 'asdf@asdf.de '
|
|
||||||
}];
|
|
||||||
scope.onAddressUpdate(to, 0);
|
|
||||||
|
|
||||||
expect(to.length).to.equal(2);
|
|
||||||
expect(to[0].address).to.equal('asdf@asdf.de');
|
|
||||||
expect(to[1].address).to.equal('');
|
|
||||||
expect(verifyMock.calledOnce).to.be.true;
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should remove field item if address is empty', function() {
|
|
||||||
var to = [{
|
|
||||||
address: 'asdf@asdf.de'
|
|
||||||
}, {
|
|
||||||
address: ''
|
|
||||||
}];
|
|
||||||
scope.onAddressUpdate(to, 1);
|
|
||||||
|
|
||||||
expect(to.length).to.equal(1);
|
|
||||||
expect(to[0].address).to.equal('asdf@asdf.de');
|
|
||||||
expect(verifyMock.calledOnce).to.be.true;
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should not remove last field item if address is empty', function() {
|
|
||||||
var to = [{
|
|
||||||
address: ''
|
|
||||||
}];
|
|
||||||
scope.onAddressUpdate(to, 0);
|
|
||||||
|
|
||||||
expect(to.length).to.equal(1);
|
|
||||||
expect(to[0].address).to.equal('');
|
|
||||||
expect(verifyMock.calledOnce).to.be.true;
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should do nothing for normal address', function() {
|
it('should do nothing for normal address', function() {
|
||||||
var to = [{
|
var to = [{
|
||||||
address: 'asdf@asdf.de'
|
address: 'asdf@asdf.de'
|
||||||
|
Loading…
Reference in New Issue
Block a user