Add AJAX Select widget as a field type for custom fields.

Select options can be provided using one of three different methods:
1.  key=value pairs, one per line, as for a selectbox
2.  @filename.php - The file must be in the egw root, and define an array named $options, that has key => value pairs
3.  Define the options normally used for the AJAX Select widget (get_rows, get_title, id_field) and it will pull values from the database, as normal.

Other options (icon, filter, template, link) can be used regardless of the method used to get the values.
This commit is contained in:
Nathan Gray 2010-01-12 22:35:51 +00:00
parent bce9456486
commit d889e92774
4 changed files with 144 additions and 12 deletions

View File

@ -21,6 +21,7 @@
* This widget can get data from any function that can provide data to a nextmatch widget.
* This widget is generating html, so it does not work (without an extra implementation) in an other UI
*/
class ajax_select_widget
{
var $public_functions = array(
@ -30,6 +31,29 @@ class ajax_select_widget
);
var $human_name = 'AJAX Select'; // this is the name for the editor
// Accepted option keys if you're passing in an array to set up the widget
// Additional options will be passed to the search query
public static $known_options = array(
// These ones can be passed in from eTemplate editor in size
'get_rows',
'get_title',
'id_field',
'template',
'filter',
'filter2',
'link',
'icon',
// Pass by code only
'values',
);
// Flag used in id_field to indicate that the key of the record should be used as the value
const ARRAY_KEY = 'array_key';
// Array of static values to emulate a combo-box, with no DB lookup
protected static $static_values = array();
private $debug = false;
function ajax_select_widget($ui='')
@ -103,6 +127,13 @@ class ajax_select_widget
$options['template'] = 'etemplate.ajax_select_widget.row';
}
if(array_key_exists('values', $options)) {
if($options['values']) {
self::$static_values[$name] = $options['values'];
}
unset($options['values']);
}
$onchange = ($cell['onchange'] ? $cell['onchange'] : 'false');
// Set current value
@ -121,10 +152,15 @@ class ajax_select_widget
$title_obj =& CreateObject($title_app . '.' . $title_class);
}
}
if(!is_object($title_obj) || !method_exists($title_obj,$title_method)) {
echo "$entry_app.$entry_class.$entry_method is not a valid method for getting the title";
} elseif($current_value) {
$title = $title_obj->$title_method($current_value);
if($title_method == 'array_title' && $title_class == __CLASS__) {
$title = self::$title_method($current_value, $name);
} else {
$title = $title_obj->$title_method($current_value);
}
}
// Check get_rows method
@ -146,6 +182,7 @@ class ajax_select_widget
$cell['type'] = 'template';
$cell['size'] = $cell['name'];
$value = array('value' => $current_value, 'search' => $title);
$widget = new etemplate('etemplate.ajax_select_widget');
$widget->no_onclick = True;
@ -165,6 +202,9 @@ class ajax_select_widget
} else {
$search['type'] = 'text';
$search['size'] = '';
if($current_value == '' && $options['id_field'] == self::ARRAY_KEY) {
$search['blur'] = lang('Search...');
}
}
// Icon
@ -173,6 +213,11 @@ class ajax_select_widget
$cell['obj'] = &$widget;
// Save static values, if set
if(self::$static_values[$name]) {
$extension_data['values'] = self::$static_values[$name];
}
// Save options for post_processing
$extension_data['options'] = $options;
$extension_data['needed'] = $cell['needed'];
@ -181,6 +226,12 @@ class ajax_select_widget
$GLOBALS['egw_info']['flags']['include_xajax'] = True;
// JavaScript
// converter doesn't handle numeric well
foreach($options as $key => &$value) {
if(is_numeric($value)) {
$value = (string)$value;
}
}
$options = $GLOBALS['egw']->js->convert_phparray_jsarray("options['$name']", $options, true);
$GLOBALS['egw']->js->set_onload("if(!options) {
var options = new Object();
@ -267,7 +318,7 @@ class ajax_select_widget
}
}
function ajax_search($id, $value, $set_id, $query) {
function ajax_search($id, $value, $set_id, $query, $etemplate_id) {
$base_id = substr($id, 0, strrpos($id, '['));
$result_id = ($set_id ? $set_id : $base_id . '[results]');
$response = new xajaxResponse();
@ -281,7 +332,7 @@ class ajax_select_widget
// Expand lists
foreach($query as $key => &$row) {
if(strpos($row, ',')) {
if($row && strpos($row, ',')) {
$query[$key] = explode(',', $row);
}
@ -293,6 +344,19 @@ class ajax_select_widget
}
}
$query['search'] = $value;
if($query['id_field'] == self::ARRAY_KEY) {
// Pass base_id so we can get the right values
$query['field_name'] = $base_id;
// Check for a provided list of values
if($request = etemplate_request::read($etemplate_id)) {
$extension_data = $request->extension_data[$base_id];
if(is_array($extension_data) && $extension_data['values']) {
self::$static_values[$base_id] = $extension_data['values'];
}
}
}
$result_list = array();
$readonlys = array();
@ -313,7 +377,18 @@ class ajax_select_widget
}
foreach($result_list as $key => &$row) {
if(!is_array($row)) {
continue;
if($query['id_field'] == self::ARRAY_KEY) {
if(!is_array($row)) {
// Restructure $row to be an array
$row = array(
self::ARRAY_KEY => $key,
'id_field' => $key,
'title' => $row
);
}
} else {
continue;
}
}
//check for multiple id's
@ -331,15 +406,17 @@ class ajax_select_widget
}
$row['id_field'] = implode(';',$id_field_keys_values);
unset($id_field_keys_values);
} else{
} else {
if($query['id_field'] && $query['get_title']) {
if($row[$query['id_field']]) {
$row['title'] = ExecMethod($query['get_title'], $row[$query['id_field']]);
if($row[$query['id_field']] && $query['id_field'] != self::ARRAY_KEY) {
$row['title'] = ExecMethod($query['get_title'], $row[$query['id_field']]);
}
}
// If we use htmlspecialchars, it causes issues with mixed quotes. addslashes() seems to handle it.
$row['id_field'] = $row[$query['id_field']];
if($query['id_field'] != self::ARRAY_KEY) {
$row['id_field'] = $row[$query['id_field']];
}
}
// If we use htmlspecialchars, it causes issues with mixed quotes. addslashes() seems to handle it.
$row['id_field'] = addslashes($row['id_field']);
$data = ($query['nextmatch_template']) ? array(1=>$row) : $row;
@ -359,4 +436,30 @@ class ajax_select_widget
}
return $response->getXML();
}
/**
* Use a simple array to get the title
* Values should be passed in to the widget as an array in $size['values']
*/
protected function array_title($id, $name) {
if(trim($id) == '') {
return lang('Search');
}
return self::$static_values[$name][$id];
}
/**
* Use a simple array to get the results
* Values should be passed in to the widget as an array in $size['values']
*/
protected function array_rows(&$query, &$result) {
foreach( self::$static_values[$query['field_name']] as $key => $value) {
if($query['search'] && stripos($value, $query['search']) === false) continue;
$result[$key] = $value;
}
$count = count($result);
$result = array_slice($result, $query['start'], $query['num_rows']);
return $count;
}
}

