47function ajax_autocompleter($selected, $htmlname, $url, $urloption =
'', $minLength = 2, $autoselect = 0, $ajaxoptions = array(), $moreparams =
'')
51 if (empty($minLength)) {
55 $dataforrenderITem =
'ui-autocomplete';
56 $dataforitem =
'ui-autocomplete-item';
58 if (defined(
'JS_QUERY_AUTOCOMPLETE_RENDERITEM')) {
59 $dataforrenderITem = constant(
'JS_QUERY_AUTOCOMPLETE_RENDERITEM');
61 if (defined(
'JS_QUERY_AUTOCOMPLETE_ITEM')) {
62 $dataforitem = constant(
'JS_QUERY_AUTOCOMPLETE_ITEM');
65 $htmlnamejquery = str_replace(
'.',
'\\\\.', $htmlname);
69 $script =
'<input type="hidden" name="'.$htmlname.
'" id="'.$htmlname.
'" value="'.$selected.
'" '.($moreparams ? $moreparams :
'').
' />';
71 $script .=
'<!-- Javascript code for autocomplete of field '.$htmlname.
' -->'.
"\n";
72 $script .=
'<script>'.
"\n";
73 $script .=
'$(document).ready(function() {
74 var autoselect = '.((int) $autoselect).
';
75 var options = '.json_encode($ajaxoptions).
'; /* Option of actions to do after keyup, or after select */
77 /* Remove selected id as soon as we type or delete a char (it means old selection is wrong). Use keyup/down instead of change to avoid loosing the product id. This is needed only for select of predefined product */
78 $("input#search_'.$htmlnamejquery.
'").keydown(function(e) {
79 if (e.keyCode != 9) /* If not "Tab" key */
81 if (e.keyCode == 13) { return false; } /* disable "ENTER" key useful for barcode readers */
82 console.log("Clear id previously selected for field '.$htmlname.
'");
83 $("#'.$htmlnamejquery.
'").val("");
87 // Check options for secondary actions when keyup
88 $("input#search_'.$htmlnamejquery.
'").keyup(function() {
89 if ($(this).val().length == 0)
91 $("#search_'.$htmlnamejquery.
'").val("");
92 $("#'.$htmlnamejquery.
'").val("").trigger("change");
93 if (options.option_disabled) {
94 $("#" + options.option_disabled).removeAttr("disabled");
96 if (options.disabled) {
97 $.each(options.disabled, function(key, value) {
98 $("#" + value).removeAttr("disabled");
101 if (options.update) {
102 $.each(options.update, function(key, value) {
103 $("#" + key).val("").trigger("change");
107 $.each(options.show, function(key, value) {
108 $("#" + value).hide().trigger("hide");
111 if (options.update_textarea) {
112 $.each(options.update_textarea, function(key, value) {
113 if (typeof CKEDITOR == "object" && typeof CKEDITOR.instances != "undefined" && CKEDITOR.instances[key] != "undefined") {
114 CKEDITOR.instances[key].setData("");
116 $("#" + key).html("");
123 $("input#search_'.$htmlnamejquery.
'").autocomplete({
124 source: function( request, response ) {
125 $.get("'.$url.($urloption ?
'?'.$urloption :
'').
'", { "'.str_replace(
'.',
'_', $htmlname).
'": request.term }, function(data){
128 response($.map( data, function(item) {
129 if (autoselect == 1 && data.length == 1) {
130 $("#search_'.$htmlnamejquery.
'").val(item.value);
131 $("#'.$htmlnamejquery.
'").val(item.key).trigger("change");
134 if (item.label != null) {
135 label = item.label.toString();
138 if (options.update) {
139 $.each(options.update, function(key, value) {
140 update[key] = item[value];
144 if (options.update_textarea) {
145 $.each(options.update_textarea, function(key, value) {
146 textarea[key] = item[value];
150 console.log("Return value from GET to the rest of code");
151 return { label: label,
154 disabled: item.disabled,
160 discount: item.discount,
161 pricebasetype: item.pricebasetype,
162 price_ht: item.price_ht,
163 price_ttc: item.price_ttc,
164 price_unit_ht: item.price_unit_ht,
165 price_unit_ht_locale: item.price_unit_ht_locale,
166 description : item.description,
167 ref_customer: item.ref_customer,
169 default_vat_code: item.default_vat_code
173 console.error("Error: Ajax url '.$url.($urloption ?
'?'.$urloption :
'').
' has returned an empty page. Should be an empty json array.");
178 minLength: '.((
int) $minLength).
',
179 select: function( event, ui ) { // Function ran once new value has been selected into javascript combo
180 console.log("We will trigger change on input '.$htmlname.
' because of the select definition of autocomplete code for input#search_'.$htmlname.
'");
181 console.log("Selected id = "+ui.item.id+" - If this value is null, it means you select a record with key that is null so selection is not effective");
183 console.log("Propagate before some properties retrieved by ajax into data-xxx properties of #'.$htmlnamejquery.
' component");
184 //console.log(ui.item);
186 // For supplier price and customer when price by quantity is off
187 $("#'.$htmlnamejquery.
'").attr("data-up", ui.item.price_ht);
188 $("#'.$htmlnamejquery.
'").attr("data-up-locale", ui.item.price_unit_ht_locale);
189 $("#'.$htmlnamejquery.
'").attr("data-base", ui.item.pricebasetype);
190 $("#'.$htmlnamejquery.
'").attr("data-qty", ui.item.qty);
191 $("#'.$htmlnamejquery.
'").attr("data-discount", ui.item.discount);
192 $("#'.$htmlnamejquery.
'").attr("data-description", ui.item.description);
193 $("#'.$htmlnamejquery.
'").attr("data-ref-customer", ui.item.ref_customer);
194 $("#'.$htmlnamejquery.
'").attr("data-tvatx", ui.item.tva_tx);
195 $("#'.$htmlnamejquery.
'").attr("data-default-vat-code", ui.item.default_vat_code);
197 if (!empty($conf->global->PRODUIT_CUSTOMER_PRICES_BY_QTY) || !empty($conf->global->PRODUIT_CUSTOMER_PRICES_BY_QTY_MULTIPRICES)) {
199 // For customer price when PRODUIT_CUSTOMER_PRICES_BY_QTY is on
200 console.log("PRODUIT_CUSTOMER_PRICES_BY_QTY is on, propagate also prices by quantity into data-pbqxxx properties");
201 $("#'.$htmlnamejquery.
'").attr("data-pbq", ui.item.pbq);
202 $("#'.$htmlnamejquery.
'").attr("data-pbqup", ui.item.price_ht);
203 $("#'.$htmlnamejquery.
'").attr("data-pbqbase", ui.item.pricebasetype);
204 $("#'.$htmlnamejquery.
'").attr("data-pbqqty", ui.item.qty);
205 $("#'.$htmlnamejquery.
'").attr("data-pbqpercent", ui.item.discount);
209 // A new value has been selected, we trigger the handlers on #htmlnamejquery
210 console.log("Trigger changes on #'.$htmlnamejquery.
'");
211 $("#'.$htmlnamejquery.
'").val(ui.item.id).trigger("change"); // Select new value
213 // Complementary actions
215 // Disable an element
216 if (options.option_disabled) {
217 console.log("Make action option_disabled on #"+options.option_disabled+" with disabled="+ui.item.disabled)
218 if (ui.item.disabled) {
219 $("#" + options.option_disabled).prop("disabled", true);
221 $.jnotify(options.error, "error", true); // Output with jnotify the error message
223 if (options.warning) {
224 $.jnotify(options.warning, "warning", false); // Output with jnotify the warning message
227 $("#" + options.option_disabled).removeAttr("disabled");
231 if (options.disabled) {
232 console.log("Make action disabled on each "+options.option_disabled)
233 $.each(options.disabled, function(key, value) {
234 $("#" + value).prop("disabled", true);
238 console.log("Make action show on each "+options.show)
239 $.each(options.show, function(key, value) {
240 $("#" + value).show().trigger("show");
245 if (ui.item.update) {
246 console.log("Make action update on each ui.item.update (if there is)")
247 // loop on each "update" fields
248 $.each(ui.item.update, function(key, value) {
249 console.log("Set value "+value+" into #"+key);
250 $("#" + key).val(value).trigger("change");
253 if (ui.item.textarea) {
254 console.log("Make action textarea on each ui.item.textarea (if there is)")
255 $.each(ui.item.textarea, function(key, value) {
256 if (typeof CKEDITOR == "object" && typeof CKEDITOR.instances != "undefined" && CKEDITOR.instances[key] != "undefined") {
257 CKEDITOR.instances[key].setData(value);
258 CKEDITOR.instances[key].focus();
260 $("#" + key).html(value);
261 $("#" + key).focus();
265 console.log("ajax_autocompleter new value selected, we trigger change also on original component so on field #search_'.$htmlname.
'");
267 $("#search_'.$htmlnamejquery.
'").trigger("change"); // We have changed value of the combo select, we must be sure to trigger all js hook binded on this event. This is required to trigger other javascript change method binded on original field by other code.
270 }).data("'.$dataforrenderITem.
'")._renderItem = function( ul, item ) {
272 .data( "'.$dataforitem.
'", item ) // jQuery UI > 1.10.0
273 .append( \'<a><span class="tag">\' + item.label + "</span></a>" )
278 $script .=
'</script>';
449function ajax_combobox($htmlname, $events = array(), $minLengthToAutocomplete = 0, $forcefocus = 0, $widthTypeOfAutocomplete =
'resolve', $idforemptyvalue =
'-1', $morecss =
'')
454 if (!empty($conf->browser->layout) && $conf->browser->layout ==
'phone' && !empty($conf->global->MAIN_DISALLOW_SELECT2_WITH_SMARTPHONE)) {
458 if (!empty($conf->global->MAIN_DISABLE_AJAX_COMBOX)) {
461 if (empty($conf->use_javascript_ajax)) {
464 if (empty($conf->global->MAIN_USE_JQUERY_MULTISELECT) && !defined(
'REQUIRE_JQUERY_MULTISELECT')) {
467 if (!empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER)) {
471 if (empty($minLengthToAutocomplete)) {
472 $minLengthToAutocomplete = 0;
475 $moreselect2theme = ($morecss ?
dol_escape_js(
' '.$morecss) :
'');
476 $moreselect2theme = preg_replace(
'/widthcentpercentminus[^\s]*/',
'', $moreselect2theme);
478 $tmpplugin =
'select2';
479 $msg =
"\n".
'<!-- JS CODE TO ENABLE '.$tmpplugin.
' for id = '.$htmlname.
' -->
481 $(document).ready(function () {
482 $(\''.(preg_match(
'/^\./', $htmlname) ? $htmlname :
'#'.$htmlname).
'\').
'.$tmpplugin.'({
484 if (preg_match(
'/onrightofpage/', $morecss)) {
485 $msg .=
' dropdownAutoWidth: true, dropdownParent: $(\'#'.$htmlname.
'\').parent(),
'."\n";
487 $msg .= ' width: \
''.dol_escape_js($widthTypeOfAutocomplete).
'\',
488 minimumInputLength:
'.((int) $minLengthToAutocomplete).',
489 language: select2arrayoflanguage,
490 matcher:
function (params, data) {
491 if ($.trim(params.term) ===
"") {
494 keywords = (params.term).split(
" ");
495 for (var i = 0; i < keywords.length; i++) {
496 if (((data.text).toUpperCase()).indexOf((keywords[i]).toUpperCase()) == -1) {
502 theme: \
'default'.$moreselect2theme.
'\',
503 containerCssClass: \
':all:\', /* Line to add class of origin SELECT propagated to the new <span class="select2-selection...> tag */
504 selectionCssClass: \':all:\', /* Line to add class of origin SELECT propagated to the new <span class="select2-selection...> tag */
505 dropdownCssClass: \'ui-dialog\',
506 templateResult: function (data, container) { /* Format visible output into combo list */
507 /* Code to add class of origin OPTION propagated to the new select2 <li> tag */
508 if (data.element) { $(container).addClass($(data.element).attr("class")); }
509 //console.log("data html is "+$(data.element).attr("data-html"));
510 if (data.id == '.((int) $idforemptyvalue).
' && $(data.element).attr("data-html") == undefined) {
513 if ($(data.element).attr("data-html") != undefined) {
514 /* If property html set, we decode html entities and use this. */
515 /* Note that HTML content must have been sanitized from js with dol_escape_htmltag(xxx, 0, 0, \'\', 0, 1) when building the select option. */
516 return htmlEntityDecodeJs($(data.element).attr("data-html"));
520 templateSelection: function (selection) { /* Format visible output of selected value */
521 if (selection.id == '.((int) $idforemptyvalue).
') return \'<span class="placeholder">\'+selection.text+\'</span>\';
522 return selection.text;
524 escapeMarkup: function(markup) {
529 $msg .=
'.select2(\'focus\')';
534 $msg .=
"</script>\n";
630function ajax_constantonoff($code, $input = array(), $entity =
null, $revertonoff = 0, $strict = 0, $forcereload = 0, $marginleftonlyshort = 2, $forcenoajax = 0, $setzeroinsteadofdel = 0, $suffix =
'', $mode =
'', $morecss =
'')
632 global $conf, $langs, $user;
634 $entity = ((isset($entity) && is_numeric($entity) && $entity >= 0) ? $entity : $conf->entity);
635 if (!isset($input)) {
639 if (empty($conf->use_javascript_ajax) || $forcenoajax) {
640 if (empty($conf->global->$code)) {
641 print
'<a '.($morecss ?
'class="'.$morecss.
'" ' :
'').
'href="'.$_SERVER[
'PHP_SELF'].
'?action=set_'.$code.
'&token='.newToken().
'&entity='.$entity.($mode ?
'&mode='.$mode :
'').($forcereload ?
'&dol_resetcache=1' :
'').
'">'.
img_picto($langs->trans(
"Disabled"),
'off').
'</a>';
643 print
'<a '.($morecss ?
'class="'.$morecss.
'" ' :
'').
' href="'.$_SERVER[
'PHP_SELF'].
'?action=del_'.$code.
'&token='.newToken().
'&entity='.$entity.($mode ?
'&mode='.$mode :
'').($forcereload ?
'&dol_resetcache=1' :
'').
'">'.
img_picto($langs->trans(
"Enabled"),
'on').
'</a>';
646 $out =
"\n<!-- Ajax code to switch constant ".$code.
" -->".
'
648 $(document).ready(function() {
649 var input = '.json_encode($input).
';
650 var url = \''.DOL_URL_ROOT.
'/core/ajax/constantonoff.php\';
652 var entity = \
''.dol_escape_js($entity).
'\';
653 var strict = \
''.dol_escape_js($strict).
'\';
654 var userid = \
''.dol_escape_js($user->id).
'\';
655 var yesButton = \
''.dol_escape_js($langs->transnoentities(
"Yes")).
'\';
656 var noButton = \
''.dol_escape_js($langs->transnoentities(
"No")).
'\';
657 var token = \
''.currentToken().
'\';
660 $(
"#set_" + code).click(
function() {
661 if (input.alert && input.alert.set) {
662 if (input.alert.set.yesButton) yesButton = input.alert.set.yesButton;
663 if (input.alert.set.noButton) noButton = input.alert.set.noButton;
664 confirmConstantAction(
"set", url, code, input, input.alert.set, entity, yesButton, noButton, strict, userid, token);
666 setConstant(url, code, input, entity, 0,
'.((int) $forcereload).', userid, token);
671 $(
"#del_" + code).click(
function() {
672 if (input.alert && input.alert.del) {
673 if (input.alert.del.yesButton) yesButton = input.alert.del.yesButton;
674 if (input.alert.del.noButton) noButton = input.alert.del.noButton;
675 confirmConstantAction(
"del", url, code, input, input.alert.del, entity, yesButton, noButton, strict, userid, token);
677 if (empty($setzeroinsteadofdel)) {
678 $out .=' delConstant(url, code, input, entity, 0,
'.((int) $forcereload).', userid, token);
';
680 $out .=' setConstant(url, code, input, entity, 0,
'.((int) $forcereload).', userid, token, 0);
';
687 $out .= '<div
id=
"confirm_'.$code.'" title=
"" style=
"display: none;"></div>
';
688 $out .= '<span
id=
"set_'.$code.'" class=
"valignmiddle linkobject '.(!empty($conf->global->$code) ? 'hideobject' : '').'">
'.($revertonoff ?img_picto($langs->trans("Enabled"), 'switch_on
', '', false, 0, 0, '', '', $marginleftonlyshort) : img_picto($langs->trans("Disabled"), 'switch_off
', '', false, 0, 0, '', '', $marginleftonlyshort)).'</span>
';
689 $out .= '<span
id=
"del_'.$code.'" class=
"valignmiddle linkobject '.(!empty($conf->global->$code) ? '' : 'hideobject').'">
'.($revertonoff ?img_picto($langs->trans("Disabled"), 'switch_off
'.$suffix, '', false, 0, 0, '', '', $marginleftonlyshort) : img_picto($langs->trans("Enabled"), 'switch_on
'.$suffix, '', false, 0, 0, '', '', $marginleftonlyshort)).'</span>
';
711function ajax_object_onoff($object, $code, $field, $text_on, $text_off, $input = array(), $morecss = '
', $htmlname = '', $forcenojs = 0)
713 global $conf, $langs;
715 if (empty($htmlname)) {
718 //var_dump($object->module); var_dump($object->element);
722 if (!empty($conf->use_javascript_ajax)) {
725 var input =
'.json_encode($input).';
728 $(
"#set_'.$htmlname.'_'.$object->id.'").click(
function() {
729 console.log(
"Click managed by ajax_object_onoff");
730 $.get(
"'.DOL_URL_ROOT.'/core/ajax/objectonoff.php", {
732 field: \''.dol_escape_js($field).
'\',
734 element: \''.dol_escape_js((empty($object->module) || $object->module == $object->element) ? $object->element : $object->element.
'@'.$object->module).
'\',
735 id: \
''.((int) $object->id).
'\',
736 token: \
''.currentToken().
'\'
739 $(
"#set_'.$htmlname.'_'.$object->id.'").hide();
740 $(
"#del_'.$htmlname.'_'.$object->id.'").show();
742 if (input.disabled && input.disabled.length > 0) {
743 $.each(input.disabled,
function(key,value) {
744 $(
"#" + value).removeAttr(
"disabled");
745 if ($(
"#" + value).hasClass(
"butActionRefused") == true) {
746 $(
"#" + value).removeClass(
"butActionRefused");
747 $(
"#" + value).addClass(
"butAction");
751 }
else if (input.showhide && input.showhide.length > 0) {
752 $.each(input.showhide,
function(key,value) {
753 $(
"#" + value).show();
760 $(
"#del_'.$htmlname.'_'.$object->id.'").click(
function() {
761 console.log(
"Click managed by ajax_object_onoff");
762 $.get(
"'.DOL_URL_ROOT.'/core/ajax/objectonoff.php", {
764 field: \''.dol_escape_js($field).
'\',
766 element: \''.
dol_escape_js((empty($object->module) || $object->module == $object->element) ? $object->element : $object->element.
'@'.$object->module).
'\',
767 id: \''.((int) $object->id).
'\',
771 $("#del_'.$htmlname.
'_'.$object->id.
'").hide();
772 $("#set_'.$htmlname.
'_'.$object->id.
'").show();
773 // Disable another element
774 if (input.disabled && input.disabled.length > 0) {
775 $.each(input.disabled, function(key,value) {
776 $("#" + value).prop("disabled", true);
777 if ($("#" + value).hasClass("butAction") == true) {
778 $("#" + value).removeClass("butAction");
779 $("#" + value).addClass("butActionRefused");
782 // Hide another element
783 } else if (input.showhide && input.showhide.length > 0) {
784 $.each(input.showhide, function(key,value) {
785 $("#" + value).hide();
794 $switchon =
'switch_on';
795 $switchoff =
'switch_off';
798 $tmparray = explode(
':', $text_on);
799 if (!empty($tmparray[1])) {
800 $text_on = $tmparray[0];
801 $switchon = $tmparray[1];
802 if (!empty($tmparray[2])) {
803 $cssswitchon = $tmparray[2];
806 $tmparray = explode(
':', $text_off);
807 if (!empty($tmparray[1])) {
808 $text_off = $tmparray[0];
809 $switchoff = $tmparray[1];
810 if (!empty($tmparray[2])) {
811 $cssswitchoff = $tmparray[2];
815 if (empty($conf->use_javascript_ajax) || $forcenojs) {
816 $out .=
'<a id="set_'.$htmlname.
'_'.$object->id.
'" class="linkobject '.($object->$code == 1 ?
'hideobject' :
'').($morecss ?
' '.$morecss :
'').
'" href="'.DOL_URL_ROOT.
'/core/ajax/objectonoff.php?action=set&token='.newToken().
'&id='.((int) $object->id).
'&element='.urlencode($object->element).
'&field='.urlencode($field).
'&value=1&backtopage='.urlencode($_SERVER[
"PHP_SELF"].
'?id='.$object->id).
'">'.
img_picto($langs->trans($text_off), $switchoff,
'', false, 0, 0,
'', $cssswitchoff).
'</a>';
817 $out .=
'<a id="del_'.$htmlname.
'_'.$object->id.
'" class="linkobject '.($object->$code == 1 ?
'' :
'hideobject').($morecss ?
' '.$morecss :
'').
'" href="'.DOL_URL_ROOT.
'/core/ajax/objectonoff.php?action=set&token='.newToken().
'&id='.((int) $object->id).
'&element='.urlencode($object->element).
'&field='.urlencode($field).
'&value=0&backtopage='.urlencode($_SERVER[
"PHP_SELF"].
'?id='.$object->id).
'">'.
img_picto($langs->trans($text_on), $switchon,
'', false, 0, 0,
'', $cssswitchon).
'</a>';
819 $out .=
'<span id="set_'.$htmlname.
'_'.$object->id.
'" class="linkobject '.($object->$code == 1 ?
'hideobject' :
'').($morecss ?
' '.$morecss :
'').
'">'.
img_picto($langs->trans($text_off), $switchoff,
'', false, 0, 0,
'', $cssswitchoff).
'</span>';
820 $out .=
'<span id="del_'.$htmlname.
'_'.$object->id.
'" class="linkobject '.($object->$code == 1 ?
'' :
'hideobject').($morecss ?
' '.$morecss :
'').
'">'.
img_picto($langs->trans($text_on), $switchon,
'', false, 0, 0,
'', $cssswitchon).
'</span>';
ajax_autocompleter($selected, $htmlname, $url, $urloption='', $minLength=2, $autoselect=0, $ajaxoptions=array(), $moreparams='')
Generic function that return javascript to add to a page to transform a common input field into an au...
ajax_combobox($htmlname, $events=array(), $minLengthToAutocomplete=0, $forcefocus=0, $widthTypeOfAutocomplete='resolve', $idforemptyvalue='-1', $morecss='')
Convert a html select field into an ajax combobox.
ajax_multiautocompleter($htmlname, $fields, $url, $option='', $minLength=2, $autoselect=0)
Generic function that return javascript to add to a page to transform a common input field into an au...
dol_string_nohtmltag($stringtoclean, $removelinefeed=1, $pagecodeto='UTF-8', $strip_tags=0, $removedoublespaces=1)
Clean a string from all HTML tags and entities.
img_picto($titlealt, $picto, $moreatt='', $pictoisfullpath=false, $srconly=0, $notitle=0, $alt='', $morecss='', $marginleftonlyshort=2)
Show picto whatever it's its name (generic function)