diff --git a/etemplate/inc/class.etemplate_widget_taglist.inc.php b/etemplate/inc/class.etemplate_widget_taglist.inc.php index 6f7a24f0c3..88ee83a1d4 100644 --- a/etemplate/inc/class.etemplate_widget_taglist.inc.php +++ b/etemplate/inc/class.etemplate_widget_taglist.inc.php @@ -51,4 +51,21 @@ class etemplate_widget_taglist extends etemplate_widget echo json_encode($results); common::egw_exit(); } + + /** + * Search for emails + * + * Uses the mail application if available, or addressbook + */ + public static function ajax_email() { + // If no mail app access, use link system -> addressbook + if(!$GLOBALS['egw_info']['apps']['mail']) + { + $_REQUEST['app'] = 'addressbook-email'; + return self::ajax_search(); + } + + // TODO: this should go to a BO, not a UI object + return mail_compose::ajax_searchAddress(); + } } \ No newline at end of file diff --git a/etemplate/js/et2_widget_taglist.js b/etemplate/js/et2_widget_taglist.js index 6afe4f9247..9ed86efcd5 100644 --- a/etemplate/js/et2_widget_taglist.js +++ b/etemplate/js/et2_widget_taglist.js @@ -107,6 +107,8 @@ var et2_taglist = et2_selectbox.extend( "tags": { ignore: true} }, + // Allows sub-widgets to override options to the library + lib_options: {}, /** * Construtor * @@ -143,7 +145,7 @@ var et2_taglist = et2_selectbox.extend( // MagicSuggest would replaces our div, so add a wrapper instead this.taglist = $j('
').appendTo(this.div); - this.taglist = this.taglist.magicSuggest({ + var options = jQuery.extend( { data: this.options.select_options && !jQuery.isEmptyObject(this.options.select_options) ? this.options.select_options : this.options.autocomplete_url, dataUrlParams: this.options.autocomplete_params, value: this.options.value, @@ -157,10 +159,11 @@ var et2_taglist = et2_selectbox.extend( allowFreeEntries: this.options.allowFreeEntries, disabled: this.options.disabled || this.options.readonly, editable: !(this.options.disabled || this.options.readonly), - selectionRenderer: this.options.tagRenderer || this.selectionRenderer, + selectionRenderer: jQuery.proxy(this.options.tagRenderer || this.selectionRenderer,this), renderer: this.options.listRenderer || null, maxSelection: this.options.maxSelection - }); + }, this.lib_options); + this.taglist = this.taglist.magicSuggest(options); // Display / hide a loading icon while fetching $j(this.taglist) @@ -262,6 +265,47 @@ var et2_taglist = et2_selectbox.extend( }); et2_register_widget(et2_taglist, ["taglist"]); +/** + * Taglist customized specifically for emails, which it pulls from the mail application, + * or addressbook if mail is not available. Free entries are allowed, and we render + * invalid free entries differently (but still accept them). + * + * @augments et2_taglist + */ +var et2_taglist_email = et2_taglist.extend( +{ + attributes: { + "autocomplete_url": { + "default": "etemplate_widget_taglist::ajax_email::etemplate", + }, + "autocomplete_params": { + "default": {}, + }, + allowFreeEntries: { + "default": true, + ignore: true + } + }, + lib_options: { + // Search function limits to 3 anyway + minChars: 3 + }, + + // PREG for client-side validation copied from etemplate_widget_url + EMAIL_PREG: new RegExp(/^[^\x00-\x20()<>@,;:\".\[\]]+@([a-z0-9ÄÖÜäöüß](|[a-z0-9ÄÖÜäöüß_-]*[a-z0-9ÄÖÜäöüß])\.)+[a-z]{2,6}/), + + selectionRenderer: function(item) + { + // We check free entries for valid email, and render as invalid if it's not. + var valid = item.id != item.label || this.EMAIL_PREG.test(item.id || ''); + + var label = ''+(item.name ? item.name : item.label)+''; + return label; + } +}); +et2_register_widget(et2_taglist_email, ["taglist-email"]); + // Require css // TODO: merge into etemplate2.css with all other widgets when done if(typeof egw != 'undefined') egw(window).includeCSS(egw.webserverUrl + "/phpgwapi/js/jquery/magicsuggest/src/magicsuggest-1.3.0.css"); diff --git a/etemplate/js/et2_widget_url.js b/etemplate/js/et2_widget_url.js index 69c45c4191..3ace24833c 100644 --- a/etemplate/js/et2_widget_url.js +++ b/etemplate/js/et2_widget_url.js @@ -30,7 +30,9 @@ var et2_url = et2_textbox.extend( "ignore": true } }, - + + // PREG for client-side validation copied from etemplate_widget_url + EMAIL_PREG: new RegExp(/^[^\x00-\x20()<>@,;:\".\[\]]+@([a-z0-9ÄÖÜäöüß](|[a-z0-9ÄÖÜäöüß_-]*[a-z0-9ÄÖÜäöüß])\.)+[a-z]{2,6}/), /** * @memberOf et2_url */ @@ -194,6 +196,11 @@ var et2_url = et2_textbox.extend( e.data.showMessage(e.data.egw().lang("Protocol is required"), "hint", true); } break; + case "url-email": + if(!e.data.EMAIL_PREG.test(value)) + { + e.data.showMessage("Invalid email","validation_error",true); + } } } });