dolibarr 21.0.0-beta
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 }).data("'.$dataforrenderITem.'")._renderItem = function( ul, item ) {
282 return $("<li>")
283 .data( "'.$dataforitem.'", item ) // jQuery UI > 1.10.0
284 .append( \'<a><span class="tag">\' + item.label + "</span></a>" )
285 .appendTo(ul);
286 };
287
288 });';
289 $script .= '</script>';
290
291 return $script;
292}
293
308function ajax_multiautocompleter($htmlname, $fields, $url, $option = '', $minLength = 2, $autoselect = 0)
309{
310 $script = '<!-- Autocomplete -->'."\n";
311 $script .= '<script>';
312 $script .= 'jQuery(document).ready(function() {
313 var fields = '.json_encode($fields).';
314 var nboffields = fields.length;
315 var autoselect = '.$autoselect.';
316 //alert(fields + " " + nboffields);
317
318 // Activate the autocomplete to execute the GET
319 jQuery("input#'.$htmlname.'").autocomplete({
320 dataType: "json",
321 minLength: '.$minLength.',
322 source: function( request, response ) {
323 jQuery.getJSON( "'.$url.($option ? '?'.$option : '').'", { '.$htmlname.': request.term }, function(data){
324 response( jQuery.map( data, function( item ) {
325 if (autoselect == 1 && data.length == 1) {
326 jQuery("#'.$htmlname.'").val(item.value);
327 // TODO move this to specific request
328 if (item.states) {
329 jQuery("#state_id").html(item.states);
330 }
331 for (i=0;i<nboffields;i++) {
332 if (item[fields[i]]) { // If defined
333 //alert(item[fields[i]]);
334 jQuery("#" + fields[i]).val(item[fields[i]]);
335 }
336 }
337 }
338 return item
339 }));
340 });
341 },
342 select: function( event, ui ) {
343 needtotrigger = "";
344 for (i=0;i<nboffields;i++) {
345 //alert(fields[i] + " = " + ui.item[fields[i]]);
346 if (fields[i]=="selectcountry_id")
347 {
348 if (ui.item[fields[i]] > 0) // Do not erase country if unknown
349 {
350 oldvalue=jQuery("#" + fields[i]).val();
351 newvalue=ui.item[fields[i]];
352 //alert(oldvalue+" "+newvalue);
353 jQuery("#" + fields[i]).val(ui.item[fields[i]]);
354 if (oldvalue != newvalue) // To force select2 to refresh visible content
355 {
356 needtotrigger="#" + fields[i];
357 }
358
359 // If we set new country and new state, we need to set a new list of state to allow change
360 if (ui.item.states && ui.item["state_id"] != jQuery("#state_id").value) {
361 jQuery("#state_id").html(ui.item.states);
362 }
363 }
364 }
365 else if (fields[i]=="state_id" || fields[i]=="state_id")
366 {
367 if (ui.item[fields[i]] > 0) // Do not erase state if unknown
368 {
369 oldvalue=jQuery("#" + fields[i]).val();
370 newvalue=ui.item[fields[i]];
371 //alert(oldvalue+" "+newvalue);
372 jQuery("#" + fields[i]).val(ui.item[fields[i]]); // This may fails if not correct country
373 if (oldvalue != newvalue) // To force select2 to refresh visible content
374 {
375 needtotrigger="#" + fields[i];
376 }
377 }
378 }
379 else if (ui.item[fields[i]]) { // If defined
380 oldvalue=jQuery("#" + fields[i]).val();
381 newvalue=ui.item[fields[i]];
382 //alert(oldvalue+" "+newvalue);
383 jQuery("#" + fields[i]).val(ui.item[fields[i]]);
384 if (oldvalue != newvalue) // To force select2 to refresh visible content
385 {
386 needtotrigger="#" + fields[i];
387 }
388 }
389
390 if (needtotrigger != "") // To force select2 to refresh visible content
391 {
392 // 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
393 // This is required for example when changing zip with autocomplete that change the country
394 jQuery(needtotrigger).delay(500).queue(function() {
395 jQuery(this).trigger("change");
396 });
397 }
398 }
399 }
400 });
401 });';
402 $script .= '</script>';
403
404 return $script;
405}
406
416function ajax_dialog($title, $message, $w = 350, $h = 150)
417{
418 $newtitle = dol_textishtml($title) ? dol_string_nohtmltag($title, 1) : $title;
419 $msg = '<div id="dialog-info" title="'.dol_escape_htmltag($newtitle).'">';
420 $msg .= $message;
421 $msg .= '</div>'."\n";
422 $msg .= '<script>
423 jQuery(function() {
424 jQuery("#dialog-info").dialog({
425 resizable: false,
426 height:'.$h.',
427 width:'.$w.',
428 modal: true,
429 buttons: {
430 Ok: function() {
431 jQuery(this).dialog(\'close\');
432 }
433 }
434 });
435 });
436 </script>';
437
438 $msg .= "\n";
439
440 return $msg;
441}
442
443
459function ajax_combobox($htmlname, $events = array(), $minLengthToAutocomplete = 0, $forcefocus = 0, $widthTypeOfAutocomplete = 'resolve', $idforemptyvalue = '-1', $morecss = '')
460{
461 global $conf;
462
463 // select2 can be disabled for smartphones
464 if (!empty($conf->browser->layout) && $conf->browser->layout == 'phone' && getDolGlobalString('MAIN_DISALLOW_SELECT2_WITH_SMARTPHONE')) {
465 return '';
466 }
467
468 if (getDolGlobalString('MAIN_DISABLE_AJAX_COMBOX')) {
469 return '';
470 }
471 if (empty($conf->use_javascript_ajax)) {
472 return '';
473 }
474 if (!getDolGlobalString('MAIN_USE_JQUERY_MULTISELECT') && !defined('REQUIRE_JQUERY_MULTISELECT')) {
475 return '';
476 }
477 if (getDolGlobalString('MAIN_OPTIMIZEFORTEXTBROWSER')) {
478 return '';
479 }
480
481 if (empty($minLengthToAutocomplete)) {
482 $minLengthToAutocomplete = 0;
483 }
484
485 $moreselect2theme = ($morecss ? dol_escape_js(' '.$morecss) : '');
486 $moreselect2theme = preg_replace('/widthcentpercentminus[^\s]*/', '', $moreselect2theme);
487
488 $tmpplugin = 'select2';
489 $msg = "\n".'<!-- JS CODE TO ENABLE '.$tmpplugin.' for id = '.$htmlname.' -->
490 <script>
491 $(document).ready(function () {
492 $(\''.(preg_match('/^\./', $htmlname) ? $htmlname : '#'.$htmlname).'\').'.$tmpplugin.'({
493 dir: \'ltr\',';
494 if (preg_match('/onrightofpage/', $morecss)) { // when $morecss contains 'onrightofpage', the select2 component must also be inside a parent with class="parentonrightofpage"
495 $msg .= ' dropdownAutoWidth: true, dropdownParent: $(\'#'.$htmlname.'\').parent(), '."\n";
496 }
497 $msg .= ' width: \''.dol_escape_js($widthTypeOfAutocomplete).'\', /* off or resolve */
498 minimumInputLength: '.((int) $minLengthToAutocomplete).',
499 language: select2arrayoflanguage,
500 matcher: function (params, data) {
501 if ($.trim(params.term) === "") {
502 return data;
503 }
504 keywords = (params.term).split(" ");
505 for (var i = 0; i < keywords.length; i++) {
506 if (((data.text).toUpperCase()).indexOf((keywords[i]).toUpperCase()) == -1) {
507 return null;
508 }
509 }
510 return data;
511 },
512 theme: \'default'.$moreselect2theme.'\', /* to add css on generated html components */
513 containerCssClass: \':all:\', /* Line to add class of origin SELECT propagated to the new <span class="select2-selection...> tag */
514 selectionCssClass: \':all:\', /* Line to add class of origin SELECT propagated to the new <span class="select2-selection...> tag */
515 dropdownCssClass: \'ui-dialog\',
516 templateResult: function (data, container) { /* Format visible output into combo list */
517 /* Code to add class of origin OPTION propagated to the new select2 <li> tag */
518 if (data.element) { $(container).addClass($(data.element).attr("class")); }
519 //console.log("data html is "+$(data.element).attr("data-html"));
520 if (data.id == '.((int) $idforemptyvalue).' && $(data.element).attr("data-html") == undefined) {
521 return \'&nbsp;\';
522 }
523 if ($(data.element).attr("data-html") != undefined) {
524 /* If property html set, we decode html entities and use this. */
525 /* Note that HTML content must have been sanitized from js with dol_escape_htmltag(xxx, 0, 0, \'\', 0, 1) when building the select option. */
526 if (typeof htmlEntityDecodeJs === "function") {
527 return htmlEntityDecodeJs($(data.element).attr("data-html"));
528 }
529 }
530 return data.text;
531 },
532 templateSelection: function (selection) { /* Format visible output of selected value */
533 if (selection.id == '.((int) $idforemptyvalue).') return \'<span class="placeholder">\'+selection.text+\'</span>\';
534 return selection.text;
535 },
536 escapeMarkup: function(markup) {
537 return markup;
538 }
539 })';
540 if ($forcefocus) {
541 $msg .= '.select2(\'focus\')';
542 }
543 $msg .= ';'."\n";
544
545 $msg .= '});'."\n";
546 $msg .= "</script>\n";
547
548 $msg .= ajax_event($htmlname, $events);
549
550 return $msg;
551}
552
553
562function ajax_event($htmlname, $events)
563{
564 $out = '';
565
566 if (is_array($events) && count($events)) { // If an array of js events to do were provided.
567 $out = '<!-- JS code to manage event for id = ' . $htmlname . ' -->
568 <script>
569 $(document).ready(function () {
570 jQuery("#'.$htmlname.'").change(function () {
571 var obj = '.json_encode($events) . ';
572 $.each(obj, function(key,values) {
573 if (values.method.length) {
574 runJsCodeForEvent'.$htmlname.'(values);
575 }
576 });
577 });
578 function runJsCodeForEvent'.$htmlname.'(obj) {
579 var id = $("#'.$htmlname.'").val();
580 var method = obj.method;
581 var url = obj.url;
582 var htmlname = obj.htmlname;
583 var showempty = obj.showempty;
584 console.log("Run runJsCodeForEvent-'.$htmlname.' from ajax_combobox id="+id+" method="+method+" showempty="+showempty+" url="+url+" htmlname="+htmlname);
585 $.getJSON(url,
586 {
587 action: method,
588 id: id,
589 htmlname: htmlname,
590 showempty: showempty
591 },
592 function(response) {
593 $.each(obj.params, function(key,action) {
594 if (key.length) {
595 var num = response.num;
596 if (num > 0) {
597 $("#" + key).removeAttr(action);
598 } else {
599 $("#" + key).attr(action, action);
600 }
601 }
602 });
603
604 console.log("Replace HTML content of select#"+htmlname);
605 $("select#" + htmlname).html(response.value);
606 if (response.num) {
607 var selecthtml_str = response.value; /* response.value is the HTML string with list of options */
608 var selecthtml_dom=$.parseHTML(selecthtml_str);
609 if (typeof(selecthtml_dom[0][0]) !== \'undefined\') {
610 $("#inputautocomplete"+htmlname).val(selecthtml_dom[0][0].innerHTML);
611 }
612 } else {
613 $("#inputautocomplete"+htmlname).val("");
614 }
615 $("select#" + htmlname).change(); /* Trigger event change */
616 }
617 );
618 }
619 });
620 </script>';
621 }
622
623 return $out;
624}
625
626
647function 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 = '')
648{
649 global $conf, $langs, $user, $db;
650
651 $entity = ((isset($entity) && is_numeric($entity) && $entity >= 0) ? $entity : $conf->entity);
652 if (!isset($input)) {
653 $input = array();
654 }
655
656 if (empty($conf->use_javascript_ajax) || $forcenoajax) {
657 if (!getDolGlobalString($code)) {
658 $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>';
659 } else {
660 $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>';
661 }
662 } else {
663 $userconstid = 0;
664 if (is_object($userconst)) {
665 $userconstid = $userconst->id;
666 } elseif (is_numeric($userconst) && $userconst > 0) {
667 $userconstid = $userconst;
668 $userconst = new User($db);
669 $userconst->fetch($userconstid);
670 }
671
672 $out = "\n<!-- Ajax code to switch constant ".$code." -->".'
673 <script>
674 $(document).ready(function() {
675 var input = '.json_encode($input).';
676 var url = \''.DOL_URL_ROOT.'/core/ajax/constantonoff.php\';
677 var code = \''.dol_escape_js($code).'\';
678 var entity = \''.dol_escape_js($entity).'\';
679 var strict = \''.dol_escape_js((string) $strict).'\';
680 var userid = \''.dol_escape_js((string) $user->id).'\';
681 var userconst = '.((int) $userconstid).';
682 var yesButton = \''.dol_escape_js($langs->transnoentities("Yes")).'\';
683 var noButton = \''.dol_escape_js($langs->transnoentities("No")).'\';
684 var token = \''.currentToken().'\';
685 var warning = \''.dol_escape_js($showwarning).'\';
686
687 // Set constant
688 $("#set_" + code).click(function() {
689 if (warning) {
690 alert(warning);
691 }
692
693 if (input.alert && input.alert.set) {
694 if (input.alert.set.yesButton) yesButton = input.alert.set.yesButton;
695 if (input.alert.set.noButton) noButton = input.alert.set.noButton;
696 confirmConstantAction("set", url, code, input, input.alert.set, entity, yesButton, noButton, strict, userid, token);
697 } else {
698 setConstant(url, code, input, entity, 0, '.((int) $forcereload).', userid, token, 1, userconst);
699 }
700 });
701
702 // Del constant
703 $("#del_" + code).click(function() {
704 if (input.alert && input.alert.del) {
705 if (input.alert.del.yesButton) yesButton = input.alert.del.yesButton;
706 if (input.alert.del.noButton) noButton = input.alert.del.noButton;
707 confirmConstantAction("del", url, code, input, input.alert.del, entity, yesButton, noButton, strict, userid, token);
708 } else {';
709 if (empty($setzeroinsteadofdel)) {
710 $out .= ' delConstant(url, code, input, entity, 0, '.((int) $forcereload).', userid, token, userconst);';
711 } else {
712 $out .= ' setConstant(url, code, input, entity, 0, '.((int) $forcereload).', userid, token, 0, userconst);';
713 }
714 $out .= ' }
715 });
716 });
717 </script>'."\n";
718
719 if (!empty($userconst) && $userconst instanceof User) {
720 $value = getDolUserString($code, '', $userconst);
721 } else {
722 $value = getDolGlobalString($code);
723 }
724 $out .= '<div id="confirm_'.$code.'" title="" style="display: none;"></div>';
725 $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>';
726 $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>';
727 $out .= "\n";
728 }
729
730 return $out;
731}
732
750function ajax_object_onoff($object, $code, $field, $text_on, $text_off, $input = array(), $morecss = '', $htmlname = '', $forcenojs = 0, $moreparam = '')
751{
752 global $conf, $langs;
753
754 if (empty($htmlname)) {
755 $htmlname = $code;
756 }
757
758 $out = '';
759
760 if (!empty($conf->use_javascript_ajax) && empty($forcenojs)) {
761 $out .= '<script>
762 $(function() {
763 var input = '.json_encode($input).';
764
765 // Set constant
766 $("#set_'.$htmlname.'_'.$object->id.'").click(function() {
767 console.log("Click managed by ajax_object_onoff");
768 $.get( "'.DOL_URL_ROOT.'/core/ajax/objectonoff.php", {
769 action: \'set\',
770 field: \''.dol_escape_js($field).'\',
771 value: \'1\',
772 element: \''.dol_escape_js((empty($object->module) || $object->module == $object->element) ? $object->element : $object->element.'@'.$object->module).'\',
773 id: \''.((int) $object->id).'\',
774 token: \''.currentToken().'\'
775 },
776 function() {
777 $("#set_'.$htmlname.'_'.$object->id.'").hide();
778 $("#del_'.$htmlname.'_'.$object->id.'").show();
779 // Enable another element
780 if (input.disabled && input.disabled.length > 0) {
781 $.each(input.disabled, function(key,value) {
782 $("#" + value).removeAttr("disabled");
783 if ($("#" + value).hasClass("butActionRefused") == true) {
784 $("#" + value).removeClass("butActionRefused");
785 $("#" + value).addClass("butAction");
786 }
787 });
788 // Show another element
789 } else if (input.showhide && input.showhide.length > 0) {
790 $.each(input.showhide, function(key,value) {
791 $("#" + value).show();
792 });
793 }
794 });
795 });
796
797 // Del constant
798 $("#del_'.$htmlname.'_'.$object->id.'").click(function() {
799 console.log("Click managed by ajax_object_onoff");
800 $.get( "'.DOL_URL_ROOT.'/core/ajax/objectonoff.php", {
801 action: \'set\',
802 field: \''.dol_escape_js($field).'\',
803 value: \'0\',
804 element: \''.dol_escape_js((empty($object->module) || $object->module == $object->element) ? $object->element : $object->element.'@'.$object->module).'\',
805 id: \''.((int) $object->id).'\',
806 token: \''.currentToken().'\'
807 },
808 function() {
809 $("#del_'.$htmlname.'_'.$object->id.'").hide();
810 $("#set_'.$htmlname.'_'.$object->id.'").show();
811 // Disable another element
812 if (input.disabled && input.disabled.length > 0) {
813 $.each(input.disabled, function(key,value) {
814 $("#" + value).prop("disabled", true);
815 if ($("#" + value).hasClass("butAction") == true) {
816 $("#" + value).removeClass("butAction");
817 $("#" + value).addClass("butActionRefused");
818 }
819 });
820 // Hide another element
821 } else if (input.showhide && input.showhide.length > 0) {
822 $.each(input.showhide, function(key,value) {
823 $("#" + value).hide();
824 });
825 }
826 });
827 });
828 });
829 </script>';
830 }
831
832 $switchon = 'switch_on';
833 $switchoff = 'switch_off';
834 $cssswitchon = '';
835 $cssswitchoff = '';
836 $tmparray = explode(':', $text_on);
837 if (!empty($tmparray[1])) {
838 $text_on = $tmparray[0];
839 $switchon = $tmparray[1];
840 if (!empty($tmparray[2])) {
841 $cssswitchon = $tmparray[2];
842 }
843 }
844 $tmparray = explode(':', $text_off);
845 if (!empty($tmparray[1])) {
846 $text_off = $tmparray[0];
847 $switchoff = $tmparray[1];
848 if (!empty($tmparray[2])) {
849 $cssswitchoff = $tmparray[2];
850 }
851 }
852
853 if (empty($conf->use_javascript_ajax) || $forcenojs) {
854 $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>';
855 $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>';
856 } else {
857 $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>';
858 $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>';
859 }
860
861 return $out;
862}
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:459
ajax_dialog($title, $message, $w=350, $h=150)
Show an ajax dialog.
Definition ajax.lib.php:416
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:308
ajax_event($htmlname, $events)
Add event management script.
Definition ajax.lib.php:562
Class to manage Dolibarr users.
img_picto($titlealt, $picto, $moreatt='', $pictoisfullpath=0, $srconly=0, $notitle=0, $alt='', $morecss='', $marginleftonlyshort=2)
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