Skip to content

Commit

Permalink
[mms] Contacts popup now does address search dynamically, without the…
Browse files Browse the repository at this point in the history
… need to reload the page.
  • Loading branch information
slusarz committed Nov 6, 2014
1 parent a1a51d3 commit 639a092
Show file tree
Hide file tree
Showing 8 changed files with 189 additions and 125 deletions.
2 changes: 2 additions & 0 deletions imp/docs/CHANGES
Expand Up @@ -2,6 +2,8 @@
v7.0.0-git
----------

[mms] Contacts popup now does address search dynamically, without the need to
reload the page.
[mms] Remove 'mailboxarray' hook.
[mms] Remove 'display_folder' hook.
[mms] Auto-detect EAI support on mail backends and provide validation feedback
Expand Down
45 changes: 20 additions & 25 deletions imp/js/compose.js
Expand Up @@ -1362,35 +1362,30 @@ var ImpCompose = {

onContactsUpdate: function(e)
{
var elt = $(e.memo.field),
v = $F(elt).strip(),
pos = v.lastIndexOf(',');

switch (e.memo.field) {
case 'bcc':
case 'cc':
if (!$('send' + e.memo.field).visible()) {
this.toggleCC(e.memo.field);
}
break;
Object.keys(e.memo).each(function(k) {
var add = [];

switch (k) {
case 'bcc':
case 'cc':
if (!$('send' + k).visible()) {
this.toggleCC(k);
}
break;

case 'to':
if (DimpCore.conf.redirect) {
e.memo.field = 'redirect_to';
case 'to':
if (DimpCore.conf.redirect) {
k = 'redirect_to';
}
break;
}
break;
}

if (v.empty()) {
v = '';
} else if (pos != (v.length - 1)) {
v += ', ';
} else {
v += ' ';
}
e.memo[k].each(function(a) {
add.push(new IMP_Autocompleter_Elt(a));
});

elt.setValue(v + e.memo.value + ', ');
document.fire('AutoComplete:reset');
this.ac.get(k).addNewItems(add);
}, this);
},

tasksHandler: function(e)
Expand Down
147 changes: 87 additions & 60 deletions imp/js/contacts.js
Expand Up @@ -8,79 +8,58 @@

var ImpContacts = {

_passAddresses: function()
{
var sa = '';

$('selected_addresses').childElements().each(function(s) {
if (s.value) {
sa += s.value + '|';
}
});

$('sa').setValue(sa);
},

sameOption: function(f, item, itemj)
{
var t = f + ": " + item.value,
tj = itemj.value;

return Try.these(
function() {
return (t == tj) || (decodeURIComponent(t) == decodeURIComponent(tj));
},
// Catch exception with NS 7.1
function() {
return (t == tj);
}
);
},
// initial,
// text,

addAddress: function(f)
{
var d, l, option, s = $('search_results');
var df = document.createDocumentFragment(),
sa = $('selected_addresses').select('[value]'),
sr = $('search_results'),
sel = $F(sr);

if (!$F(s).size()) {
if (!sel.size()) {
alert(this.text.select);
} else {
d = $('selected_addresses');
l = $A(d).size();
s.childElements().each(function(i) {
if (i.value && i.selected) {
if (!$A(d).any(function(j) {
return this.sameOption(f, i, j);
}, this)) {
option = f + ': ' + i.value;
d[l++] = new Option(option, option);
}
}
}, this);
return;
}

sel.each(function(s) {
if (!sa.any(function(j) {
return (j.readAttribute('value') == s) &&
(j.retrieve('header') == f);
})) {
df.appendChild(
new Element('OPTION', { value: s })
.store('header', f)
.insert(f + ': ' + s.escapeHTML())
);
}
});

$('selected_addresses').appendChild(df);
},

updateMessage: function()
{
var addr = {};

if (!parent.opener) {
alert(this.text.closed);
window.close();
return;
}

$('selected_addresses').childElements().each(function(s) {
var pos,
address = s.value;

if (!address.empty()) {
pos = address.indexOf(':');
$('selected_addresses').select('[value]').each(function(s) {
var field = s.retrieve('header');

$(parent.opener.document).fire('ImpContacts:update', {
field: address.substring(0, pos),
value: address.substring(pos + 2, address.length)
});
if (Object.isUndefined(addr[field])) {
addr[field] = [];
}

addr[field].push(s.readAttribute('value'));
});

$(parent.opener.document).fire('ImpContacts:update', addr);
window.close();
},

Expand All @@ -93,22 +72,66 @@ var ImpContacts = {
});
},

resize: function()
contactsSearch: function()
{
window.resizeBy(0, Math.max(0, document.body.clientHeight - document.viewport.getHeight()));
var sr = $('search_results');

sr.select('[value]').invoke('remove');
sr.childElements().invoke('hide');
sr.appendChild(
new Element('OPTION', { disabled: true, value: "" })
.insert(this.text.searching)
);

HordeCore.doAction('contactsSearch', {
search: $F('search'),
source: $F('source')
}, {
callback: function(r) {
sr.select(':not([value])').invoke('show');
this.updateResults(r.results);
}.bind(this)
});
},

onDomLoad: function()
updateResults: function(r)
{
if ($('search').present()) {
$('btn_clear').show();
var df = document.createDocumentFragment(),
sr = $('search_results');

r.each(function(addr) {
df.appendChild(
new Element('OPTION', { value: addr })
.insert(addr.escapeHTML())
);
});

sr.select('[value]').invoke('remove');

if (r.size()) {
sr.appendChild(df);
}
},

resize: function()
{
window.resizeBy(
0,
Math.max(0, document.body.clientHeight - document.viewport.getHeight())
);
},

onDomLoad: function()
{
HordeCore.initHandler('click');
HordeCore.initHandler('dblclick');
$('contacts').observe('submit', this._passAddresses.bind(this));

this.resize.bind(this).delay(0.25);
if (this.initial) {
this.updateResults(this.initial);
delete this.initial;
}

this.resize.bind(this).delay(0.1);
},

clickHandler: function(e)
Expand Down Expand Up @@ -139,6 +162,10 @@ var ImpContacts = {
this.removeAddress();
break;

case 'btn_search':
this.contactsSearch();
break;

case 'btn_update':
this.updateMessage();
break;
Expand Down
1 change: 1 addition & 0 deletions imp/lib/Ajax/Application.php
Expand Up @@ -58,6 +58,7 @@ protected function _init()
case $registry::VIEW_BASIC:
case $registry::VIEW_DYNAMIC:
$this->addHandler('IMP_Ajax_Application_Handler_Common');
$this->addHandler('IMP_Ajax_Application_Handler_Contacts');
$this->addHandler('IMP_Ajax_Application_Handler_ComposeAttach');
$this->addHandler('IMP_Ajax_Application_Handler_Draft');
$this->addHandler('IMP_Ajax_Application_Handler_Dynamic');
Expand Down
53 changes: 53 additions & 0 deletions imp/lib/Ajax/Application/Handler/Contacts.php
@@ -0,0 +1,53 @@
<?php
/**
* Copyright 2014 Horde LLC (http://www.horde.org/)
*
* See the enclosed file COPYING for license information (GPL). If you
* did not receive this file, see http://www.horde.org/licenses/gpl.
*
* @category Horde
* @copyright 2014 Horde LLC
* @license http://www.horde.org/licenses/gpl GPL
* @package IMP
*/

/**
* Defines AJAX actions used in the contacts popup.
*
* @author Michael Slusarz <slusarz@horde.org>
* @category Horde
* @copyright 2014 Horde LLC
* @license http://www.horde.org/licenses/gpl GPL
* @package IMP
*/
class IMP_Ajax_Application_Handler_Contacts
extends Horde_Core_Ajax_Application_Handler
{
/**
* AJAX action: Return address list for the contacts popup.
*
* Variables used:
* - search: (string) Search string.
* - source: (string) Source identifier.
*
* @return object An object with a single property: 'results'.
* 'results' is an array of e-mail addresses.
*/
public function contactsSearch()
{
global $injector;

$contacts = $injector->getInstance('IMP_Contacts');

$out = new stdClass;
$out->results = array_map(
'strval',
iterator_to_array($contacts->searchEmail($this->vars->get('search', ''), array(
'sources' => array($this->vars->source)
)))
);

return $out;
}

}

0 comments on commit 639a092

Please sign in to comment.