dolibarr 21.0.4
ajax.lib.php
Go to the documentation of this file.
1<?php
2/* Copyright (C) 2007-2010 Laurent Destailleur <eldy@users.sourceforge.net>
3 * Copyright (C) 2007-2015 Regis Houssin <regis.houssin@inodbox.com>
4 * Copyright (C) 2012 Christophe Battarel <christophe.battarel@altairis.fr>
5 * Copyright (C) 2024 MDW <mdeweerd@users.noreply.github.com>
6 * Copyright (C) 2024 Frédéric France <frederic.france@free.fr>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 3 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see <https://www.gnu.org/licenses/>.
20 * or see https://www.gnu.org/
21 */
22
49function ajax_autocompleter($selected, $htmlname, $url, $urloption = '', $minLength = 2, $autoselect = 0, $ajaxoptions = array(), $moreparams = '')
50{
51 if (empty($minLength)) {
52 $minLength = 1;
53 }
54
55 $dataforrenderITem = 'ui-autocomplete';
56 $dataforitem = 'ui-autocomplete-item';
57 // Allow two constant to use other values for backward compatibility
58 if (defined('JS_QUERY_AUTOCOMPLETE_RENDERITEM')) {
59 $dataforrenderITem = constant('JS_QUERY_AUTOCOMPLETE_RENDERITEM');
60 }
61 if (defined('JS_QUERY_AUTOCOMPLETE_ITEM')) {
62 $dataforitem = constant('JS_QUERY_AUTOCOMPLETE_ITEM');
63 }
64
65 $htmlnamejquery = str_replace('.', '\\\\.', $htmlname);
66
67 // Input search_htmlname is original field
68 // Input htmlname is a second input field used when using ajax autocomplete.
69 $script = '<input type="hidden" name="'.$htmlname.'" id="'.$htmlname.'" value="'.$selected.'" '.($moreparams ? $moreparams : '').' />';
70
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 */
76
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 losing 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 */
80 {
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("");
84 }
85 });
86
87 // Check options for secondary actions when keyup
88 $("input#search_'.$htmlnamejquery.'").keyup(function() {
89 if ($(this).val().length == 0)
90 {
91 $("#search_'.$htmlnamejquery.'").val("");
92 $("#'.$htmlnamejquery.'").val("").trigger("change");
93 if (options.option_disabled) {
94 $("#" + options.option_disabled).removeAttr("disabled");
95 }
96 if (options.disabled) {
97 $.each(options.disabled, function(key, value) {
98 $("#" + value).removeAttr("disabled");
99 });
100 }
101 if (options.update) {
102 $.each(options.update, function(key, value) {
103 $("#" + key).val("").trigger("change");
104 });
105 }
106 if (options.show) {
107 $.each(options.show, function(key, value) {
108 $("#" + value).hide().trigger("hide");
109 });
110 }
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("");
115 } else {
116 $("#" + key).html("");
117 }
118 });
119 }
120 }
121 });
122
123 // Activate the autocomplete to execute the GET
124 $("input#search_'.$htmlnamejquery.'").autocomplete({
125 source: function( request, response ) {
126 $.get("'.$url.($urloption ? '?'.$urloption : '').'", { "'.str_replace('.', '_', $htmlname).'": request.term }, function(data){
127 if (data != null)
128 {
129 response($.map( data, function(item) {
130 console.log("Received answer from ajax GET, we populate array to return to the jquery autocomplete");
131 if (autoselect == 1 && data.length == 1) {
132 $("#search_'.$htmlnamejquery.'").val(item.value);
133 $("#'.$htmlnamejquery.'").val(item.key).trigger("change");
134 }
135 var label = "";
136 if (item.labelhtml != null) {
137 label = item.labelhtml.toString();
138 } else if (item.label != null) {
139 label = item.label.toString();
140 }
141 var update = {};
142 if (options.update) {
143 $.each(options.update, function(key, value) {
144 update[key] = item[value];
145 });
146 }
147 var textarea = {};
148 if (options.update_textarea) {
149 $.each(options.update_textarea, function(key, value) {
150 textarea[key] = item[value];
151 });
152 }
153
154 return { label: label,
155 value: item.value,
156 id: item.key,
157 disabled: item.disabled,
158 update: update,
159 textarea: textarea,
160 pbq: item.pbq,
161 type: item.type,
162 qty: item.qty,
163 discount: item.discount,
164 pricebasetype: item.pricebasetype,
165 price_ht: item.price_ht,
166 price_ttc: item.price_ttc,
167 price_unit_ht: item.price_unit_ht,
168 price_unit_ht_locale: item.price_unit_ht_locale,
169 multicurrency_code: item.multicurrency_code,
170 multicurrency_unitprice: item.multicurrency_unitprice,
171 description : item.description,
172 ref_customer: item.ref_customer,
173 tva_tx: item.tva_tx,
174 default_vat_code: item.default_vat_code,
175 supplier_ref: item.supplier_ref
176 }
177 }));
178 } else {
179 console.error("Error: Ajax url '.$url.($urloption ? '?'.$urloption : '').' has returned an empty page. Should be an empty json array.");
180 }
181 }, "json");
182 },
183 dataType: "json",
184 minLength: '.((int) $minLength).',
185 select: function( event, ui ) { // Function ran once a new value has been selected into the javascript combo
186 console.log("We will trigger change on input '.$htmlname.' because of the select definition of autocomplete code for input#search_'.$htmlname.'");
187 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");
188
189 console.log("Before, we propagate some properties, retrieved by the ajax of the get, into the data-xxx properties of the component #'.$htmlnamejquery.'");
190 //console.log(ui.item);
191
192 // For supplier price and customer when price by quantity is off
193 $("#'.$htmlnamejquery.'").attr("data-up", ui.item.price_ht);
194 $("#'.$htmlnamejquery.'").attr("data-up-locale", ui.item.price_unit_ht_locale);
195 $("#'.$htmlnamejquery.'").attr("data-base", ui.item.pricebasetype);
196 $("#'.$htmlnamejquery.'").attr("data-qty", ui.item.qty);
197 $("#'.$htmlnamejquery.'").attr("data-discount", ui.item.discount);
198 $("#'.$htmlnamejquery.'").attr("data-description", ui.item.description);
199 $("#'.$htmlnamejquery.'").attr("data-ref-customer", ui.item.ref_customer);
200 $("#'.$htmlnamejquery.'").attr("data-tvatx", ui.item.tva_tx);
201 $("#'.$htmlnamejquery.'").attr("data-default-vat-code", ui.item.default_vat_code);
202 $("#'.$htmlnamejquery.'").attr("data-supplier-ref", ui.item.supplier_ref); // supplier_ref of price
203
204 // For multi-currency values
205 $("#'.$htmlnamejquery.'").attr("data-multicurrency-code", ui.item.multicurrency_code);
206 $("#'.$htmlnamejquery.'").attr("data-multicurrency-unitprice", ui.item.multicurrency_unitprice);
207 ';
208 if (getDolGlobalString('PRODUIT_CUSTOMER_PRICES_BY_QTY') || getDolGlobalString('PRODUIT_CUSTOMER_PRICES_BY_QTY_MULTIPRICES')) {
209 $script .= '
210 // For customer price when PRODUIT_CUSTOMER_PRICES_BY_QTY is on
211 console.log("PRODUIT_CUSTOMER_PRICES_BY_QTY is on, so we propagate also prices by quantity into data-pbqxxx properties");
212 $("#'.$htmlnamejquery.'").attr("data-pbq", ui.item.pbq);
213 $("#'.$htmlnamejquery.'").attr("data-pbqup", ui.item.price_ht);
214 $("#'.$htmlnamejquery.'").attr("data-pbqbase", ui.item.pricebasetype);
215 $("#'.$htmlnamejquery.'").attr("data-pbqqty", ui.item.qty);
216 $("#'.$htmlnamejquery.'").attr("data-pbqpercent", ui.item.discount);
217 ';
218 }
219 $script .= '
220 // A new value has been selected, we trigger the handlers on #htmlnamejquery
221 console.log("Now, we trigger changes on #'.$htmlnamejquery.'");
222 $("#'.$htmlnamejquery.'").val(ui.item.id).trigger("change"); // Select new value
223
224 // Complementary actions
225
226 // Disable an element
227 if (options.option_disabled) {
228 console.log("Make action option_disabled on #"+options.option_disabled+" with disabled="+ui.item.disabled)
229 if (ui.item.disabled) {
230 $("#" + options.option_disabled).prop("disabled", true);
231 if (options.error) {
232 $.jnotify(options.error, "error", true); // Output with jnotify the error message
233 }
234 if (options.warning) {
235 $.jnotify(options.warning, "warning", false); // Output with jnotify the warning message
236 }
237 } else {
238 $("#" + options.option_disabled).removeAttr("disabled");
239 }
240 }
241
242 if (options.disabled) {
243 console.log("Make action \'disabled\' on each "+options.option_disabled)
244 $.each(options.disabled, function(key, value) {
245 $("#" + value).prop("disabled", true);
246 });
247 }
248 if (options.show) {
249 console.log("Make action \'show\' on each "+options.show)
250 $.each(options.show, function(key, value) {
251 $("#" + value).show().trigger("show");
252 });
253 }
254
255 // Update an input
256 if (ui.item.update) {
257 console.log("Make action \'update\' on each ui.item.update (if there is)")
258 // loop on each "update" fields
259 $.each(ui.item.update, function(key, value) {
260 console.log("Set value "+value+" into #"+key);
261 $("#" + key).val(value).trigger("change");
262 });
263 }
264 if (ui.item.textarea) {
265 console.log("Make action \'textarea\' on each ui.item.textarea (if there is)")
266 $.each(ui.item.textarea, function(key, value) {
267 if (typeof CKEDITOR == "object" && typeof CKEDITOR.instances != "undefined" && CKEDITOR.instances[key] != "undefined") {
268 CKEDITOR.instances[key].setData(value);
269 CKEDITOR.instances[key].focus();
270 } else {
271 $("#" + key).html(value);
272 $("#" + key).focus();
273 }
274 });
275 }
276 console.log("ajax_autocompleter new value selected, we trigger change also on original component so on field #search_'.$htmlname.'");
277
278 $("#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.
279 }
280 ,delay: 500
281 });
282 const widgetData = $("input#search_'.$htmlnamejquery.'").data("'.$dataforrenderITem.'");
283 if (widgetData) {
284 widgetData._renderItem = function( ul, item ) {
285 return $("<li>")
286 .data( "'.$dataforitem.'", item ) // jQuery UI > 1.10.0
287 .append( \'<a><span class="tag">\' + item.label + "</span></a>" )
288 .appendTo(ul);
289 };
290 }
291
292 });';
293 $script .= '</script>';
294
295 return $script;
296}
297
312function ajax_multiautocompleter($htmlname, $fields, $url, $option = '', $minLength = 2, $autoselect = 0)
313{
314 $script = '<!-- Autocomplete -->'."\n";
315 $script .= '<script>';
316 $script .= 'jQuery(document).ready(function() {
317 var fields = '.json_encode($fields).';
318 var nboffields = fields.length;
319 var autoselect = '.$autoselect.';
320 //alert(fields + " " + nboffields);
321
322 // Activate the autocomplete to execute the GET
323 jQuery("input#'.$htmlname.'").autocomplete({
324 dataType: "json",
325 minLength: '.$minLength.',
326 source: function( request, response ) {
327 jQuery.getJSON( "'.$url.($option ? '?'.$option : '').'", { '.$htmlname.': request.term }, function(data){
328 response( jQuery.map( data, function( item ) {
329 if (autoselect == 1 && data.length == 1) {
330 jQuery("#'.$htmlname.'").val(item.value);
331 // TODO move this to specific request
332 if (item.states) {
333 jQuery("#state_id").html(item.states);
334 }
335 for (i=0;i<nboffields;i++) {
336 if (item[fields[i]]) { // If defined
337 //alert(item[fields[i]]);
338 jQuery("#" + fields[i]).val(item[fields[i]]);
339 }
340 }
341 }
342 return item
343 }));
344 });
345 },
346 select: function( event, ui ) {
347 needtotrigger = "";
348 for (i=0;i<nboffields;i++) {
349 //alert(fields[i] + " = " + ui.item[fields[i]]);
350 if (fields[i]=="selectcountry_id")
351 {
352 if (ui.item[fields[i]] > 0) // Do not erase country if unknown
353 {
354 oldvalue=jQuery("#" + fields[i]).val();
355 newvalue=ui.item[fields[i]];
356 //alert(oldvalue+" "+newvalue);
357 jQuery("#" + fields[i]).val(ui.item[fields[i]]);
358 if (oldvalue != newvalue) // To force select2 to refresh visible content
359 {
360 needtotrigger="#" + fields[i];
361 }
362
363 // If we set new country and new state, we need to set a new list of state to allow change
364 if (ui.item.states && ui.item["state_id"] != jQuery("#state_id").value) {
365 jQuery("#state_id").html(ui.item.states);
366 }
367 }
368 }
369 else if (fields[i]=="state_id" || fields[i]=="state_id")
370 {
371 if (ui.item[fields[i]] > 0) // Do not erase state if unknown
372 {
373 oldvalue=jQuery("#" + fields[i]).val();
374 newvalue=ui.item[fields[i]];
375 //alert(oldvalue+" "+newvalue);
376 jQuery("#" + fields[i]).val(ui.item[fields[i]]); // This may fails if not correct country
377 if (oldvalue != newvalue) // To force select2 to refresh visible content
378 {
379 needtotrigger="#" + fields[i];
380 }
381 }
382 }
383 else if (ui.item[fields[i]]) { // If defined
384 oldvalue=jQuery("#" + fields[i]).val();
385 newvalue=ui.item[fields[i]];
386 //alert(oldvalue+" "+newvalue);
387 jQuery("#" + fields[i]).val(ui.item[fields[i]]);
388 if (oldvalue != newvalue) // To force select2 to refresh visible content
389 {
390 needtotrigger="#" + fields[i];
391 }
392 }
393
394 if (needtotrigger != "") // To force select2 to refresh visible content
395 {
396 // We introduce a delay so hand is back to js and all other js change can be done before the trigger that may execute a submit is done
397 // This is required for example when changing zip with autocomplete that change the country
398 jQuery(needtotrigger).delay(500).queue(function() {
399 jQuery(this).trigger("change");
400 });
401 }
402 }
403 }
404 });
405 });';
406 $script .= '</script>';
407
408 return $script;
409}
410
420function ajax_dialog($title, $message, $w = 350, $h = 150)
421{
422 $newtitle = dol_textishtml($title) ? dol_string_nohtmltag($title, 1) : $title;
423 $msg = '<div id="dialog-info" title="'.dol_escape_htmltag($newtitle).'">';
424 $msg .= $message;
425 $msg .= '</div>'."\n";
426 $msg .= '<script>
427 jQuery(function() {
428 jQuery("#dialog-info").dialog({
429 resizable: false,
430 height:'.$h.',
431 width:'.$w.',
432 modal: true,
433 buttons: {
434 Ok: function() {
435 jQuery(this).dialog(\'close\');
436 }
437 }
438 });
439 });
440 </script>';
441
442 $msg .= "\n";
443
444 return $msg;
445}
446
447
463function ajax_combobox($htmlname, $events = array(), $minLengthToAutocomplete = 0, $forcefocus = 0, $widthTypeOfAutocomplete = 'resolve', $idforemptyvalue = '-1', $morecss = '')
464{
465 global $conf;
466
467 // select2 can be disabled for smartphones
468 if (!empty($conf->browser->layout) && $conf->browser->layout == 'phone' && getDolGlobalString('MAIN_DISALLOW_SELECT2_WITH_SMARTPHONE')) {
469 return '';
470 }
471
472 if (getDolGlobalString('MAIN_DISABLE_AJAX_COMBOX')) {
473 return '';
474 }
475 if (empty($conf->use_javascript_ajax)) {
476 return '';
477 }
478 if (!getDolGlobalString('MAIN_USE_JQUERY_MULTISELECT') && !defined('REQUIRE_JQUERY_MULTISELECT')) {
479 return '';
480 }
481 if (getDolGlobalString('MAIN_OPTIMIZEFORTEXTBROWSER')) {
482 return '';
483 }
484
485 if (empty($minLengthToAutocomplete)) {
486 $minLengthToAutocomplete = 0;
487 }
488
489 $moreselect2theme = ($morecss ? dol_escape_js(' '.$morecss) : '');
490 $moreselect2theme = preg_replace('/widthcentpercentminus[^\s]*/', '', $moreselect2theme);
491
492 $tmpplugin = 'select2';
493 $msg = "\n".'<!-- JS CODE TO ENABLE '.$tmpplugin.' for id = '.$htmlname.' -->
494 <script>
495 $(document).ready(function () {
496 $(\''.(dol_escape_js(preg_match('/^\./', $htmlname) ? $htmlname : '#'.$htmlname)).'\').'.$tmpplugin.'({
497 dir: \'ltr\',';
498 if (preg_match('/onrightofpage/', $morecss)) { // when $morecss contains 'onrightofpage', the select2 component must also be inside a parent with class="parentonrightofpage"
499 $msg .= ' dropdownAutoWidth: true, dropdownParent: $(\'#'.$htmlname.'\').parent(), '."\n";
500 }
501 $msg .= ' width: \''.dol_escape_js($widthTypeOfAutocomplete).'\', /* off or resolve */
502 minimumInputLength: '.((int) $minLengthToAutocomplete).',
503 language: (typeof select2arrayoflanguage === \'undefined\') ? \'en\' : select2arrayoflanguage,
504 matcher: function (params, data) {
505 if ($.trim(params.term) === "") {
506 return data;
507 }
508 keywords = (params.term).split(" ");
509 for (var i = 0; i < keywords.length; i++) {
510 if (((data.text).toUpperCase()).indexOf((keywords[i]).toUpperCase()) == -1) {
511 return null;
512 }
513 }
514 return data;
515 },
516 theme: \'default'.dol_escape_js($moreselect2theme).'\', /* to add css on generated html components */
517 containerCssClass: \':all:\', /* Line to add class of origin SELECT propagated to the new <span class="select2-selection...> tag */
518 selectionCssClass: \':all:\', /* Line to add class of origin SELECT propagated to the new <span class="select2-selection...> tag */
519 dropdownCssClass: \'ui-dialog\',
520 templateResult: function (data, container) { /* Format visible output into combo list */
521 /* Code to add class of origin OPTION propagated to the new select2 <li> tag */
522 if (data.element) { $(container).addClass($(data.element).attr("class")); }
523 //console.log("data html is "+$(data.element).attr("data-html"));
524 if (data.id == '.((int) $idforemptyvalue).' && $(data.element).attr("data-html") == undefined) {
525 return \'&nbsp;\';
526 }
527 if ($(data.element).attr("data-html") != undefined) {
528 /* If property html set, we decode html entities and use this. */
529 /* Note that HTML content must have been sanitized from js with dol_escape_htmltag(xxx, 0, 0, \'\', 0, 1) when building the select option. */
530 if (typeof htmlEntityDecodeJs === "function") {
531 return htmlEntityDecodeJs($(data.element).attr("data-html"));
532 }
533 }
534 return data.text;
535 },
536 templateSelection: function (selection) { /* Format visible output of selected value */
537 if (selection.id == '.((int) $idforemptyvalue).') return \'<span class="placeholder">\'+selection.text+\'</span>\';
538 return selection.text;
539 },
540 escapeMarkup: function(markup) {
541 return markup;
542 }
543 })';
544 if ($forcefocus) {
545 $msg .= '.select2(\'focus\')';
546 }
547 $msg .= ';'."\n";
548
549 $msg .= '});'."\n";
550 $msg .= "</script>\n";
551
552 $msg .= ajax_event($htmlname, $events);
553
554 return $msg;
555}
556
557
566function ajax_event($htmlname, $events)
567{
568 $out = '';
569
570 if (is_array($events) && count($events)) { // If an array of js events to do were provided.
571 $out = '<!-- JS code to manage event for id = ' . $htmlname . ' -->
572 <script>
573 $(document).ready(function () {
574 jQuery("#'.$htmlname.'").change(function () {
575 var obj = '.json_encode($events) . ';
576 $.each(obj, function(key,values) {
577 if (values.method.length) {
578 runJsCodeForEvent'.$htmlname.'(values);
579 }
580 });
581 });
582 function runJsCodeForEvent'.$htmlname.'(obj) {
583 var id = $("#'.$htmlname.'").val();
584 var method = obj.method;
585 var url = obj.url;
586 var htmlname = obj.htmlname;
587 var showempty = obj.showempty;
588 console.log("Run runJsCodeForEvent-'.$htmlname.' from ajax_combobox id="+id+" method="+method+" showempty="+showempty+" url="+url+" htmlname="+htmlname);
589 $.getJSON(url,
590 {
591 action: method,
592 id: id,
593 htmlname: htmlname,
594 showempty: showempty
595 },
596 function(response) {
597 $.each(obj.params, function(key,action) {
598 if (key.length) {
599 var num = response.num;
600 if (num > 0) {
601 $("#" + key).removeAttr(action);
602 } else {
603 $("#" + key).attr(action, action);
604 }
605 }
606 });
607
608 console.log("Replace HTML content of select#"+htmlname);
609 $("select#" + htmlname).html(response.value);
610 if (response.num) {
611 var selecthtml_str = response.value; /* response.value is the HTML string with list of options */
612 var selecthtml_dom=$.parseHTML(selecthtml_str);
613 if (typeof(selecthtml_dom[0][0]) !== \'undefined\') {
614 $("#inputautocomplete"+htmlname).val(selecthtml_dom[0][0].innerHTML);
615 }
616 } else {
617 $("#inputautocomplete"+htmlname).val("");
618 }
619 $("select#" + htmlname).change(); /* Trigger event change */
620 }
621 );
622 }
623 });
624 </script>';
625 }
626
627 return $out;
628}
629
630
651function ajax_constantonoff($code, $input = array(), $entity = null, $revertonoff = 0, $strict = 0, $forcereload = 0, $marginleftonlyshort = 2, $forcenoajax = 0, $setzeroinsteadofdel = 0, $suffix = '', $mode = '', $morecss = 'inline-block', $userconst = 0, $showwarning = '')
652{
653 global $conf, $langs, $user, $db;
654
655 $entity = ((isset($entity) && is_numeric($entity) && $entity >= 0) ? $entity : $conf->entity);
656 if (!isset($input)) {
657 $input = array();
658 }
659
660 if (empty($conf->use_javascript_ajax) || $forcenoajax) {
661 if (!getDolGlobalString($code)) {
662 $out = '<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>';
663 } else {
664 $out = '<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>';
665 }
666 } else {
667 $userconstid = 0;
668 if (is_object($userconst)) {
669 $userconstid = $userconst->id;
670 } elseif (is_numeric($userconst) && $userconst > 0) {
671 $userconstid = $userconst;
672 $userconst = new User($db);
673 $userconst->fetch($userconstid);
674 }
675
676 $out = "\n<!-- Ajax code to switch constant ".$code." -->".'
677 <script>
678 $(document).ready(function() {
679 var input = '.json_encode($input).';
680 var url = \''.DOL_URL_ROOT.'/core/ajax/constantonoff.php\';
681 var code = \''.dol_escape_js($code).'\';
682 var entity = \''.dol_escape_js($entity).'\';
683 var strict = \''.dol_escape_js((string) $strict).'\';
684 var userid = \''.dol_escape_js((string) $user->id).'\';
685 var userconst = '.((int) $userconstid).';
686 var yesButton = \''.dol_escape_js($langs->transnoentities("Yes")).'\';
687 var noButton = \''.dol_escape_js($langs->transnoentities("No")).'\';
688 var token = \''.currentToken().'\';
689 var warning = \''.dol_escape_js($showwarning).'\';
690
691 // Set constant
692 $("#set_" + code).click(function() {
693 if (warning) {
694 alert(warning);
695 }
696
697 if (input.alert && input.alert.set) {
698 if (input.alert.set.yesButton) yesButton = input.alert.set.yesButton;
699 if (input.alert.set.noButton) noButton = input.alert.set.noButton;
700 confirmConstantAction("set", url, code, input, input.alert.set, entity, yesButton, noButton, strict, userid, token);
701 } else {
702 setConstant(url, code, input, entity, 0, '.((int) $forcereload).', userid, token, 1, userconst);
703 }
704 });
705
706 // Del constant
707 $("#del_" + code).click(function() {
708 if (input.alert && input.alert.del) {
709 if (input.alert.del.yesButton) yesButton = input.alert.del.yesButton;
710 if (input.alert.del.noButton) noButton = input.alert.del.noButton;
711 confirmConstantAction("del", url, code, input, input.alert.del, entity, yesButton, noButton, strict, userid, token);
712 } else {';
713 if (empty($setzeroinsteadofdel)) {
714 $out .= ' delConstant(url, code, input, entity, 0, '.((int) $forcereload).', userid, token, userconst);';
715 } else {
716 $out .= ' setConstant(url, code, input, entity, 0, '.((int) $forcereload).', userid, token, 0, userconst);';
717 }
718 $out .= ' }
719 });
720 });
721 </script>'."\n";
722
723 if (!empty($userconst) && $userconst instanceof User) {
724 $value = getDolUserString($code, '', $userconst);
725 } else {
726 $value = getDolGlobalString($code);
727 }
728 $out .= '<div id="confirm_'.$code.'" title="" style="display: none;"></div>';
729 $out .= '<span id="set_'.$code.'" class="valignmiddle inline-block linkobject '.($value ? 'hideobject' : '').($morecss ? ' '.$morecss : '').'">'.($revertonoff ? img_picto($langs->trans("Enabled"), 'switch_on', '', 0, 0, 0, '', '', $marginleftonlyshort) : img_picto($langs->trans("Disabled"), 'switch_off', '', 0, 0, 0, '', '', $marginleftonlyshort)).'</span>';
730 $out .= '<span id="del_'.$code.'" class="valignmiddle inline-block linkobject '.($value ? '' : 'hideobject').($morecss ? ' '.$morecss : '').'">'.($revertonoff ? img_picto($langs->trans("Disabled"), 'switch_off'.$suffix, '', 0, 0, 0, '', '', $marginleftonlyshort) : img_picto($langs->trans("Enabled"), 'switch_on'.$suffix, '', 0, 0, 0, '', '', $marginleftonlyshort)).'</span>';
731 $out .= "\n";
732 }
733
734 return $out;
735}
736
754function ajax_object_onoff($object, $code, $field, $text_on, $text_off, $input = array(), $morecss = '', $htmlname = '', $forcenojs = 0, $moreparam = '')
755{
756 global $conf, $langs;
757
758 if (empty($htmlname)) {
759 $htmlname = $code;
760 }
761
762 $out = '';
763
764 if (!empty($conf->use_javascript_ajax) && empty($forcenojs)) {
765 $out .= '<script>
766 $(function() {
767 var input = '.json_encode($input).';
768
769 // Set constant
770 $("#set_'.$htmlname.'_'.$object->id.'").click(function() {
771 console.log("Click managed by ajax_object_onoff");
772 $.get( "'.DOL_URL_ROOT.'/core/ajax/objectonoff.php", {
773 action: \'set\',
774 field: \''.dol_escape_js($field).'\',
775 value: \'1\',
776 element: \''.dol_escape_js((empty($object->module) || $object->module == $object->element) ? $object->element : $object->element.'@'.$object->module).'\',
777 id: \''.((int) $object->id).'\',
778 token: \''.currentToken().'\'
779 },
780 function() {
781 $("#set_'.$htmlname.'_'.$object->id.'").hide();
782 $("#del_'.$htmlname.'_'.$object->id.'").show();
783 // Enable another element
784 if (input.disabled && input.disabled.length > 0) {
785 $.each(input.disabled, function(key,value) {
786 $("#" + value).removeAttr("disabled");
787 if ($("#" + value).hasClass("butActionRefused") == true) {
788 $("#" + value).removeClass("butActionRefused");
789 $("#" + value).addClass("butAction");
790 }
791 });
792 // Show another element
793 } else if (input.showhide && input.showhide.length > 0) {
794 $.each(input.showhide, function(key,value) {
795 $("#" + value).show();
796 });
797 }
798 });
799 });
800
801 // Del constant
802 $("#del_'.$htmlname.'_'.$object->id.'").click(function() {
803 console.log("Click managed by ajax_object_onoff");
804 $.get( "'.DOL_URL_ROOT.'/core/ajax/objectonoff.php", {
805 action: \'set\',
806 field: \''.dol_escape_js($field).'\',
807 value: \'0\',
808 element: \''.dol_escape_js((empty($object->module) || $object->module == $object->element) ? $object->element : $object->element.'@'.$object->module).'\',
809 id: \''.((int) $object->id).'\',
810 token: \''.currentToken().'\'
811 },
812 function() {
813 $("#del_'.$htmlname.'_'.$object->id.'").hide();
814 $("#set_'.$htmlname.'_'.$object->id.'").show();
815 // Disable another element
816 if (input.disabled && input.disabled.length > 0) {
817 $.each(input.disabled, function(key,value) {
818 $("#" + value).prop("disabled", true);
819 if ($("#" + value).hasClass("butAction") == true) {
820 $("#" + value).removeClass("butAction");
821 $("#" + value).addClass("butActionRefused");
822 }
823 });
824 // Hide another element
825 } else if (input.showhide && input.showhide.length > 0) {
826 $.each(input.showhide, function(key,value) {
827 $("#" + value).hide();
828 });
829 }
830 });
831 });
832 });
833 </script>';
834 }
835
836 $switchon = 'switch_on';
837 $switchoff = 'switch_off';
838 $cssswitchon = '';
839 $cssswitchoff = '';
840 $tmparray = explode(':', $text_on);
841 if (!empty($tmparray[1])) {
842 $text_on = $tmparray[0];
843 $switchon = $tmparray[1];
844 if (!empty($tmparray[2])) {
845 $cssswitchon = $tmparray[2];
846 }
847 }
848 $tmparray = explode(':', $text_off);
849 if (!empty($tmparray[1])) {
850 $text_off = $tmparray[0];
851 $switchoff = $tmparray[1];
852 if (!empty($tmparray[2])) {
853 $cssswitchoff = $tmparray[2];
854 }
855 }
856
857 if (empty($conf->use_javascript_ajax) || $forcenojs) {
858 $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.($moreparam ? '&'.$moreparam : '')).'">'.img_picto($langs->trans($text_off), $switchoff, '', 0, 0, 0, '', $cssswitchoff).'</a>';
859 $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.($moreparam ? '&'.$moreparam : '')).'">'.img_picto($langs->trans($text_on), $switchon, '', 0, 0, 0, '', $cssswitchon).'</a>';
860 } else {
861 $out .= '<span id="set_'.$htmlname.'_'.$object->id.'" class="linkobject '.($object->$code == 1 ? 'hideobject' : '').($morecss ? ' '.$morecss : '').'">'.img_picto($langs->trans($text_off), $switchoff, '', 0, 0, 0, '', $cssswitchoff).'</span>';
862 $out .= '<span id="del_'.$htmlname.'_'.$object->id.'" class="linkobject '.($object->$code == 1 ? '' : 'hideobject').($morecss ? ' '.$morecss : '').'">'.img_picto($langs->trans($text_on), $switchon, '', 0, 0, 0, '', $cssswitchon).'</span>';
863 }
864
865 return $out;
866}
if( $user->socid > 0) if(! $user->hasRight('accounting', 'chartofaccount')) $object
Definition card.php:66
ajax_autocompleter($selected, $htmlname, $url, $urloption='', $minLength=2, $autoselect=0, $ajaxoptions=array(), $moreparams='')
Generic function that return javascript to add to transform a common input text or select field into ...
Definition ajax.lib.php:49
ajax_combobox($htmlname, $events=array(), $minLengthToAutocomplete=0, $forcefocus=0, $widthTypeOfAutocomplete='resolve', $idforemptyvalue='-1', $morecss='')
Convert a html select field into an ajax combobox.
Definition ajax.lib.php:463
ajax_dialog($title, $message, $w=350, $h=150)
Show an ajax dialog.
Definition ajax.lib.php:420
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 text field into ...
Definition ajax.lib.php:312
ajax_event($htmlname, $events)
Add event management script.
Definition ajax.lib.php:566
Class to manage Dolibarr users.
img_picto($titlealt, $picto, $moreatt='', $pictoisfullpath=0, $srconly=0, $notitle=0, $alt='', $morecss='', $marginleftonlyshort=2, $allowothertags=array())
Show picto whatever it's its name (generic function)
dol_string_nohtmltag($stringtoclean, $removelinefeed=1, $pagecodeto='UTF-8', $strip_tags=0, $removedoublespaces=1)
Clean a string from all HTML tags and entities.
currentToken()
Return the value of token currently saved into session with name 'token'.
dol_escape_js($stringtoescape, $mode=0, $noescapebackslashn=0)
Returns text escaped for inclusion into javascript code.
newToken()
Return the value of token currently saved into session with name 'newtoken'.
dol_textishtml($msg, $option=0)
Return if a text is a html content.
getDolGlobalString($key, $default='')
Return a Dolibarr global constant string value.
global $conf
The following vars must be defined: $type2label $form $conf, $lang, The following vars may also be de...
Definition member.php:79