diff --git a/calendar/inc/class.calendar_ui.inc.php b/calendar/inc/class.calendar_ui.inc.php index c863873105..38361ab563 100644 --- a/calendar/inc/class.calendar_ui.inc.php +++ b/calendar/inc/class.calendar_ui.inc.php @@ -619,22 +619,29 @@ class calendar_ui $owners = $this->owner ? is_array($this->owner) ? array($this->owner) : explode(',',$this->owner) : array($GLOBALS['egw_info']['user']['account_id']); - $sel_options = array(); + $sel_options = array('owner' => array()); // Get user accounts, formatted nicely for grouping and matching - // the ajax call calendar_uiforms->ajax_owner() - $account_options = array('account_type' => 'both'); - $accounts = accounts::link_query('',$account_options); + // the ajax call calendar_uiforms->ajax_owner() - users first + $accounts = array(); + $list = array('accounts', 'owngroups'); + foreach($list as $type) + { + $account_options = array('account_type' => $type); + $accounts += accounts::link_query('',$account_options); + } + $accounts = array_intersect_key($accounts, $GLOBALS['egw']->acl->get_grants('calendar')); $sel_options['owner'] = array_map( function($account_id, $account_name) { return array( - 'value' => $account_id, + 'value' => ''.$account_id, 'label' => $account_name, 'app' => lang('home-accounts') ); }, array_keys($accounts), $accounts ); + // Add external owners that a select account widget will not find $linked_owners = array(); diff --git a/calendar/inc/class.calendar_uiforms.inc.php b/calendar/inc/class.calendar_uiforms.inc.php index dbd5838479..a81024600a 100644 --- a/calendar/inc/class.calendar_uiforms.inc.php +++ b/calendar/inc/class.calendar_uiforms.inc.php @@ -2949,40 +2949,56 @@ class calendar_uiforms extends calendar_ui public function ajax_owner() { $query = $_REQUEST['query']; - $options = ['num_rows' => 100]; + // Arbitrarily limited to 50 / resource + $options = ['start' => 0, 'num_rows' => 50]; $results = []; if($query) { - foreach($this->bo->resources as $type => $data) + $resources = array_merge(array('' => $this->bo->resources['']),$this->bo->resources); + foreach($resources as $type => $data) { $mapped = array(); - if ($data['app'] && egw_link::get_registry($data['app'], 'query')) + $_results = array(); + + // Handle accounts seperately + if($type == '') + { + $list = array('accounts', 'owngroups'); + foreach($list as $a_type) + { + $account_options = $options + array('account_type' => $a_type); + $_results += accounts::link_query('',$account_options); + } + $_results = array_intersect_key($_results, $GLOBALS['egw']->acl->get_grants('calendar')); + } + else if ($data['app'] && egw_link::get_registry($data['app'], 'query')) { $_results = egw_link::query($data['app'], $query,$options); - if(!$_results) continue; - $r_results = array_unique($_results); - foreach($_results as $id => $title) + } + if(!$_results) continue; + $_results = array_unique($_results); + + foreach($_results as $id => $title) + { + if($id && $title) { - if($id && $title) + // Magicsuggest uses id, not value. + $value = [ + 'id' => $type.$id, + 'value'=> $type.$id, + 'label' => $title, + 'app' => lang($data['app']) + ]; + if(is_array($value['label'])) { - // Magicsuggest uses id, not value. - $value = [ - 'id' => $type.$id, - 'value'=> $type.$id, - 'label' => $title, - 'app' => lang($data['app']) - ]; - if(is_array($value['label'])) - { - $value = array_merge($value, $value['label']); - } - $mapped[] = $value; + $value = array_merge($value, $value['label']); } + $mapped[] = $value; } - if(count($mapped)) - { - $results = array_merge($results, $mapped); - } + } + if(count($mapped)) + { + $results = array_merge($results, $mapped); } } } diff --git a/calendar/js/app.js b/calendar/js/app.js index 314d21e919..7d1c98978a 100644 --- a/calendar/js/app.js +++ b/calendar/js/app.js @@ -824,6 +824,7 @@ app.classes.calendar = AppJS.extend( swipe:function(event, direction, distance, duration, fingerCount) { if(direction == "up" || direction == "down") { + if(fingerCount <= 1) return; var at_bottom = direction !== -1; var at_top = direction !== 1; @@ -834,7 +835,6 @@ app.classes.calendar = AppJS.extend( }).each(function() { at_top = at_top && this.scrollTop === 0; }); - if(!at_bottom && !at_top && fingerCount == 1) return; } var delta = direction == "down" || direction == "right" ? -1 : 1; diff --git a/calendar/js/et2_widget_owner.js b/calendar/js/et2_widget_owner.js index efd3cce6d5..09664652d7 100644 --- a/calendar/js/et2_widget_owner.js +++ b/calendar/js/et2_widget_owner.js @@ -53,7 +53,41 @@ var et2_calendar_owner = et2_taglist_email.extend( // Allows sub-widgets to override options to the library lib_options: { groupBy: 'app', - expandOnFocus: true + minChars: 2, + // This option will also expand when the selection is changed + // via code, which we do not want + //expandOnFocus: true + toggleOnClick: true + }, + + + doLoadingFinished: function() { + this._super.apply(this, arguments); + + var widget = this; + // onChange fired when losing focus, which is different from normal + this._oldValue = this.taglist.getValue(); + $j(this.taglist) + .off("selectionchange"); + // .on('focus', function() {debugger; widget.taglist.expand();}); + + if(this.options.onchange && typeof this.onchange === 'function') + { + $j(this.taglist).on("blur", function() { + if(widget._oldValue.toString() !== widget.taglist.getValue().toString()) + { + widget.onchange.call(widget, arguments); + } + widget._oldValue = widget.taglist.getValue(); + }); + } + return true; + }, + + getValue: function() + { + if(this.taglist == null) return null; + return this.taglist.getValue(); } }); et2_register_widget(et2_calendar_owner, ["calendar_owner"]); \ No newline at end of file diff --git a/calendar/js/et2_widget_timegrid.js b/calendar/js/et2_widget_timegrid.js index 261077d140..b8db7f8639 100644 --- a/calendar/js/et2_widget_timegrid.js +++ b/calendar/js/et2_widget_timegrid.js @@ -1799,7 +1799,7 @@ var et2_calendar_timegrid = et2_calendar_view.extend([et2_IDetachedDOM, et2_IRes this.div.css('height', this.options.height); // Re-do time grid - if(!this.update_timer)// && this.options.height != old_height) + if(!this.update_timer) { this.resizeTimes(); } diff --git a/etemplate/js/et2_widget_taglist.js b/etemplate/js/et2_widget_taglist.js index ab906daf7f..8f87345ddc 100644 --- a/etemplate/js/et2_widget_taglist.js +++ b/etemplate/js/et2_widget_taglist.js @@ -278,10 +278,27 @@ var et2_taglist = et2_selectbox.extend( _data: function(query) { if(query.trim() ==='' || !this.options.autocomplete_url) { + // No server - let magicsuggest handle options return this.options.select_options; } + if (!jQuery.isEmptyObject(this.options.select_options)) + { + // Check options, if there's a match there (that is not already + // selected), do not ask server + var filtered = [] + var selected = this.taglist.getSelection(); + $j.each(this.options.select_options, function(index, obj) { + var name = obj.label; + if(selected.indexOf(obj) < 0 && name.toLowerCase().indexOf(query.toLowerCase()) > -1) + { + filtered.push(obj); + } + }); + return filtered.length > 0 ? filtered : this.options.autocomplete_url + } else { + // No options - ask server return this.options.autocomplete_url; } }, @@ -364,8 +381,11 @@ var et2_taglist = et2_selectbox.extend( this.options.value = value; if(this.taglist == null) return; - this.taglist.clear(true); - if(!value) return; + if(!value) + { + this.taglist.clear(true); + return; + } var values = jQuery.isArray(value) ? jQuery.extend([],value) : [value]; var result = []; @@ -374,11 +394,16 @@ var et2_taglist = et2_selectbox.extend( var v = values[i]; if (v && typeof v == 'object' && typeof v.id != 'undefined' && typeof v.label != 'undefined') { - // alread in correct format + // already in correct format } else if (this.options.select_options && + // Check options (result = $j.grep(this.options.select_options, function(e) { return e.id == v; + })) || + // Check current selection to avoid going back to server + (result = $j.grep(this.taglist.getSelection(), function(e) { + return e.id == v; })) ) { @@ -405,7 +430,7 @@ var et2_taglist = et2_selectbox.extend( } } - this.taglist.addToSelection(values); + this.taglist.setSelection(values); }, getValue: function()