+include_once($path_to_root . "/includes/types.inc");
+include_once($path_to_root . "/includes/current_user.inc");
+
+define('SEARCH_BUTTON', "<input %s type='submit' class='combo_submit' style='border:0;background:url($path_to_root/themes/"
+ ."%s/images/locate.png) no-repeat;%s' aspect='fallback' name='%s' value=' ' title='"._("Set filter")."'> ");
+
+define('SELECT_BUTTON', "<input %s type='submit' class='combo_select' style='border:0;background:url($path_to_root/themes/"
+ ."%s/images/button_ok.png) no-repeat;%s' aspect='fallback' name='%s' value=' ' title='"._("Select")."'> ");
+
+//----------------------------------------------------------------------------
+// Universal sql combo generator
+// $sql must return selector values and selector texts in columns 0 & 1
+// Options are merged with defaults.
+
+function combo_input($name, $selected_id, $sql, $valfield, $namefield,
+ $options=null, $type=null)
+{
+global $Ajax, $path_to_root, $SysPrefs ;
+
+$opts = array( // default options
+ 'where'=> array(), // additional constraints
+ 'order' => $namefield, // list sort order
+ // special option parameters
+ 'spec_option'=>false, // option text or false
+ 'spec_id' => 0, // option id
+ // submit on select parameters
+ 'default' => '', // default value when $_POST is not set
+ 'multi' => false, // multiple select
+ 'select_submit' => false, //submit on select: true/false
+ 'async' => true, // select update via ajax (true) vs _page_body reload
+ // search box parameters
+ 'sel_hint' => null,
+ 'search_box' => false, // name or true/false
+ 'type' => 0, // type of extended selector:
+ // 0 - with (optional) visible search box, search by fragment inside id
+ // 1 - with hidden search box, search by option text
+ // 2 - with (optional) visible search box, search by fragment at the start of id
+ // 3 - TODO reverse: box with hidden selector available via enter; this
+ // would be convenient for optional ad hoc adding of new item
+ 'search_submit' => true, //search submit button: true/false
+ 'size' => 8, // size and max of box tag
+ 'max' => 50,
+ 'height' => false, // number of lines in select box
+ 'cells' => false, // combo displayed as 2 <td></td> cells
+ 'search' => array(), // sql field names to search
+ 'format' => null, // format functions for regular options
+ 'disabled' => false,
+ 'box_hint' => null, // box/selectors hints; null = std see below
+ 'category' => false, // category column name or false
+ 'show_inactive' => false, // show inactive records.
+ 'editable' => false, // false, or length of editable entry field
+ 'editlink' => false // link to entity entry/edit page (optional)
+);
+// ------ merge options with defaults ----------
+ if($options != null)
+ $opts = array_merge($opts, $options);
+ if (!is_array($opts['where'])) $opts['where'] = array($opts['where']);
+
+ $search_box = $opts['search_box']===true ? '_'.$name.'_edit' : $opts['search_box'];
+ // select content filtered by search field:
+ $search_submit = $opts['search_submit']===true ? '_'.$name.'_button' : $opts['search_submit'];
+ // select set by select content field
+ $search_button = $opts['editable'] ? '_'.$name.'_button' : ($search_box ? $search_submit : false);
+
+ $select_submit = $opts['select_submit'];
+ $spec_id = $opts['spec_id'];
+ $spec_option = $opts['spec_option'];
+ if ($opts['type'] == 0) {
+ $by_id = true;
+ $class = 'combo';
+ } elseif($opts['type'] == 1) {
+ $by_id = false;
+ $class = 'combo2';
+ } else {
+ $by_id = true;
+ $class = 'combo3';
+ }