View File

@ -45,6 +45,7 @@ class customfields_widget
'text' => 'Text',
'label' => 'Label',
'select' => 'Selectbox',
'ajax_select' => 'Search',
'radio' => 'Radiobutton',
'checkbox' => 'Checkbox',
'date' => 'Date',
@ -235,6 +236,34 @@ class customfields_widget
*/
}
break;
case 'ajax_select' :
// Set some reasonable defaults for the widget
$options = array(
'get_title' => 'etemplate.ajax_select_widget.array_title',
'get_rows' => 'etemplate.ajax_select_widget.array_rows',
'id_field' => ajax_select_widget::ARRAY_KEY,
);
if($field['rows']) {
$options['num_rows'] = $field['rows'];
}
// If you specify an option known to the AJAX Select widget, it will be pulled from the list of values
// and used as such. All unknown values will be used for selection, not passed through to the query
if (isset($field['values']['@']))
{
$options['values'] = $this->_get_options_from_file($field['values']['@']);
unset($field['values']['@']);
} else {
$options['values'] = array_diff_key($field['values'], array_flip(ajax_select_widget::$known_options));
}
$options = array_merge($options, array_intersect_key($field['values'], array_flip(ajax_select_widget::$known_options)));
$input =& etemplate::empty_cell('ajax_select', $this->prefix.$lname, array(
'readonly' => $readonly,
'no_lang' => True,
'size' => $options
));
break;
case 'label' :
$row_class = 'th';
break;

