From 54d5d16e78ff402947eb37e64ed7db8018aaf15a Mon Sep 17 00:00:00 2001 From: Kamel Khelifa <kkhelifa@open-dsi.fr> Date: Tue, 11 Mar 2025 10:25:47 +0100 Subject: [PATCH 1/3] =?UTF-8?q?-=20Ajout=20d'un=20param=C3=A8tre=20'emptyv?= =?UTF-8?q?alue'=20aux=20fonctions=20FormDictionary::select=5Fdictionary?= =?UTF-8?q?=20et=20FormDictionary::select=5Fdictionary=5Flist?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ChangeLog.md | 1 + class/html.formdictionary.class.php | 635 ++++++++++++++-------------- 2 files changed, 311 insertions(+), 325 deletions(-) diff --git a/ChangeLog.md b/ChangeLog.md index 2879907..495713e 100755 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -5,6 +5,7 @@ Le format du fichier est basé sur [Tenez un ChangeLog](http://keepachangelog.co ## [14.0.13] - 10-03-2025 - Fix affichage de l'aide +- Ajout d'un paramètre 'emptyvalue' aux fonctions FormDictionary::select_dictionary et FormDictionary::select_dictionary_list ## [14.0.12] - 10-02-2025 - Compatibilité V21 diff --git a/class/html.formdictionary.class.php b/class/html.formdictionary.class.php index 07e91f5..65cb863 100755 --- a/class/html.formdictionary.class.php +++ b/class/html.formdictionary.class.php @@ -45,220 +45,222 @@ */ class FormDictionary { - var $db; - var $error; - var $num; - - /** - * Constructor - * - * @param DoliDB $db Database handler - */ - public function __construct($db) - { - $this->db = $db; - } - - /** - * Output html form to select a third party - * - * @param string $module Name of the module containing the dictionary - * @param string $name Name of dictionary - * @param string $selected Preselected type - * @param string $htmlname Name of field in form - * @param string $key Field name of the dictionary for the key of the line - * @param string $label Label pattern for the label of the line (replace {{FieldName}} by this value) - * @param array $filters List of filters: array(fieldName => value), value is a array search a list of rowid, if $filters = null then return no lines - * @param array $orders Order by: array(fieldName => order, ...) - * @param string $showempty Add an empty field (Can be '1' or text key to use on empty line like 'SelectThirdParty') - * @param int $forcecombo Force to use combo box - * @param array $events Ajax event options to run on change. Example: array(array('method'=>'getContacts', 'url'=>dol_buildpath('/core/ajax/contacts.php',1), 'htmlname'=>'contactid', 'params'=>array('add-customer-contact'=>'disabled'))) - * @param int $usesearchtoselect Minimum length of input string to start autocomplete - * @param int $limit Maximum number of elements - * @param string $morecss Add more css styles to the SELECT component - * @param string $moreparam Add more parameters onto the select tag. For example 'style="width: 95%"' to avoid select2 component to go over parent container - * @param string $selected_input_value Value of preselected input text (for use with ajax) - * @param int $hidelabel Hide label (0=no, 1=yes, 2=show search icon (before) and placeholder, 3 search icon after) - * @param string $selectlabel Text of the label (can be translated) - * @param int $autofocus Autofocus the field in form (1 auto focus, 0 not) - * @param array $ajaxoptions Options for ajax_autocompleter - * @param bool $options_only Return options only (for ajax treatment) - * @param int $ismultiselect 0=Not multiselect, 1=Multiselect - * @return string HTML string with select box for thirdparty. - */ - public function select_dictionary($module, $name, $selected = '', $htmlname = 'dictionaryid', $showempty = '', $key='rowid', $label='{{label}}', $filters=array(), $orders=array('label'=>'ASC'), $forcecombo = 0, $events = array(), $usesearchtoselect=0, $limit = 0, $morecss = 'minwidth100', $moreparam = '', $selected_input_value = '', $hidelabel = 1, $selectlabel = '', $autofocus=0, $ajaxoptions = array(), $options_only=false, $ismultiselect=0) - { - global $conf, $langs; - - $out = ''; - - if (!empty($conf->use_javascript_ajax) && !empty($usesearchtoselect) && !$forcecombo && !$options_only) { - // No immediate load of all database - $placeholder = ''; - if ($selected && empty($selected_input_value)) { - dol_include_once('/advancedictionaries/class/dictionary.class.php'); - $dictionaryLine = Dictionary::getDictionaryLine($this->db, $module, $name); - $dictionaryLine->fetch($selected); - $selected_input_value = $dictionaryLine->getLabel($label); - unset($dictionaryLine); - } - // mode 1 - $urloption = 'module=' . $module . '&name=' . $name . '&htmlname=' . $htmlname . '&key=' . $key . '&label=' . $label . '&showempty=' . $showempty . '&outjson=1&' . http_build_query(array('filters' => $filters)); - $out .= ajax_autocompleter($selected, $htmlname, dol_buildpath('/advancedictionaries/ajax/dictionary.php', 1), $urloption, $usesearchtoselect, 0, $ajaxoptions); - $out .= '<style type="text/css"> + public $db; + public $error; + public $num; + + /** + * Constructor + * + * @param DoliDB $db Database handler + */ + public function __construct($db) + { + $this->db = $db; + } + + /** + * Output html form to select a third party + * + * @param string $module Name of the module containing the dictionary + * @param string $name Name of dictionary + * @param string $selected Preselected type + * @param string $htmlname Name of field in form + * @param string $key Field name of the dictionary for the key of the line + * @param string $label Label pattern for the label of the line (replace {{FieldName}} by this value) + * @param array $filters List of filters: array(fieldName => value), value is a array search a list of rowid, if $filters = null then return no lines + * @param array $orders Order by: array(fieldName => order, ...) + * @param string $showempty Add an empty field (Can be '1' or text key to use on empty line like 'SelectThirdParty') + * @param int $forcecombo Force to use combo box + * @param array $events Ajax event options to run on change. Example: array(array('method'=>'getContacts', 'url'=>dol_buildpath('/core/ajax/contacts.php',1), 'htmlname'=>'contactid', 'params'=>array('add-customer-contact'=>'disabled'))) + * @param int $usesearchtoselect Minimum length of input string to start autocomplete + * @param int $limit Maximum number of elements + * @param string $morecss Add more css styles to the SELECT component + * @param string $moreparam Add more parameters onto the select tag. For example 'style="width: 95%"' to avoid select2 component to go over parent container + * @param string $selected_input_value Value of preselected input text (for use with ajax) + * @param int $hidelabel Hide label (0=no, 1=yes, 2=show search icon (before) and placeholder, 3 search icon after) + * @param string $selectlabel Text of the label (can be translated) + * @param int $autofocus Autofocus the field in form (1 auto focus, 0 not) + * @param array $ajaxoptions Options for ajax_autocompleter + * @param bool $options_only Return options only (for ajax treatment) + * @param int $ismultiselect 0=Not multiselect, 1=Multiselect + * @param string $emptyvalue Value of the empty options + * @return string HTML string with select box for thirdparty. + */ + public function select_dictionary($module, $name, $selected = '', $htmlname = 'dictionaryid', $showempty = '', $key = 'rowid', $label = '{{label}}', $filters = array(), $orders = array('label'=>'ASC'), $forcecombo = 0, $events = array(), $usesearchtoselect=0, $limit = 0, $morecss = 'minwidth100', $moreparam = '', $selected_input_value = '', $hidelabel = 1, $selectlabel = '', $autofocus = 0, $ajaxoptions = array(), $options_only = false, $ismultiselect = 0, $emptyvalue = '-1') + { + global $conf, $langs; + + $out = ''; + + if (!empty($conf->use_javascript_ajax) && !empty($usesearchtoselect) && !$forcecombo && !$options_only) { + // No immediate load of all database + $placeholder = ''; + if ($selected && empty($selected_input_value)) { + dol_include_once('/advancedictionaries/class/dictionary.class.php'); + $dictionaryLine = Dictionary::getDictionaryLine($this->db, $module, $name); + $dictionaryLine->fetch($selected); + $selected_input_value = $dictionaryLine->getLabel($label); + unset($dictionaryLine); + } + // mode 1 + $urloption = 'module=' . $module . '&name=' . $name . '&htmlname=' . $htmlname . '&key=' . $key . '&label=' . $label . '&showempty=' . $showempty . '&outjson=1&' . http_build_query(array('filters' => $filters)); + $out .= ajax_autocompleter($selected, $htmlname, dol_buildpath('/advancedictionaries/ajax/dictionary.php', 1), $urloption, $usesearchtoselect, 0, $ajaxoptions); + $out .= '<style type="text/css"> .ui-autocomplete { z-index: 250; } </style>'; - if (empty($hidelabel)) print $langs->trans($selectlabel) . ' : '; - else if ($hidelabel > 1) { - if (!empty($conf->global->MAIN_HTML5_PLACEHOLDER)) $placeholder = ' placeholder="' . $langs->trans($selectlabel) . '"'; - else $placeholder = ' title="' . $langs->trans($selectlabel) . '"'; - if ($hidelabel == 2) { - $out .= img_picto($langs->trans("Search"), 'search'); - } - } - $out .= '<input type="text" class="' . $morecss . '" name="search_' . $htmlname . '" id="search_' . $htmlname . '" value="' . $selected_input_value . '"' . $placeholder . ' ' . (!empty($autofocus) ? 'autofocus' : '') . ' />'; - if ($hidelabel == 3) { - $out .= img_picto($langs->trans("Search"), 'search'); - } - } else { - // Immediate load of all database - $out .= $this->select_dictionary_list($module, $name, $selected, $htmlname, $showempty, $key, $label, $filters, $orders, $forcecombo, $events, $usesearchtoselect, 0, $limit, $morecss, $moreparam, $options_only, $ismultiselect); - } - - return $out; - } - - /** - * Output html form to select a dictionary. - * Note, you must use the select_dictionary to get the component to select a dictionary. This function must only be called by select_dictionary. - * - * @param string $module Name of the module containing the dictionary - * @param string $name Name of dictionary - * @param string|array $selected Preselected values - * @param string $htmlname Name of field in form - * @param string $key Field name for the key of the line - * @param string $label Label pattern for the label of the line (replace {{FieldName}} by this value) - * @param array $filters List of filters: array(fieldName => value), value is a array search a list of rowid, if $filters = null then return no lines - * @param array $orders Order by: array(fieldName => order, ...) - * @param string $showempty Add an empty field (Can be '1' or text to use on empty line like 'SelectThirdParty') - * @param int $forcecombo Force to use combo box - * @param array $events Event options. Example: array(array('method'=>'getContacts', 'url'=>dol_buildpath('/core/ajax/contacts.php',1), 'htmlname'=>'contactid', 'params'=>array('add-customer-contact'=>'disabled'))) - * @param int $usesearchtoselect Minimum length of input string to start autocomplete - * @param int $outputmode 0=HTML select string, 1=Array - * @param int $limit Limit number of answers - * @param string $morecss Add more css styles to the SELECT component - * @param string $moreparam Add more parameters onto the select tag. For example 'style="width: 95%"' to avoid select2 component to go over parent container - * @param bool $options_only Return options only (for ajax treatment) - * @param int $ismultiselect 0=Not multiselect, 1=Multiselect - * @return string HTML string with - */ - public function select_dictionary_list($module, $name, $selected='', $htmlname='dictionaryid', $showempty='', $key='rowid', $label='{{label}}', $filters=array(), $orders=array(), $forcecombo=0, $events=array(), $usesearchtoselect=0, $outputmode=0, $limit=0, $morecss='minwidth100', $moreparam='', $options_only=false, $ismultiselect=0) - { - global $conf, $langs; - - dol_syslog(__METHOD__, LOG_DEBUG); - - // Get lines - dol_include_once('/advancedictionaries/class/dictionary.class.php'); - $dictionary = Dictionary::getDictionary($this->db, $module, $name); - $lines = $filters === null ? array() : $dictionary->fetch_array($key, $label, $filters, $orders, $limit, 1, false); - if (empty($dictionary->error)) { - $out = ''; - $outarray = array(); - - // Build output string - if ($conf->use_javascript_ajax && !$forcecombo && !$options_only) { - include_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php'; - if ($ismultiselect) { - $comboenhancement = $this->multiselect_javascript_code($selected, $htmlname, $elemtype=''); - $comboenhancement .= $this->add_select_events($htmlname, $events); - } else { - $comboenhancement = ajax_combobox($htmlname, $events, $usesearchtoselect); - } - $out .= $comboenhancement; - } - - // Construct $out and $outarray - if (!$options_only) $out .= '<select id="' . $htmlname . '" class="flat' . ($morecss ? ' ' . $morecss : '') . '"' . ($moreparam ? ' ' . $moreparam : '') . ' name="' . $htmlname . '">' . "\n"; - - $textifempty = ''; - // Do not use textifempty = ' ' or ' ' here, or search on key will search on ' key'. - //if (! empty($conf->use_javascript_ajax) || $forcecombo) $textifempty=''; - if (!empty($usesearchtoselect)) { - if ($showempty && !is_numeric($showempty)) $textifempty = $langs->trans($showempty); - else $textifempty .= $langs->trans("All"); - } - if ($showempty) $out .= '<option value="-1">' . $textifempty . '</option>' . "\n"; - - $selected = !empty($selected) ? (is_array($selected) ? $selected : explode(',', $selected)) : array(); - - $num = count($lines); - $i = 0; - foreach ($lines as $k => $l) { - if (in_array($k, $selected)) { - $out .= '<option value="' . $k . '" selected>' . $l . '</option>'; - } else { - $out .= '<option value="' . $k . '">' . $l . '</option>'; - } + if (empty($hidelabel)) print $langs->trans($selectlabel) . ' : '; + elseif ($hidelabel > 1) { + if (!empty($conf->global->MAIN_HTML5_PLACEHOLDER)) $placeholder = ' placeholder="' . $langs->trans($selectlabel) . '"'; + else $placeholder = ' title="' . $langs->trans($selectlabel) . '"'; + if ($hidelabel == 2) { + $out .= img_picto($langs->trans("Search"), 'search'); + } + } + $out .= '<input type="text" class="' . $morecss . '" name="search_' . $htmlname . '" id="search_' . $htmlname . '" value="' . $selected_input_value . '"' . $placeholder . ' ' . (!empty($autofocus) ? 'autofocus' : '') . ' />'; + if ($hidelabel == 3) { + $out .= img_picto($langs->trans("Search"), 'search'); + } + } else { + // Immediate load of all database + $out .= $this->select_dictionary_list($module, $name, $selected, $htmlname, $showempty, $key, $label, $filters, $orders, $forcecombo, $events, $usesearchtoselect, 0, $limit, $morecss, $moreparam, $options_only, $ismultiselect, $emptyvalue); + } + + return $out; + } + + /** + * Output html form to select a dictionary. + * Note, you must use the select_dictionary to get the component to select a dictionary. This function must only be called by select_dictionary. + * + * @param string $module Name of the module containing the dictionary + * @param string $name Name of dictionary + * @param string|array $selected Preselected values + * @param string $htmlname Name of field in form + * @param string $key Field name for the key of the line + * @param string $label Label pattern for the label of the line (replace {{FieldName}} by this value) + * @param array $filters List of filters: array(fieldName => value), value is a array search a list of rowid, if $filters = null then return no lines + * @param array $orders Order by: array(fieldName => order, ...) + * @param string $showempty Add an empty field (Can be '1' or text to use on empty line like 'SelectThirdParty') + * @param int $forcecombo Force to use combo box + * @param array $events Event options. Example: array(array('method'=>'getContacts', 'url'=>dol_buildpath('/core/ajax/contacts.php',1), 'htmlname'=>'contactid', 'params'=>array('add-customer-contact'=>'disabled'))) + * @param int $usesearchtoselect Minimum length of input string to start autocomplete + * @param int $outputmode 0=HTML select string, 1=Array + * @param int $limit Limit number of answers + * @param string $morecss Add more css styles to the SELECT component + * @param string $moreparam Add more parameters onto the select tag. For example 'style="width: 95%"' to avoid select2 component to go over parent container + * @param bool $options_only Return options only (for ajax treatment) + * @param int $ismultiselect 0=Not multiselect, 1=Multiselect + * @param string $emptyvalue Value of the empty options + * @return string|array HTML string with + */ + public function select_dictionary_list($module, $name, $selected = '', $htmlname = 'dictionaryid', $showempty = '', $key = 'rowid', $label = '{{label}}', $filters = array(), $orders = array(), $forcecombo = 0, $events = array(), $usesearchtoselect = 0, $outputmode = 0, $limit = 0, $morecss = 'minwidth100', $moreparam = '', $options_only = false, $ismultiselect = 0, $emptyvalue = '-1') + { + global $conf, $langs; + + dol_syslog(__METHOD__, LOG_DEBUG); + + // Get lines + dol_include_once('/advancedictionaries/class/dictionary.class.php'); + $dictionary = Dictionary::getDictionary($this->db, $module, $name); + $lines = $filters === null ? array() : $dictionary->fetch_array($key, $label, $filters, $orders, $limit, 1, false); + if (empty($dictionary->error)) { + $out = ''; + $outarray = array(); + + // Build output string + if ($conf->use_javascript_ajax && !$forcecombo && !$options_only) { + include_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php'; + if ($ismultiselect) { + $comboenhancement = $this->multiselect_javascript_code($selected, $htmlname, $elemtype = ''); + $comboenhancement .= $this->add_select_events($htmlname, $events); + } else { + $comboenhancement = ajax_combobox($htmlname, $events, $usesearchtoselect); + } + $out .= $comboenhancement; + } + + // Construct $out and $outarray + if (!$options_only) $out .= '<select id="' . $htmlname . '" class="flat' . ($morecss ? ' ' . $morecss : '') . '"' . ($moreparam ? ' ' . $moreparam : '') . ' name="' . $htmlname . '">' . "\n"; + + $textifempty = ''; + // Do not use textifempty = ' ' or ' ' here, or search on key will search on ' key'. + //if (! empty($conf->use_javascript_ajax) || $forcecombo) $textifempty=''; + if (!empty($usesearchtoselect)) { + if ($showempty && !is_numeric($showempty)) $textifempty = $langs->trans($showempty); + else $textifempty .= $langs->trans("All"); + } + if ($showempty) $out .= '<option value="' . $emptyvalue . '">' . $textifempty . '</option>' . "\n"; + + $selected = !empty($selected) ? (is_array($selected) ? $selected : explode(',', $selected)) : array(); + + $num = count($lines); + $i = 0; + foreach ($lines as $k => $l) { + if (in_array($k, $selected)) { + $out .= '<option value="' . $k . '" selected>' . $l . '</option>'; + } else { + $out .= '<option value="' . $k . '">' . $l . '</option>'; + } + + $tmp = array('key' => $k, 'value' => $l, 'label' => $l); + $tmp2 = array_intersect_key(is_array($dictionary->lines[$k]->fields) ? $dictionary->lines[$k]->fields : array(), is_array($dictionary->fields) ? $dictionary->fields : array()); + $tmp = array_merge($tmp, $tmp2); + array_push($outarray, $tmp); + + if (($i % 10) == 0) $out .= "\n"; + $i++; + } + if (!$options_only) $out .= '</select>' . "\n"; + + $this->result = array('nboflines' => $num); + + $this->num = $num; + if ($outputmode) return $outarray; + return $out; + } else { + $this->error = $dictionary->error; + if ($outputmode) return array(); + return -1; + } + } - $tmp = array('key' => $k, 'value' => $l, 'label' => $l); - $tmp2 = array_intersect_key(is_array($dictionary->lines[$k]->fields) ? $dictionary->lines[$k]->fields : array(), is_array($dictionary->fields) ? $dictionary->fields : array()); - $tmp = array_merge($tmp, $tmp2); - array_push($outarray, $tmp); - - if (($i % 10) == 0) $out .= "\n"; - $i++; - } - if (!$options_only) $out .= '</select>' . "\n"; - - $this->result = array('nboflines' => $num); - - $this->num = $num; - if ($outputmode) return $outarray; - return $out; - } else { - $this->error = $dictionary->error; - if ($outputmode) return array(); - return -1; - } - } - - /** - * Return list of labels (translated) of education - * - * @param string $htmlname Name of html select field ('myid' or '.myclass') - * @param array $events Event options. Example: array(array('action'=>'getContacts', 'url'=>dol_buildpath('/core/ajax/contacts.php',1), 'htmlname'=>'contactid', 'done_action'=>array('disabled' => array('add-customer-contact')))) - * 'url': string, Url of the Ajax script - * 'action': string, Action name for the Ajax script - * 'params': array(), Others parameters send for Ajax script (exclude name: id, action, htmlname), if value = '{{selector}}' get value of the 'selector' input - * 'htmlname': string, Id of the select updated with new options from Ajax script - * 'done_action': array(), List of action done when new options get successfully - * 'empty_select': array(), List of html ID of select to empty - * 'disabled' : array(), List of html ID to disable if no options - * @return string - */ + /** + * Return list of labels (translated) of education + * + * @param string $htmlname Name of html select field ('myid' or '.myclass') + * @param array $events Event options. Example: array(array('action'=>'getContacts', 'url'=>dol_buildpath('/core/ajax/contacts.php',1), 'htmlname'=>'contactid', 'done_action'=>array('disabled' => array('add-customer-contact')))) + * 'url': string, Url of the Ajax script + * 'action': string, Action name for the Ajax script + * 'params': array(), Others parameters send for Ajax script (exclude name: id, action, htmlname), if value = '{{selector}}' get value of the 'selector' input + * 'htmlname': string, Id of the select updated with new options from Ajax script + * 'done_action': array(), List of action done when new options get successfully + * 'empty_select': array(), List of html ID of select to empty + * 'disabled' : array(), List of html ID to disable if no options + * @return string + */ public function add_select_events($htmlname, $events) - { - global $conf; + { + global $conf; - $out = ''; - if (!empty($conf->use_javascript_ajax)) { - $out .= '<script type="text/javascript"> + $out = ''; + if (!empty($conf->use_javascript_ajax)) { + $out .= '<script type="text/javascript"> $(document).ready(function () { - jQuery("#'.$htmlname.'").change(function () { - var obj = '.json_encode($events).'; + jQuery("#' . $htmlname . '").change(function () { + var obj = ' . json_encode($events) . '; $.each(obj, function(key,values) { if (values.action.length) { - runJsCodeForEvent'.$htmlname.'(values); + runJsCodeForEvent' . $htmlname . '(values); } }); }); - function runJsCodeForEvent'.$htmlname.'(obj) { - console.log("Run runJsCodeForEvent'.$htmlname.'"); - var id = $("#'.$htmlname.'").val(); + function runJsCodeForEvent' . $htmlname . '(obj) { + console.log("Run runJsCodeForEvent' . $htmlname . '"); + var id = $("#' . $htmlname . '").val(); var action = obj.action; var url = obj.url; var htmlname = obj.htmlname; @@ -319,62 +321,55 @@ class FormDictionary } }); </script>'; - } - - return $out; - } - - /** - * Return multiselect javascript code - * - * @param array $selected Preselected values - * @param string $htmlname Field name in form - * @param string $elemtype Type of element we show ('category', ...) - * @return string - */ - public function multiselect_javascript_code($selected, $htmlname, $elemtype='') - { - global $conf; - - $out = ''; - - // Add code for jquery to use multiselect - if (! empty($conf->global->MAIN_USE_JQUERY_MULTISELECT) || defined('REQUIRE_JQUERY_MULTISELECT')) - { - $selected = array_values($selected); - $tmpplugin=empty($conf->global->MAIN_USE_JQUERY_MULTISELECT)?constant('REQUIRE_JQUERY_MULTISELECT'):$conf->global->MAIN_USE_JQUERY_MULTISELECT; - $out.='<!-- JS CODE TO ENABLE '.$tmpplugin.' for id '.$htmlname.' --> + } + + return $out; + } + + /** + * Return multiselect javascript code + * + * @param array $selected Preselected values + * @param string $htmlname Field name in form + * @param string $elemtype Type of element we show ('category', ...) + * @return string + */ + public function multiselect_javascript_code($selected, $htmlname, $elemtype = '') + { + global $conf; + + $out = ''; + + // Add code for jquery to use multiselect + if (!empty($conf->global->MAIN_USE_JQUERY_MULTISELECT) || defined('REQUIRE_JQUERY_MULTISELECT')) { + $selected = array_values($selected); + $tmpplugin = empty($conf->global->MAIN_USE_JQUERY_MULTISELECT) ? constant('REQUIRE_JQUERY_MULTISELECT') : $conf->global->MAIN_USE_JQUERY_MULTISELECT; + $out .= '<!-- JS CODE TO ENABLE ' . $tmpplugin . ' for id ' . $htmlname . ' --> <script type="text/javascript"> - function formatResult(record) {'."\n"; - if ($elemtype == 'category') - { - $out.=' //return \'<span><img src="'.DOL_URL_ROOT.'/theme/eldy/img/object_category.png'.'"> <a href="'.DOL_URL_ROOT.'/categories/viewcat.php?type=0&id=\'+record.id+\'">\'+record.text+\'</a></span>\'; - return \'<span><img src="'.DOL_URL_ROOT.'/theme/eldy/img/object_category.png'.'"> \'+record.text+\'</span>\';'; - } - else - { - $out.='return record.text;'; - } - $out.= ' }; - function formatSelection(record) {'."\n"; - if ($elemtype == 'category') - { - $out.=' //return \'<span><img src="'.DOL_URL_ROOT.'/theme/eldy/img/object_category.png'.'"> <a href="'.DOL_URL_ROOT.'/categories/viewcat.php?type=0&id=\'+record.id+\'">\'+record.text+\'</a></span>\'; - return \'<span><img src="'.DOL_URL_ROOT.'/theme/eldy/img/object_category.png'.'"> \'+record.text+\'</span>\';'; - } - else - { - $out.='return record.text;'; - } - $out.= ' }; + function formatResult(record) {' . "\n"; + if ($elemtype == 'category') { + $out .= ' //return \'<span><img src="' . DOL_URL_ROOT . '/theme/eldy/img/object_category.png' . '"> <a href="' . DOL_URL_ROOT . '/categories/viewcat.php?type=0&id=\'+record.id+\'">\'+record.text+\'</a></span>\'; + return \'<span><img src="' . DOL_URL_ROOT . '/theme/eldy/img/object_category.png' . '"> \'+record.text+\'</span>\';'; + } else { + $out .= 'return record.text;'; + } + $out .= ' }; + function formatSelection(record) {' . "\n"; + if ($elemtype == 'category') { + $out .= ' //return \'<span><img src="' . DOL_URL_ROOT . '/theme/eldy/img/object_category.png' . '"> <a href="' . DOL_URL_ROOT . '/categories/viewcat.php?type=0&id=\'+record.id+\'">\'+record.text+\'</a></span>\'; + return \'<span><img src="' . DOL_URL_ROOT . '/theme/eldy/img/object_category.png' . '"> \'+record.text+\'</span>\';'; + } else { + $out .= 'return record.text;'; + } + $out .= ' }; $(document).ready(function () { - $(\'#'.$htmlname.'\').attr("name", "'.$htmlname.'[]"); - $(\'#'.$htmlname.'\').attr("multiple", "multiple"); - //$.map('.json_encode($selected).', function(val, i) { - $(\'#'.$htmlname.'\').val('.json_encode($selected).'); + $(\'#' . $htmlname . '\').attr("name", "' . $htmlname . '[]"); + $(\'#' . $htmlname . '\').attr("multiple", "multiple"); + //$.map(' . json_encode($selected) . ', function(val, i) { + $(\'#' . $htmlname . '\').val(' . json_encode($selected) . '); //}); - $(\'#'.$htmlname.'\').'.$tmpplugin.'({ + $(\'#' . $htmlname . '\').' . $tmpplugin . '({ dir: \'ltr\', // Specify format function for dropdown item formatResult: formatResult, @@ -385,10 +380,10 @@ class FormDictionary }); }); </script>'; - } + } - return $out; - } + return $out; + } /** * Show a confirmation HTML form or AJAX popup. @@ -415,7 +410,7 @@ class FormDictionary * @param int $disableformtag 1=Disable form tag. Can be used if we are already inside a <form> section. * @return string HTML ajax code if a confirm ajax popup is required, Pure HTML code if it's an html form */ - public function formconfirm($page, $title, $question, $action, $formquestion=array(), $selectedchoice="", $useajax=0, $height=200, $width=500, $post=0, $resizable=0, $disableformtag = 0) + public function formconfirm($page, $title, $question, $action, $formquestion = array(), $selectedchoice = "", $useajax = 0, $height = 200, $width = 500, $post = 0, $resizable = 0, $disableformtag = 0) { global $langs, $conf, $form; @@ -424,7 +419,7 @@ class FormDictionary $form = new Form($this->db); } - $more = '<!-- formconfirm before calling page='.dol_escape_htmltag($page).' -->'; + $more = '<!-- formconfirm before calling page=' . dol_escape_htmltag($page) . ' -->'; $formconfirm = ''; $inputok = array(); $inputko = array(); @@ -445,10 +440,10 @@ class FormDictionary if (is_array($formquestion) && !empty($formquestion)) { if ($post) { - $more .= '<form id="form_dialog_confirm" name="form_dialog_confirm" action="'.$page.'" method="POST" enctype="multipart/form-data">'; + $more .= '<form id="form_dialog_confirm" name="form_dialog_confirm" action="' . $page . '" method="POST" enctype="multipart/form-data">'; $more .= '<input type="hidden" id="confirm" name="confirm" value="yes">' . "\n"; - $more .= '<input type="hidden" id="action" name="action" value="'.$action.'">' . "\n"; - $more .= '<input type="hidden" id="token" name="token" value="'.newToken().'">' . "\n"; + $more .= '<input type="hidden" id="action" name="action" value="' . $action . '">' . "\n"; + $more .= '<input type="hidden" id="token" name="token" value="' . newToken() . '">' . "\n"; } // First add hidden fields and value foreach ($formquestion as $key => $input) { @@ -469,14 +464,14 @@ class FormDictionary if ($input['type'] == 'text') { $more .= '<tr class="oddeven"><td class="titlefield">' . $input['label'] . '</td><td colspan="2" align="left"><input type="text" class="flat" id="' . $input['name'] . '" name="' . $input['name'] . '"' . $size . ' value="' . $input['value'] . '" /></td></tr>' . "\n"; - } else if ($input['type'] == 'password') { + } elseif ($input['type'] == 'password') { $more .= '<tr class="oddeven"><td class="titlefield">' . $input['label'] . '</td><td colspan="2" align="left"><input type="password" class="flat" id="' . $input['name'] . '" name="' . $input['name'] . '"' . $size . ' value="' . $input['value'] . '" /></td></tr>' . "\n"; - } else if ($input['type'] == 'select') { + } elseif ($input['type'] == 'select') { $more .= '<tr class="oddeven"><td class="titlefield">'; if (!empty($input['label'])) $more .= $input['label'] . '</td><td valign="top" colspan="2" align="left">'; $more .= $form->selectarray($input['name'], $input['values'], $input['default'], 1); $more .= '</td></tr>' . "\n"; - } else if ($input['type'] == 'checkbox') { + } elseif ($input['type'] == 'checkbox') { $more .= '<tr class="oddeven">'; $more .= '<td class="titlefield">' . $input['label'] . ' </td><td align="left">'; $more .= '<input type="checkbox" class="flat" id="' . $input['name'] . '" name="' . $input['name'] . '"'; @@ -486,7 +481,7 @@ class FormDictionary $more .= ' /></td>'; $more .= '<td align="left"> </td>'; $more .= '</tr>' . "\n"; - } else if ($input['type'] == 'radio') { + } elseif ($input['type'] == 'radio') { $i = 0; foreach ($input['values'] as $selkey => $selval) { $more .= '<tr class="oddeven">'; @@ -500,7 +495,7 @@ class FormDictionary $more .= '</td></tr>' . "\n"; $i++; } - } else if ($input['type'] == 'date') { + } elseif ($input['type'] == 'date') { $more .= '<tr class="oddeven"><td class="titlefield">' . $input['label'] . '</td>'; $more .= '<td colspan="2" align="left">'; $more .= $form->select_date($input['value'], $input['name'], $input['hour'] ? 1 : 0, $input['minute'] ? 1 : 0, 0, '', 1, $input['addnowlink'] ? 1 : 0, 1); @@ -510,12 +505,12 @@ class FormDictionary $formquestion[] = array('name' => $input['name'] . 'year'); $formquestion[] = array('name' => $input['name'] . 'hour'); $formquestion[] = array('name' => $input['name'] . 'min'); - } else if ($input['type'] == 'other') { + } elseif ($input['type'] == 'other') { $more .= '<tr class="oddeven"><td class="titlefield">'; if (!empty($input['label'])) $more .= $input['label'] . '</td><td colspan="2" align="left">'; $more .= $input['value']; $more .= '</td></tr>' . "\n"; - } else if ($input['type'] == 'onecolumn') { + } elseif ($input['type'] == 'onecolumn') { $more .= '<tr class="oddeven"><td class="titlefield" colspan="3" align="left">'; $more .= $input['value']; $more .= '</td></tr>' . "\n"; @@ -566,12 +561,12 @@ class FormDictionary // Show JQuery confirm box. $formconfirm .= '<div id="' . $dialogconfirm . '" title="' . dol_escape_htmltag($title) . '" style="display: none;">'; if (!empty($more)) { - $formconfirm .= '<div class="confirmquestions">'.$more.'</div>'."\n"; + $formconfirm .= '<div class="confirmquestions">' . $more . '</div>' . "\n"; } $formconfirm .= ($question ? '<div class="confirmmessage">' . img_help('', '') . ' ' . $question . '</div>' : ''); $formconfirm .= '</div>' . "\n"; - $formconfirm .= "\n<!-- begin code of popup for formconfirm page=".$page." -->\n"; + $formconfirm .= "\n<!-- begin code of popup for formconfirm page=" . $page . " -->\n"; $formconfirm .= '<script type="text/javascript">' . "\n"; $formconfirm .= "/* Code for the jQuery('#dialogforpopup').dialog() */\n"; $formconfirm .= 'jQuery(document).ready(function() { @@ -629,8 +624,8 @@ class FormDictionary closeOnEscape: false, buttons: { "' . dol_escape_js($langs->transnoentities("Yes")) . '": function() { - var options = "&token='.urlencode(newToken()).'"; - var inputok = '.json_encode($inputok).'; /* List of fields into form */ + var options = "&token=' . urlencode(newToken()) . '"; + var inputok = ' . json_encode($inputok) . '; /* List of fields into form */ var pageyes = "' . dol_escape_js(!empty($pageyes) ? $pageyes : '') . '"; if (inputok.length>0) { $.each(inputok, function(i, inputname) { @@ -652,8 +647,8 @@ class FormDictionary $(this).dialog("close"); }, "' . dol_escape_js($langs->transnoentities("No")) . '": function() { - var options = "&token='.urlencode(newToken()).'"; - var inputko = '.json_encode($inputko).'; /* List of fields into form */ + var options = "&token=' . urlencode(newToken()) . '"; + var inputko = ' . json_encode($inputko) . '; /* List of fields into form */ var pageno="' . dol_escape_js(!empty($pageno) ? $pageno : '') . '"; if (inputko.length>0) { $.each(inputko, function(i, inputname) { @@ -685,30 +680,30 @@ class FormDictionary } $formconfirm .= "<!-- end ajax formconfirm -->\n"; } else { - $formconfirm .= "\n<!-- begin formconfirm page=".dol_escape_htmltag($page)." -->\n"; + $formconfirm .= "\n<!-- begin formconfirm page=" . dol_escape_htmltag($page) . " -->\n"; if (empty($disableformtag)) { $formconfirm .= '<form method="POST" action="' . $page . '" class="notoptoleftroright">' . "\n"; } $formconfirm .= '<input type="hidden" name="action" value="' . $action . '">' . "\n"; - $formconfirm .= '<input type="hidden" name="token" value="'.newToken().'">'."\n"; + $formconfirm .= '<input type="hidden" name="token" value="' . newToken() . '">' . "\n"; - $formconfirm .= '<table class="valid centpercent">'."\n"; + $formconfirm .= '<table class="valid centpercent">' . "\n"; // Line title $formconfirm .= '<tr class="validtitre"><td class="validtitre" colspan="2">'; - $formconfirm .= img_picto('', 'recent').' '.$title; - $formconfirm .= '</td></tr>'."\n"; + $formconfirm .= img_picto('', 'recent') . ' ' . $title; + $formconfirm .= '</td></tr>' . "\n"; // Line text if (is_array($formquestion) && !empty($formquestion['text'])) { - $formconfirm .= '<tr class="valid"><td class="valid" colspan="2">'.$formquestion['text'].'</td></tr>'."\n"; + $formconfirm .= '<tr class="valid"><td class="valid" colspan="2">' . $formquestion['text'] . '</td></tr>' . "\n"; } // Line form fields if ($more) { - $formconfirm .= '<tr class="valid"><td class="valid" colspan="2">'."\n"; + $formconfirm .= '<tr class="valid"><td class="valid" colspan="2">' . "\n"; $formconfirm .= $more; $formconfirm .= '</td></tr>' . "\n"; } @@ -718,7 +713,7 @@ class FormDictionary $formconfirm .= '<td class="valid">' . $question . '</td>'; $formconfirm .= '<td class="valid center">'; $formconfirm .= $this->selectyesno("confirm", $newselectedchoice, 0, false, 0, 0, 'marginleftonly marginrightonly'); - $formconfirm .= '<input class="button valignmiddle confirmvalidatebutton small" type="submit" value="'.$langs->trans("Validate").'">'; + $formconfirm .= '<input class="button valignmiddle confirmvalidatebutton small" type="submit" value="' . $langs->trans("Validate") . '">'; $formconfirm .= '</td>'; $formconfirm .= '</tr>' . "\n"; @@ -731,7 +726,7 @@ class FormDictionary if (!empty($conf->use_javascript_ajax)) { $formconfirm .= '<!-- code to disable button to avoid double clic -->'; - $formconfirm .= '<script type="text/javascript">'."\n"; + $formconfirm .= '<script type="text/javascript">' . "\n"; $formconfirm .= ' $(document).ready(function () { $(".confirmvalidatebutton").on("click", function() { @@ -743,7 +738,7 @@ class FormDictionary }); }); '; - $formconfirm .= '</script>'."\n"; + $formconfirm .= '</script>' . "\n"; } $formconfirm .= "<!-- end formconfirm -->\n"; @@ -782,31 +777,27 @@ class FormDictionary } // Add code for jquery to use multiselect - if (!empty($conf->global->MAIN_USE_JQUERY_MULTISELECT) || defined('REQUIRE_JQUERY_MULTISELECT')) - { - $out .= "\n".'<!-- JS CODE TO ENABLE select for id '.$htmlname.', addjscombo='.$addjscombo.' --> - <script>'."\n"; - if ($addjscombo == 1) - { + if (!empty($conf->global->MAIN_USE_JQUERY_MULTISELECT) || defined('REQUIRE_JQUERY_MULTISELECT')) { + $out .= "\n" . '<!-- JS CODE TO ENABLE select for id ' . $htmlname . ', addjscombo=' . $addjscombo . ' --> + <script>' . "\n"; + if ($addjscombo == 1) { $tmpplugin = "ADselect2Sortable"; - $out .= 'function formatResult(record) {'."\n"; - if ($elemtype == 'category') - { - $out .= 'return \'<span><img src="'.DOL_URL_ROOT.'/theme/eldy/img/object_category.png"> \'+record.text+\'</span>\';'; + $out .= 'function formatResult(record) {' . "\n"; + if ($elemtype == 'category') { + $out .= 'return \'<span><img src="' . DOL_URL_ROOT . '/theme/eldy/img/object_category.png"> \'+record.text+\'</span>\';'; } else { $out .= 'return record.text;'; } - $out .= '};'."\n"; - $out .= 'function formatSelection(record) {'."\n"; - if ($elemtype == 'category') - { - $out .= 'return \'<span><img src="'.DOL_URL_ROOT.'/theme/eldy/img/object_category.png"> \'+record.text+\'</span>\';'; + $out .= '};' . "\n"; + $out .= 'function formatSelection(record) {' . "\n"; + if ($elemtype == 'category') { + $out .= 'return \'<span><img src="' . DOL_URL_ROOT . '/theme/eldy/img/object_category.png"> \'+record.text+\'</span>\';'; } else { $out .= 'return record.text;'; } - $out .= '};'."\n"; + $out .= '};' . "\n"; $out .= '$(document).ready(function () { - $(\'#'.$htmlname.'\').'.$tmpplugin.'({ + $(\'#' . $htmlname . '\').' . $tmpplugin . '({ dir: \'ltr\', // Specify format function for dropdown item formatResult: formatResult, @@ -818,22 +809,21 @@ class FormDictionary /* Add also morecss to the css .select2 that is after the #htmlname, for component that are show dynamically after load, because select2 set the size only if component is not hidden by default on load */ - $(\'#'.$htmlname.' + .select2\').addClass(\''.$morecss.'\'); - });'."\n"; - } elseif ($addjscombo == 2 && !defined('DISABLE_MULTISELECT')) - { + $(\'#' . $htmlname . ' + .select2\').addClass(\'' . $morecss . '\'); + });' . "\n"; + } elseif ($addjscombo == 2 && !defined('DISABLE_MULTISELECT')) { // Add other js lib // TODO external lib multiselect/jquery.multi-select.js must have been loaded to use this multiselect plugin // ... - $out .= 'console.log(\'addjscombo=2 for htmlname='.$htmlname.'\');'; + $out .= 'console.log(\'addjscombo=2 for htmlname=' . $htmlname . '\');'; $out .= '$(document).ready(function () { - $(\'#'.$htmlname.'\').multiSelect({ + $(\'#' . $htmlname . '\').multiSelect({ containerHTML: \'<div class="multi-select-container">\', menuHTML: \'<div class="multi-select-menu">\', - buttonHTML: \'<span class="multi-select-button '.$morecss.'">\', + buttonHTML: \'<span class="multi-select-button ' . $morecss . '">\', menuItemHTML: \'<label class="multi-select-menuitem">\', activeClass: \'multi-select-container--open\', - noneText: \''.$placeholder.'\' + noneText: \'' . $placeholder . '\' }); })'; } @@ -841,42 +831,37 @@ class FormDictionary } // Try also magic suggest - $out .= '<select id="'.$htmlname.'" class="multiselect'.($morecss ? ' '.$morecss : '').'" multiple name="'.$htmlname.'[]"'.($moreattrib ? ' '.$moreattrib : '').($width ? ' style="width: '.(preg_match('/%/', $width) ? $width : $width.'px').'"' : '').'>'."\n"; - if (is_array($array) && !empty($array)) - { + $out .= '<select id="' . $htmlname . '" class="multiselect' . ($morecss ? ' ' . $morecss : '') . '" multiple name="' . $htmlname . '[]"' . ($moreattrib ? ' ' . $moreattrib : '') . ($width ? ' style="width: ' . (preg_match('/%/', $width) ? $width : $width . 'px') . '"' : '') . '>' . "\n"; + if (is_array($array) && !empty($array)) { if ($value_as_key) $array = array_combine($array, $array); - if (!empty($array)) - { + if (!empty($array)) { $sortedDataArray = array(); //Will contain all data but with selected value sorted - foreach($selected as $selectedKey) { - if(!empty($array[$selectedKey])) { + foreach ($selected as $selectedKey) { + if (!empty($array[$selectedKey])) { $sortedDataArray[$selectedKey] = $array[$selectedKey]; unset($array[$selectedKey]); } } $sortedDataArray = $sortedDataArray + $array; - foreach ($sortedDataArray as $key => $value) - { + foreach ($sortedDataArray as $key => $value) { $newval = ($translate ? $langs->trans($value) : $value); - $newval = ($key_in_label ? $key.' - '.$newval : $newval); + $newval = ($key_in_label ? $key . ' - ' . $newval : $newval); - $out .= '<option value="'.$key.'"'; - if (is_array($selected) && !empty($selected) && in_array((string) $key, $selected) && ((string) $key != '')) - { + $out .= '<option value="' . $key . '"'; + if (is_array($selected) && !empty($selected) && in_array((string) $key, $selected) && ((string) $key != '')) { $out .= ' selected'; } - $out .= ' data-html="'.dol_escape_htmltag($newval).'"'; + $out .= ' data-html="' . dol_escape_htmltag($newval) . '"'; $out .= '>'; $out .= dol_htmlentitiesbr($newval); - $out .= '</option>'."\n"; + $out .= '</option>' . "\n"; } } } - $out .= '</select>'."\n"; + $out .= '</select>' . "\n"; return $out; } - } -- GitLab From 30f8db8a4c4c7b2daf9af07387d97d005331dc81 Mon Sep 17 00:00:00 2001 From: Kamel Khelifa <kkhelifa@open-dsi.fr> Date: Tue, 11 Mar 2025 10:28:19 +0100 Subject: [PATCH 2/3] Change version --- ChangeLog.md | 8 +++++--- VERSION | 2 +- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/ChangeLog.md b/ChangeLog.md index 495713e..5ac8d31 100755 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -3,9 +3,11 @@ Le format du fichier est basé sur [Tenez un ChangeLog](http://keepachangelog.co ## [Non Distribué] +## [14.0.14] - 11-03-2025 +- Ajout d'un paramètre 'emptyvalue' aux fonctions FormDictionary::select_dictionary et FormDictionary::select_dictionary_list + ## [14.0.13] - 10-03-2025 - Fix affichage de l'aide -- Ajout d'un paramètre 'emptyvalue' aux fonctions FormDictionary::select_dictionary et FormDictionary::select_dictionary_list ## [14.0.12] - 10-02-2025 - Compatibilité V21 @@ -286,8 +288,8 @@ Le format du fichier est basé sur [Tenez un ChangeLog](http://keepachangelog.co ## [4.0.0] - 16-07-2018 - Version initial. -[Non Distribué]: https://github.com/OPEN-DSI/dolibarr_module_advancedictionaries/compare/14.0.13...HEAD -[14.0.13]: https://github.com/OPEN-DSI/dolibarr_module_advancedictionaries/commits/14.0.13 +[Non Distribué]: https://github.com/OPEN-DSI/dolibarr_module_advancedictionaries/compare/14.0.14...HEAD +[14.0.14]: https://github.com/OPEN-DSI/dolibarr_module_advancedictionaries/commits/14.0.14 [14.0.12]: https://github.com/OPEN-DSI/dolibarr_module_advancedictionaries/commits/14.0.12 [14.0.11]: https://github.com/OPEN-DSI/dolibarr_module_advancedictionaries/commits/14.0.11 [14.0.10]: https://github.com/OPEN-DSI/dolibarr_module_advancedictionaries/commits/14.0.10 diff --git a/VERSION b/VERSION index 4526d8d..ce07870 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -14.0.13 \ No newline at end of file +14.0.14 \ No newline at end of file -- GitLab From ae4bfad207f0b93b0b3684359b0f0e50e0f018ca Mon Sep 17 00:00:00 2001 From: Kamel Khelifa <kkhelifa@open-dsi.fr> Date: Tue, 11 Mar 2025 10:39:57 +0100 Subject: [PATCH 3/3] Correction --- class/html.formdictionary.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/class/html.formdictionary.class.php b/class/html.formdictionary.class.php index 65cb863..ba4a3af 100755 --- a/class/html.formdictionary.class.php +++ b/class/html.formdictionary.class.php @@ -191,7 +191,7 @@ class FormDictionary if (!empty($usesearchtoselect)) { if ($showempty && !is_numeric($showempty)) $textifempty = $langs->trans($showempty); else $textifempty .= $langs->trans("All"); - } + } else $textifempty = ' '; if ($showempty) $out .= '<option value="' . $emptyvalue . '">' . $textifempty . '</option>' . "\n"; $selected = !empty($selected) ? (is_array($selected) ? $selected : explode(',', $selected)) : array(); -- GitLab