View File

@ -281,7 +281,7 @@ function change(e, value) {
selects[i].style.visibility = 'hidden';
}
}
xajax_doXMLHTTP(current_app + ".ajax_select_widget.ajax_search.etemplate", id, value, set_id, query);
xajax_doXMLHTTP(current_app + ".ajax_select_widget.ajax_search.etemplate", id, value, set_id, query, document.getElementById('etemplate_exec_id').value);
}

View File

@ -2,7 +2,7 @@
/**
* eGroupWare - eTemplates for Application etemplate
* http://www.egroupware.org
* generated by soetemplate::dump4setup() 2010-01-08 03:21
* generated by soetemplate::dump4setup() 2010-01-12 13:39
*
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
* @package etemplate
@ -39,7 +39,7 @@ div.resultBoxSelected {
background-color: #D3DCE3;
}','modified' => '1176831076',);
$templ_data[] = array('name' => 'etemplate.ajax_select_widget.row','template' => '','lang' => '','group' => '0','version' => '','data' => 'a:1:{i:0;a:4:{s:4:"type";s:4:"grid";s:4:"data";a:2:{i:0;a:0:{}i:1;a:2:{s:1:"A";a:3:{s:4:"type";s:5:"label";s:7:"no_lang";s:1:"1";s:4:"name";s:8:"id_field";}s:1:"B";a:3:{s:4:"type";s:5:"label";s:7:"no_lang";s:1:"1";s:4:"name";s:5:"title";}}}s:4:"rows";i:1;s:4:"cols";i:2;}}','size' => '','style' => '','modified' => '1160761596',);
$templ_data[] = array('name' => 'etemplate.ajax_select_widget.row','template' => '','lang' => '','group' => '0','version' => '','data' => 'a:1:{i:0;a:4:{s:4:"type";s:4:"grid";s:4:"data";a:2:{i:0;a:0:{}i:1;a:1:{s:1:"A";a:3:{s:4:"type";s:5:"label";s:7:"no_lang";s:1:"1";s:4:"name";s:5:"title";}}}s:4:"rows";i:1;s:4:"cols";i:1;}}','size' => '','style' => '','modified' => '1160761596',);
$templ_data[] = array('name' => 'etemplate.captcha_widget','template' => '','lang' => '','group' => '0','version' => '1.7.002','data' => 'a:1:{i:0;a:6:{s:4:"type";s:4:"grid";s:4:"data";a:4:{i:0;a:3:{s:2:"c1";s:7:",bottom";s:2:"c2";s:4:",top";s:2:"h3";s:10:",!@val_msg";}i:1;a:2:{s:1:"A";a:3:{s:4:"type";s:5:"image";s:4:"name";s:25:"etemplate/securimage_show";s:4:"size";s:14:",,,,show_image";}s:1:"B";a:2:{s:4:"type";s:5:"image";s:4:"name";s:24:"etemplate/audio_icon.gif";}}i:2;a:2:{s:1:"A";a:4:{s:4:"type";s:4:"text";s:4:"name";s:12:"captcha_code";s:4:"size";s:2:"24";s:6:"needed";s:1:"1";}s:1:"B";a:2:{s:4:"type";s:5:"image";s:4:"name";s:21:"etemplate/refresh.gif";}}i:3;a:2:{s:1:"A";a:2:{s:4:"type";s:5:"label";s:4:"name";s:7:"val_msg";}s:1:"B";a:1:{s:4:"type";s:5:"label";}}}s:4:"rows";i:3;s:4:"cols";i:2;s:4:"size";s:8:",,0,,0,0";s:7:"options";a:3:{i:4;s:1:"0";i:5;s:1:"0";i:2;s:1:"0";}}}','size' => ',,0,,0,0','style' => '','modified' => '1245517015',);