dolibarr 18.0.6
lib_head.js.php
Go to the documentation of this file.
1<?php
2/* Copyright (C) 2005-2018 Laurent Destailleur <eldy@users.sourceforge.net>
3 * Copyright (C) 2005-2014 Regis Houssin <regis.houssin@inodbox.com>
4 * Copyright (C) 2015 Raphaël Doursenaud <rdoursenaud@gpcsolutions.fr>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <https://www.gnu.org/licenses/>.
18 * or see https://www.gnu.org/
19 */
20
27if (!defined('NOREQUIRESOC')) {
28 define('NOREQUIRESOC', '1');
29}
30if (!defined('NOCSRFCHECK')) {
31 define('NOCSRFCHECK', 1);
32}
33if (!defined('NOTOKENRENEWAL')) {
34 define('NOTOKENRENEWAL', 1);
35}
36if (!defined('NOLOGIN')) {
37 define('NOLOGIN', 1);
38}
39if (!defined('NOREQUIREMENU')) {
40 define('NOREQUIREMENU', 1);
41}
42if (!defined('NOREQUIREHTML')) {
43 define('NOREQUIREHTML', 1);
44}
45if (!defined('NOREQUIREAJAX')) {
46 define('NOREQUIREAJAX', '1');
47}
48
49session_cache_limiter('public');
50
51require_once '../../main.inc.php';
52
53
54/*
55 * View
56 */
57
58// Define javascript type
59top_httphead('text/javascript; charset=UTF-8');
60// Important: Following code is to avoid page request by browser and PHP CPU at each Dolibarr page access.
61if (empty($dolibarr_nocache)) {
62 header('Cache-Control: max-age=10800, public, must-revalidate');
63} else {
64 header('Cache-Control: no-cache');
65}
66
67
68
69// Define tradMonths javascript array (we define this in datepicker AND in parent page to avoid errors with IE8)
70$tradMonths = array(
71dol_escape_js($langs->transnoentitiesnoconv("Month01")),
72dol_escape_js($langs->transnoentitiesnoconv("Month02")),
73dol_escape_js($langs->transnoentitiesnoconv("Month03")),
74dol_escape_js($langs->transnoentitiesnoconv("Month04")),
75dol_escape_js($langs->transnoentitiesnoconv("Month05")),
76dol_escape_js($langs->transnoentitiesnoconv("Month06")),
77dol_escape_js($langs->transnoentitiesnoconv("Month07")),
78dol_escape_js($langs->transnoentitiesnoconv("Month08")),
79dol_escape_js($langs->transnoentitiesnoconv("Month09")),
80dol_escape_js($langs->transnoentitiesnoconv("Month10")),
81dol_escape_js($langs->transnoentitiesnoconv("Month11")),
82dol_escape_js($langs->transnoentitiesnoconv("Month12"))
83);
84
85$tradMonthsShort = array(
86$langs->trans("MonthShort01"),
87$langs->trans("MonthShort02"),
88$langs->trans("MonthShort03"),
89$langs->trans("MonthShort04"),
90$langs->trans("MonthShort05"),
91$langs->trans("MonthShort06"),
92$langs->trans("MonthShort07"),
93$langs->trans("MonthShort08"),
94$langs->trans("MonthShort09"),
95$langs->trans("MonthShort10"),
96$langs->trans("MonthShort11"),
97$langs->trans("MonthShort12")
98);
99
100$tradDays = array(
101$langs->trans("Sunday"),
102$langs->trans("Monday"),
103$langs->trans("Tuesday"),
104$langs->trans("Wednesday"),
105$langs->trans("Thursday"),
106$langs->trans("Friday"),
107$langs->trans("Saturday")
108);
109
110$tradDaysShort = array(
111$langs->trans("ShortSunday"),
112$langs->trans("ShortMonday"),
113$langs->trans("ShortTuesday"),
114$langs->trans("ShortWednesday"),
115$langs->trans("ShortThursday"),
116$langs->trans("ShortFriday"),
117$langs->trans("ShortSaturday")
118);
119
120$tradDaysMin = array(
121$langs->trans("SundayMin"),
122$langs->trans("MondayMin"),
123$langs->trans("TuesdayMin"),
124$langs->trans("WednesdayMin"),
125$langs->trans("ThursdayMin"),
126$langs->trans("FridayMin"),
127$langs->trans("SaturdayMin")
128);
129
130
131$dec = ',';
132$thousand = ' ';
133if ($langs->transnoentitiesnoconv("SeparatorDecimal") != "SeparatorDecimal") {
134 $dec = $langs->transnoentitiesnoconv("SeparatorDecimal");
135}
136if ($langs->transnoentitiesnoconv("SeparatorThousand") != "SeparatorThousand") {
137 $thousand = $langs->transnoentitiesnoconv("SeparatorThousand");
138}
139if ($thousand == 'Space') {
140 $thousand = ' ';
141}
142
143?>
144// Javascript libraries for Dolibarr ERP CRM (https://www.dolibarr.org)
145
146// For jQuery date picker
147var tradMonths = <?php echo json_encode($tradMonths) ?>;
148var tradMonthsShort = <?php echo json_encode($tradMonthsShort) ?>;
149var tradDays = <?php echo json_encode($tradDays) ?>;
150var tradDaysShort = <?php echo json_encode($tradDaysShort) ?>;
151var tradDaysMin = <?php echo json_encode($tradDaysMin) ?>;
152var currencyCache = <?php echo json_encode($langs->cache_currencies) ?>;
153
154// For JQuery date picker
155$(document).ready(function() {
156 $.datepicker.setDefaults({
157 autoSize: true,
158 changeMonth: true,
159 changeYear: true,
160 altField: '#timestamp',
161 altFormat: '@' // Gives a timestamp dateformat
162 });
163});
164
165jQuery(function($){
166 $.datepicker.regional['<?php echo $langs->defaultlang ?>'] = {
167 closeText: '<?php echo $langs->trans("Close2") ?>',
168 prevText: '<?php echo $langs->trans("Previous") ?>',
169 nextText: '<?php echo $langs->trans("Next") ?>',
170 currentText: '<?php echo $langs->trans("Now") ?>',
171 monthNames: tradMonths,
172 monthNamesShort: tradMonthsShort,
173 dayNames: tradDays,
174 dayNamesShort: tradDaysShort,
175 dayNamesMin: tradDaysMin,
176 weekHeader: '<?php echo $langs->trans("Week"); ?>',
177 dateFormat: '<?php echo $langs->trans("FormatDateShortJQuery"); ?>', /* Note dd/mm/yy means year on 4 digit in jquery format */
178 firstDay: <?php echo (isset($conf->global->MAIN_START_WEEK) ? $conf->global->MAIN_START_WEEK : '1'); ?>,
179 isRTL: <?php echo ($langs->trans("DIRECTION") == 'rtl' ? 'true' : 'false'); ?>,
180 showMonthAfterYear: false, /* TODO add specific to country */
181 yearSuffix: '' /* TODO add specific to country */
182 };
183 $.datepicker.setDefaults($.datepicker.regional['<?php echo $langs->defaultlang ?>']);
184});
185
186
187
192var select2arrayoflanguage = {
193 matches: function (matches) { return matches + " <?php echo dol_escape_js($langs->transnoentitiesnoconv("Select2ResultFoundUseArrows")); ?>"; },
194 noResults: function () { return "<?php echo dol_escape_js($langs->transnoentitiesnoconv("Select2NotFound")); ?>"; },
195 inputTooShort: function (input) {
196 var n = input.minimum;
197 /*console.log(input);
198 console.log(input.minimum);*/
199 if (n > 1) return "<?php echo dol_escape_js($langs->transnoentitiesnoconv("Select2Enter")); ?> " + n + " <?php echo dol_escape_js($langs->transnoentitiesnoconv("Select2MoreCharacters")); ?>";
200 else return "<?php echo dol_escape_js($langs->transnoentitiesnoconv("Select2Enter")); ?> " + n + " <?php echo dol_escape_js($langs->transnoentitiesnoconv("Select2MoreCharacter")); ?>"
201 },
202 loadMore: function (pageNumber) { return "<?php echo dol_escape_js($langs->transnoentitiesnoconv("Select2LoadingMoreResults")); ?>"; },
203 searching: function () { return "<?php echo dol_escape_js($langs->transnoentitiesnoconv("Select2SearchInProgress")); ?>"; }
204};
205
206
211// Returns an object given an id
212function getObjectFromID(id){
213 var theObject;
214 if(document.getElementById)
215 theObject=document.getElementById(id);
216 else
217 theObject=document.all[id];
218 return theObject;
219}
220
221// Called after selection of a date to save details into detailed fields
222function dpChangeDay(dateFieldID, format)
223{
224 //showDP.datefieldID=dateFieldID;
225 console.log("Call dpChangeDay, we save date into detailed fields from format = "+format);
226
227 var thefield=getObjectFromID(dateFieldID);
228 var thefieldday=getObjectFromID(dateFieldID+"day");
229 var thefieldmonth=getObjectFromID(dateFieldID+"month");
230 var thefieldyear=getObjectFromID(dateFieldID+"year");
231
232 var date=getDateFromFormat(thefield.value, format);
233 //console.log(date);
234 if (date)
235 {
236 thefieldday.value=date.getDate();
237 if(thefieldday.onchange) thefieldday.onchange.call(thefieldday);
238 thefieldmonth.value=date.getMonth()+1;
239 if(thefieldmonth.onchange) thefieldmonth.onchange.call(thefieldmonth);
240 thefieldyear.value=date.getFullYear();
241 if(thefieldyear.onchange) thefieldyear.onchange.call(thefieldyear);
242 }
243 else
244 {
245 thefieldday.value='';
246 if(thefieldday.onchange) thefieldday.onchange.call(thefieldday);
247 thefieldmonth.value='';
248 if(thefieldmonth.onchange) thefieldmonth.onchange.call(thefieldmonth);
249 thefieldyear.value='';
250 if(thefieldyear.onchange) thefieldyear.onchange.call(thefieldyear);
251 }
252}
253
254/*
255 * =================================================================
256 * Function:
257 * formatDate (javascript object Date(), format) Purpose: Returns a date in the
258 * output format specified. The format string can use the following tags: Field |
259 * Tags -------------+------------------------------- Year | yyyy (4 digits), yy
260 * (2 digits) Month | MM (2 digits) Day of Month | dd (2 digits) Hour (1-12) |
261 * hh (2 digits) Hour (0-23) | HH (2 digits) Minute | mm (2 digits) Second | ss
262 * (2 digits) Author: Laurent Destailleur Author: Matelli (see
263 * http://matelli.fr/showcases/patchs-dolibarr/update-date-input-in-action-form.html)
264 * Licence: GPL
265 * ==================================================================
266 */
267function formatDate(date,format)
268{
269 // alert('formatDate date='+date+' format='+format);
270
271 // Force parametres en chaine
272 format=format+"";
273
274 var result="";
275
276 var year=date.getYear()+""; if (year.length < 4) { year=""+(year-0+1900); }
277 var month=date.getMonth()+1;
278 var day=date.getDate();
279 var hour=date.getHours();
280 var minute=date.getMinutes();
281 var seconde=date.getSeconds();
282
283 var i=0;
284 while (i < format.length)
285 {
286 c=format.charAt(i); // Recupere char du format
287 var substr = '';
288 j=i;
289 while ((format.charAt(j)==c) && (j < format.length)) // Recupere char successif identiques
290 {
291 substr += format.charAt(j++);
292 }
293
294 // alert('substr='+substr);
295 if (substr == 'yyyy') { result=result+year; }
296 else if (substr == 'yy') { result=result+year.substring(2,4); }
297 else if (substr == 'M') { result=result+month; }
298 else if (substr == 'MM') { result=result+(month<1||month>9?"":"0")+month; }
299 else if (substr == 'd') { result=result+day; }
300 else if (substr == 'dd') { result=result+(day<1||day>9?"":"0")+day; }
301 else if (substr == 'hh') { if (hour > 12) hour-=12; result=result+(hour<0||hour>9?"":"0")+hour; }
302 else if (substr == 'HH') { result=result+(hour<0||hour>9?"":"0")+hour; }
303 else if (substr == 'mm') { result=result+(minute<0||minute>9?"":"0")+minute; }
304 else if (substr == 'ss') { result=result+(seconde<0||seconde>9?"":"0")+seconde; }
305 else { result=result+substr; }
306
307 i+=substr.length;
308 }
309
310 // alert(result);
311 return result;
312}
313
314
315/*
316 * =================================================================
317 * Function: getDateFromFormat(date_string, format_string)
318 * Purpose: This function takes a date string and a format string.
319 * It parses the date string with format and it
320 * returns the date as a javascript Date() object. If date does not match
321 * format, it returns 0. The format string can use the following tags:
322 * Field | Tags
323 * -------------+-----------------------------------
324 * Year | yyyy (4 digits), yy (2 digits)
325 * Month | MM (2 digits)
326 * Day of Month | dd (2 digits)
327 * Hour (1-12) | hh (2 digits)
328 * Hour (0-23) | HH (2 digits)
329 * Minute | mm (2 digits)
330 * Second | ss (2 digits)
331 * Author: Laurent Destailleur
332 * Licence: GPL
333 * ==================================================================
334 */
335function getDateFromFormat(val,format)
336{
337 // alert('getDateFromFormat val='+val+' format='+format);
338
339 // Force parametres en chaine
340 val=val+"";
341 format=format+"";
342
343 if (val == '') return 0;
344
345 var now=new Date();
346 var year=now.getYear(); if (year.length < 4) { year=""+(year-0+1900); }
347 var month=now.getMonth()+1;
348 var day=now.getDate();
349 var hour=now.getHours();
350 var minute=now.getMinutes();
351 var seconde=now.getSeconds();
352
353 var i=0;
354 var d=0; // -d- follows the date string while -i- follows the format
355 // string
356
357 while (i < format.length)
358 {
359 c=format.charAt(i); // Recupere char du format
360 substr="";
361 j=i;
362 while ((format.charAt(j)==c) && (j < format.length)) // Recupere char
363 // successif
364 // identiques
365 {
366 substr += format.charAt(j++);
367 }
368
369 // alert('substr='+substr);
370 if (substr == "yyyy") year=getIntegerInString(val,d,4,4);
371 if (substr == "yy") year=""+(getIntegerInString(val,d,2,2)-0+1900);
372 if (substr == "MM" ||substr == "M")
373 {
374 month=getIntegerInString(val,d,1,2);
375 if (month) d -= 2- month.length;
376 }
377 if (substr == "dd")
378 {
379 day=getIntegerInString(val,d,1,2);
380 if (day) d -= 2- day.length;
381 }
382 if (substr == "HH" ||substr == "hh" )
383 {
384 hour=getIntegerInString(val,d,1,2);
385 if (dhouray) d -= 2- hour.length;
386 }
387 if (substr == "mm"){
388 minute=getIntegerInString(val,d,1,2);
389 if (minute) d -= 2- minute.length;
390 }
391 if (substr == "ss")
392 {
393 seconde=getIntegerInString(val,d,1,2);
394 if (seconde) d -= 2- seconde.length;
395 }
396
397 i+=substr.length;
398 d+=substr.length;
399 }
400
401 // Check if format param are ok
402 if (year==null||year<1) { return 0; }
403 if (month==null||(month<1)||(month>12)) { return 0; }
404 if (day==null||(day<1)||(day>31)) { return 0; }
405 if (hour==null||(hour<0)||(hour>24)) { return 0; }
406 if (minute==null||(minute<0)||(minute>60)) { return 0; }
407 if (seconde==null||(seconde<0)||(seconde>60)) { return 0; }
408
409 // alert(year+' '+month+' '+day+' '+hour+' '+minute+' '+seconde);
410 return new Date(year,month-1,day,hour,minute,seconde);
411}
412
413/*
414 * =================================================================
415 * Function: stringIsInteger(string)
416 * Purpose: Return true if string is an integer
417 * ==================================================================
418 */
419function stringIsInteger(str)
420{
421 var digits="1234567890";
422 for (var i=0; i < str.length; i++)
423 {
424 if (digits.indexOf(str.charAt(i))==-1)
425 {
426 return false;
427 }
428 }
429 return true;
430}
431
432/*
433 * =================================================================
434 * Function: getIntegerInString(string,pos,minlength,maxlength)
435 * Purpose: Return part of string from position i that is integer
436 * ==================================================================
437 */
438function getIntegerInString(str,i,minlength,maxlength)
439{
440 for (var x=maxlength; x>=minlength; x--)
441 {
442 var substr=str.substring(i,i+x);
443 if (substr.length < minlength) { return null; }
444 if (stringIsInteger(substr)) { return substr; }
445 }
446 return null;
447}
448
449
450/*
451 * =================================================================
452 * Purpose: Clean string to have it url encoded
453 * Input: s
454 * Author: Laurent Destailleur
455 * Licence: GPL
456 * ==================================================================
457 */
458function urlencode(s) {
459 var news = s;
460 news = news.replace(/\+/gi,'%2B');
461 news = news.replace(/&/gi,'%26');
462 return news;
463}
464
465/*
466 * =================================================================
467 * Purpose: Clean string to get a HTML coded string.
468 * Input: s
469 * Author: Laurent Destailleur
470 * Licence: GPL
471 * ==================================================================
472 */
473function htmlEntityDecodeJs(inp){
474 var replacements = {'&lt;':'<','&gt;':'>','&sol;':'/','&quot;':'"','&apos;':'\'','&amp;':'&','&nbsp;':' '};
475 if (inp) {
476 for(var r in replacements){
477 inp = inp.replace(new RegExp(r,'g'),replacements[r]);
478 }
479 return inp.replace(/&#(\d+);/g, function(match, dec) {
480 return String.fromCharCode(dec);
481 });
482 } else {
483 return '';
484 }
485}
486
487
488/*
489 * =================================================================
490 * Purpose: Applique un delai avant execution. Used for autocompletion of companies.
491 * Input: funct, delay
492 * Author: Regis Houssin
493 * Licence: GPL
494 * ==================================================================
495 */
496 function ac_delay(funct,delay) {
497 // delay before start of action
498 setTimeout(funct,delay);
499}
500
501
502/*
503 * =================================================================
504 * Purpose:
505 * Clean values of a "Sortable.serialize". Used by drag and drop.
506 * Input: expr
507 * Author: Regis Houssin
508 * Licence: GPL
509 * ==================================================================
510 */
511function cleanSerialize(expr) {
512 if (typeof(expr) != 'string') {
513 return '';
514 }
515 var reg = new RegExp("(&)", "g");
516 var reg2 = new RegExp("[^A-Z0-9,]", "g");
517 var liste1 = expr.replace(reg, ",");
518 return liste1.replace(reg2, "");
519}
520
521
522/*
523 * =================================================================
524 * Purpose: Display a temporary message in input text fields (For showing help message on
525 * input field).
526 * Input: fieldId
527 * Input: message
528 * Author: Regis Houssin
529 * Licence: GPL
530 * ==================================================================
531 */
532function displayMessage(fieldId,message) {
533 var textbox = document.getElementById(fieldId);
534 if (textbox.value == '') {
535 textbox.style.color = 'grey';
536 textbox.value = message;
537 }
538}
539
540/*
541 * =================================================================
542 * Purpose: Hide a temporary message in input text fields (For showing help message on
543 * input field).
544 * Input: fiedId
545 * Input: message
546 * Author: Regis Houssin
547 * Licence: GPL
548 * ==================================================================
549 */
550function hideMessage(fieldId,message) {
551 var textbox = document.getElementById(fieldId);
552 textbox.style.color = 'black';
553 if (textbox.value == message) textbox.value = '';
554}
555
556
557/*
558 * Used by button to set on/off.
559 * Call url then make complementary action (like show/hide, enable/disable or set another option).
560 *
561 * @param string url Url (warning: as any url called in ajax mode, the url called here must not renew the token)
562 * @param string code Code
563 * @param string intput Array of complementary actions to do if success
564 * @param int entity Entity
565 * @param int strict Strict
566 * @param int forcereload Force reload
567 * @param int userid User id
568 * @param int value Value to set
569 * @param string token Token
570 * @retun boolean
571 */
572function setConstant(url, code, input, entity, strict, forcereload, userid, token, value) {
573 var saved_url = url; /* avoid undefined url */
574 $.post( url, {
575 action: "set",
576 name: code,
577 entity: entity,
578 token: token,
579 value: value
580 },
581 function() { /* handler for success of post */
582 console.log("Ajax url request to set constant is a success. Make complementary actions and then forcereload="+forcereload+" value="+value);
583 if (value == 0) {
584 $("#set_" + code).show();
585 $("#del_" + code).hide();
586 } else {
587 $("#set_" + code).hide();
588 $("#del_" + code).show();
589 }
590 $.each(input, function(type, data) {
591 // Enable another element
592 if (type == "disabled" && strict != 1) {
593 $.each(data, function(key, value) {
594 var newvalue=((value.search("^#") < 0 && value.search("^\.") < 0) ? "#" : "") + value;
595 $(newvalue).removeAttr("disabled");
596 if ($(newvalue).hasClass("butActionRefused") == true) {
597 $(newvalue).removeClass("butActionRefused");
598 $(newvalue).addClass("butAction");
599 }
600 });
601 } else if (type == "enabled") {
602 $.each(data, function(key, value) {
603 var newvalue=((value.search("^#") < 0 && value.search("^\.") < 0) ? "#" : "") + value;
604 if (strict == 1)
605 $(newvalue).removeAttr("disabled");
606 else
607 $(newvalue).attr("disabled", true);
608 if ($(newvalue).hasClass("butAction") == true) {
609 $(newvalue).removeClass("butAction");
610 $(newvalue).addClass("butActionRefused");
611 }
612 });
613 // Show another element
614 } else if (type == "showhide" || type == "show") {
615 $.each(data, function(key, value) {
616 var newvalue=((value.search("^#") < 0 && value.search("^\.") < 0) ? "#" : "") + value;
617 $(newvalue).show();
618 });
619 // Set another constant
620 } else if (type == "set") {
621 $.each(data, function(key, value) {
622 $("#set_" + key).hide();
623 $("#del_" + key).show();
624 $.post( saved_url, {
625 action: "set",
626 name: key,
627 value: value,
628 entity: entity,
629 token: token
630 });
631 });
632 }
633 });
634 if (forcereload) {
635 var url = window.location.href;
636 if (url.indexOf('dol_resetcache') < 0) {
637 if (url.indexOf('?') > -1) {
638 url = url + "&dol_resetcache=1";
639 } else {
640 url = url + "?dol_resetcache=1";
641 }
642 }
643 var page_y = $(document).scrollTop();
644 url = url.replace(/page_y=\d+/g, '');
645 if (page_y > 0) {
646 if (url.indexOf('?') > -1) {
647 url = url + "&page_y="+page_y;
648 } else {
649 url = url + "?page_y="+page_y;
650 }
651 }
652 url = url.replace(/&&+/, '&');
653 console.log("url ro redirect = "+url);
654
655 window.location.href = url;
656 //location.reload();
657 return false;
658 }
659 }).fail(function(error) { console.log("Error, we force reload"); location.reload(); }); /* When it fails, we always force reload to have setEventErrorMessages in session visible */
660
661 return true;
662}
663
664/*
665 * Used by button to set on/off
666 * Call url then make complementary action (like show/hide, enable/disable or set another option).
667 *
668 * @param {string} url Url (warning: as any url called in ajax mode, the url called here must not renew the token)
669 * @param {string} code Code
670 * @param {string} intput Array of complementary actions to do if success
671 * @param {int} entity Entity
672 * @param {int} strict Strict
673 * @param {int} forcereload Force reload
674 * @param {int} userid User id
675 * @param {string} token Token
676 * @return boolean
677 */
678function delConstant(url, code, input, entity, strict, forcereload, userid, token) {
679 var saved_url = url; /* avoid undefined url */
680 $.post( url, {
681 action: "del",
682 name: code,
683 entity: entity,
684 token: token
685 },
686 function() {
687 console.log("Ajax url request to delete constant is success. Make complementary actions and then forcereload="+forcereload);
688 $("#del_" + code).hide();
689 $("#set_" + code).show();
690 $.each(input, function(type, data) {
691 // Disable another element
692 if (type == "disabled") {
693 $.each(data, function(key, value) {
694 var newvalue=((value.search("^#") < 0 && value.search("^\.") < 0) ? "#" : "") + value;
695 $(newvalue).attr("disabled", true);
696 if ($(newvalue).hasClass("butAction") == true) {
697 $(newvalue).removeClass("butAction");
698 $(newvalue).addClass("butActionRefused");
699 }
700 });
701 } else if (type == "enabled" && strict != 1) {
702 $.each(data, function(key, value) {
703 var newvalue=((value.search("^#") < 0 && value.search("^\.") < 0) ? "#" : "") + value;
704 $(newvalue).removeAttr("disabled");
705 if ($(newvalue).hasClass("butActionRefused") == true) {
706 $(newvalue).removeClass("butActionRefused");
707 $(newvalue).addClass("butAction");
708 }
709 });
710 // Hide another element
711 } else if (type == "showhide" || type == "hide") {
712 $.each(data, function(key, value) {
713 var newvalue=((value.search("^#") < 0 && value.search("^\.") < 0) ? "#" : "") + value;
714 $(newvalue).hide();
715 });
716 // Delete another constant
717 } else if (type == "del") {
718 $.each(data, function(key, value) {
719 $("#del_" + value).hide();
720 $("#set_" + value).show();
721 $.post( saved_url, {
722 action: "del",
723 name: value,
724 entity: entity,
725 token: token
726 });
727 });
728 }
729 });
730 if (forcereload) {
731 var url = window.location.href;
732 if (url.indexOf('dol_resetcache') < 0) {
733 if (url.indexOf('?') > -1) {
734 url = url + "&dol_resetcache=1";
735 } else {
736 url = url + "?dol_resetcache=1";
737 }
738 }
739 var page_y = $(document).scrollTop();
740 url = url.replace(/page_y=\d+/g, '');
741 if (page_y > 0) {
742 if (url.indexOf('?') > -1) {
743 url = url + "&page_y="+page_y;
744 } else {
745 url = url + "?page_y="+page_y;
746 }
747 }
748 url = url.replace(/&&+/, '&');
749 console.log("url ro redirect = "+url);
750
751 window.location.href = url;
752 //location.reload();
753 return false;
754 }
755 }).fail(function(error) { console.log("Error, we force reload"); location.reload(); }); /* When it fails, we always force reload to have setEventErrorMessages in session visible */
756
757 return true;
758}
759
760/*
761 * Call the setConstant or delConstant but with a confirmation before.
762 * Used by button to set on/off.
763 *
764 * @param string action Action
765 * @param string url Url
766 * @param string code Code
767 * @param string intput Array of complementary actions to do if success
768 * @param string box Box
769 * @param int entity Entity
770 * @param int yesButton yesButton
771 * @param int noButton noButton
772 * @param int strict Strict
773 * @param int userid User id
774 * @param string token Token
775 * @return boolean
776 */
777function confirmConstantAction(action, url, code, input, box, entity, yesButton, noButton, strict, userid, token) {
778 var boxConfirm = box;
779 $("#confirm_" + code)
780 .attr("title", boxConfirm.title)
781 .html(boxConfirm.content)
782 .dialog({
783 resizable: false,
784 height: 170,
785 width: 500,
786 modal: true,
787 buttons: [
788 {
789 id : 'yesButton_' + code,
790 text : yesButton,
791 click : function() {
792 if (action == "set") {
793 setConstant(url, code, input, entity, strict, 0, userid, token, 1);
794 } else if (action == "del") {
795 delConstant(url, code, input, entity, strict, 0, userid, token);
796 }
797 // Close dialog
798 $(this).dialog("close");
799 // Execute another method
800 if (boxConfirm.method) {
801 var fnName = boxConfirm.method;
802 if (window.hasOwnProperty(fnName)) {
803 window[fnName]();
804 }
805 }
806 }
807 },
808 {
809 id : 'noButton_' + code,
810 text : noButton,
811 click : function() {
812 $(this).dialog("close");
813 }
814 }
815 ]
816 });
817 // For information dialog box only, hide the noButton
818 if (boxConfirm.info) {
819 $("#noButton_" + code).button().hide();
820 }
821
822 return true;
823}
824
825
826/*
827 * =================================================================
828 * This is to allow to transform all select box into ajax autocomplete box
829 * with just one line:
830 * $(function() { $( "#idofmylist" ).combobox(); });
831 * Do not use it on large combo boxes
832 * =================================================================
833 */
834(function( $ ) {
835 $.widget( "ui.combobox", {
836 options: {
837 minLengthToAutocomplete: 0
838 },
839 _create: function() {
840 var savMinLengthToAutocomplete = this.options.minLengthToAutocomplete;
841 var self = this,
842 select = this.element.hide(),
843 selected = select.children( ":selected" ),
844 value = selected.val() ? selected.text() : "";
845 var input = this.input = $( "<input>" )
846 .insertAfter( select )
847 .val( value )
848 .attr('id', 'inputautocomplete'+select.attr('id'))
849 .autocomplete({
850 delay: 0,
851 minLength: this.options.minLengthToAutocomplete,
852 source: function( request, response ) {
853 var matcher = new RegExp( $.ui.autocomplete.escapeRegex(request.term), "i" );
854 response( select.children( "option:enabled" ).map(function() {
855 var text = $( this ).text();
856 if ( this.value && ( !request.term || matcher.test(text) ) )
857 return {
858 label: text.replace(
859 new RegExp(
860 "(?![^&;]+;)(?!<[^<>]*)(" +
861 $.ui.autocomplete.escapeRegex(request.term) +
862 ")(?![^<>]*>)(?![^&;]+;)", "gi"
863 ), "<strong>$1</strong>" ),
864 value: text,
865 option: this
866 };
867 }) );
868 },
869 select: function( event, ui ) {
870 ui.item.option.selected = true;
871 self._trigger( "selected", event, {
872 item: ui.item.option
873 });
874 },
875 change: function( event, ui ) {
876 if ( !ui.item ) {
877 var matcher = new RegExp( "^" + $.ui.autocomplete.escapeRegex( $(this).val() ) + "$", "i" ),
878 valid = false;
879 select.children( "option" ).each(function() {
880 if ( $( this ).text().match( matcher ) ) {
881 this.selected = valid = true;
882 return false;
883 }
884 });
885 if ( !valid ) {
886 // remove invalid value, as it didnt match anything
887 $( this ).val( "" );
888 select.val( "" );
889 input.data("ui-autocomplete").term = "";
890 return false;
891 }
892 }
893 }
894 })
895 .addClass( "ui-widget ui-widget-content ui-corner-left dolibarrcombobox" );
896
897 input.data("ui-autocomplete")._renderItem = function( ul, item ) {
898 return $("<li>")
899 .data( "ui-autocomplete-item", item ) // jQuery UI > 1.10.0
900 .append( "<a>" + item.label + "</a>" )
901 .appendTo( ul );
902 };
903
904 this.button = $( "<button type=\'button\'>&nbsp;</button>" )
905 .attr( "tabIndex", -1 )
906 .attr( "title", "Show All Items" )
907 .insertAfter( input )
908 .button({
909 icons: {
910 primary: "ui-icon-triangle-1-s"
911 },
912 text: false
913 })
914 .removeClass( "ui-corner-all" )
915 .addClass( "ui-corner-right ui-button-icon" )
916 .click(function() {
917 // close if already visible
918 if ( input.autocomplete( "widget" ).is( ":visible" ) ) {
919 input.autocomplete( "close" );
920 return;
921 }
922
923 // pass empty string as value to search for, displaying all results
924 input.autocomplete({ minLength: 0 });
925 input.autocomplete( "search", "" );
926 input.autocomplete({ minLength: savMinLengthToAutocomplete });
927 input.focus();
928 });
929 },
930
931 destroy: function() {
932 this.input.remove();
933 this.button.remove();
934 this.element.show();
935 $.Widget.prototype.destroy.call( this );
936 }
937 });
938})( jQuery );
939
940
941
948function copyToClipboard(text,text2)
949{
950 text = text.replace(/<br>/g,"\n");
951 var newElem = '<textarea id="coordsforpopup" style="border: none; width: 90%; height: 120px;">'+text+'</textarea><br><br>'+text2;
952 /* alert(newElem); */
953 $("#dialogforpopup").html(newElem);
954 $("#dialogforpopup").dialog();
955 $("#coordsforpopup").select();
956
957 return false;
958}
959
960
969function newpopup(url, title) {
970 var argv = newpopup.arguments;
971 var argc = newpopup.arguments.length;
972 var tmp = url;
973 console.log("newpopup "+argv[2]+" "+argv[3]);
974 var l = (argc > 2) ? argv[2] : 600;
975 var h = (argc > 3) ? argv[3] : 400;
976 var left = (screen.width - l)/2;
977 var top = (screen.height - h)/2;
978 var wfeatures = "directories=0,menubar=0,status=0,resizable=0,scrollbars=1,toolbar=0,width=" + l +",height=" + h + ",left=" + left + ",top=" + top;
979 fen=window.open(tmp,title,wfeatures);
980
981 return false;
982}
983
994function document_preview(file, type, title)
995{
996 var ValidImageTypes = ["image/gif", "image/jpeg", "image/png", "image/webp"];
997 var showOriginalSizeButton = false;
998
999 console.log("document_preview A click was done. file="+file+", type="+type+", title="+title);
1000
1001 if ($.inArray(type, ValidImageTypes) < 0) {
1002 /* Not an image */
1003 var width='85%';
1004 var object_width='100%';
1005 var height = ($( window ).height() - 60) * 0.90;
1006 var object_height='98%';
1007
1008 show_preview('notimage');
1009
1010 } else {
1011 /* This is an image */
1012 var object_width=0;
1013 var object_height=0;
1014
1015 var img = new Image();
1016
1017 img.onload = function() {
1018 object_width = this.width;
1019 object_height = this.height;
1020
1021 width = $( window ).width()*0.90;
1022 console.log("object_width="+object_width+" window width="+width);
1023 if(object_width < width){
1024 console.log("Object width is small, we set width of popup according to image width.");
1025 width = object_width + 30
1026 }
1027 height = $( window ).height()*0.85;
1028 console.log("object_height="+object_height+" window height="+height);
1029 if(object_height < height){
1030 console.log("Object height is small, we set height of popup according to image height.");
1031 height = object_height + 80
1032 }
1033 else
1034 {
1035 showOriginalSizeButton = true;
1036 }
1037
1038 show_preview('image');
1039
1040 };
1041 img.src = file;
1042
1043 }
1044
1045 function show_preview(mode) {
1046 /* console.log("mode="+mode+" file="+file+" type="+type+" width="+width+" height="+height); */
1047 var newElem = '<object name="objectpreview" data="'+file+'" type="'+type+'" width="'+object_width+'" height="'+object_height+'" param="noparam"></object>';
1048
1049 optionsbuttons = {}
1050 if (mode == 'image' && showOriginalSizeButton)
1051 {
1052 optionsbuttons = {
1053 "<?php echo dol_escape_js($langs->transnoentitiesnoconv("OriginalSize")); ?>": function() { console.log("Click on original size"); jQuery(".ui-dialog-content.ui-widget-content > object").css({ "max-height": "none" }); },
1054 "<?php echo dol_escape_js($langs->transnoentitiesnoconv("CloseWindow")); ?>": function() { $( this ).dialog( "close" ); }
1055 };
1056 }
1057
1058 $("#dialogforpopup").html(newElem);
1059
1060 $("#dialogforpopup").dialog({
1061 closeOnEscape: true,
1062 resizable: true,
1063 width: width,
1064 height: height,
1065 modal: true,
1066 title: title,
1067 buttons: optionsbuttons
1068 });
1069
1070 if (showOriginalSizeButton)
1071 {
1072 jQuery(".ui-dialog-content.ui-widget-content > object").css({ "max-height": "100%", "width": "auto", "margin-left": "auto", "margin-right": "auto", "display": "block" });
1073 }
1074 }
1075}
1076
1077/*
1078 * Provide a function to get an URL GET parameter in javascript
1079 *
1080 * @param name Name of parameter
1081 * @param valueifnotfound Value if not found
1082 * @return string Value
1083 */
1084function getParameterByName(name, valueifnotfound)
1085{
1086 name = name.replace(/[\[]/, "\\[").replace(/[\]]/, "\\]");
1087 var regex = new RegExp("[\\?&]" + name + "=([^&#]*)"),
1088 results = regex.exec(location.search);
1089 return results === null ? valueifnotfound : decodeURIComponent(results[1].replace(/\+/g, " "));
1090}
1091
1092
1093// Code in the public domain from https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/round
1094(function() {
1103 function decimalAdjust(type, value, exp) {
1104 // If the exp is undefined or zero...
1105 if (typeof exp === 'undefined' || +exp === 0) {
1106 return Math[type](value);
1107 }
1108 value = +value;
1109 exp = +exp;
1110 // If the value is not a number or the exp is not an integer...
1111 if (isNaN(value) || !(typeof exp === 'number' && exp % 1 === 0)) {
1112 return NaN;
1113 }
1114 // Shift
1115 value = value.toString().split('e');
1116 value = Math[type](+(value[0] + 'e' + (value[1] ? (+value[1] - exp) : -exp)));
1117 // Shift back
1118 value = value.toString().split('e');
1119 return +(value[0] + 'e' + (value[1] ? (+value[1] + exp) : exp));
1120 }
1121
1122 // Decimal round
1123 if (!Math.round10) {
1124 Math.round10 = function(value, exp) {
1125 return decimalAdjust('round', value, exp);
1126 };
1127 }
1128 // Decimal floor
1129 if (!Math.floor10) {
1130 Math.floor10 = function(value, exp) {
1131 return decimalAdjust('floor', value, exp);
1132 };
1133 }
1134 // Decimal ceil
1135 if (!Math.ceil10) {
1136 Math.ceil10 = function(value, exp) {
1137 return decimalAdjust('ceil', value, exp);
1138 };
1139 }
1140})();
1141
1142// Another solution, easier, to build a javascript rounding function
1143function dolroundjs(number, decimals) { return +(Math.round(number + "e+" + decimals) + "e-" + decimals); }
1144
1162function pricejs(amount, mode = 'MT', currency_code = '', force_locale = '') {
1163 var main_max_dec_shown = <?php echo (int) str_replace('.', '', getDolGlobalInt('MAIN_MAX_DECIMALS_SHOWN')); ?>;
1164 var main_rounding_unit = <?php echo (int) getDolGlobalInt('MAIN_MAX_DECIMALS_UNIT'); ?>;
1165 var main_rounding_tot = <?php echo (int) getDolGlobalInt('MAIN_MAX_DECIMALS_TOT'); ?>;
1166 var main_decimal_separator = <?php echo json_encode($dec) ?>;
1167 var main_thousand_separator = <?php echo json_encode($thousand) ?>;
1168 var locale_code = force_locale || <?php echo json_encode($langs->defaultlang) ?>;
1169 var amountAsLocalizedString;
1170 var useIntl = Boolean(Intl && Intl.NumberFormat);
1171 var nDigits;
1172 if (currency_code === 'auto') currency_code = <?php echo json_encode($conf->currency) ?>;
1173
1174 if (mode === 'MU') nDigits = main_rounding_unit;
1175 else if (mode === 'MT') nDigits = main_rounding_tot;
1176 else return 'Bad value for parameter mode';
1177
1178 if (useIntl) {
1179 // simple version: let the browser decide how to format the number using the provided language / currency
1180 // parameters
1181 var formattingOptions = {
1182 minimumFractionDigits: nDigits,
1183 maximumFractionDigits: nDigits
1184 };
1185 if (currency_code) {
1186 formattingOptions['style'] = 'currency';
1187 formattingOptions['currency'] = currency_code;
1188 }
1189 return Intl.NumberFormat(locale_code.replace('_', '-'), formattingOptions).format(amount);
1190 }
1191
1192 // No Intl -> attempt to format the number in a way similar to Dolibarr PHP's `price()` function
1193 amountAsLocalizedString = amount.toFixed(nDigits).replace(
1194 /((?!^)(?:\d{3})*)(?:\.(\d+))?$/,
1195 (fullMatch, digitsByThree, decimals) =>
1196 digitsByThree.replace(
1197 /\d{3}/g,
1198 (groupOfThree) => main_thousand_separator + groupOfThree
1199 ) + (decimals !== undefined ? main_decimal_separator + decimals : '')
1200 ).replace(/ /, ' ');
1201 if (!currency_code) return amountAsLocalizedString;
1202
1203 // print with currency
1204 var currency_symbol = currency_code;
1205
1206 // codes of languages / currencies where the symbol must be placed before the amount
1207 var currencyBeforeAmountCodes = {
1208 currency: ['AUD', 'CAD', 'CNY', 'COP', 'CLP', 'GBP', 'HKD', 'MXN', 'PEN', 'USD'],
1209 language: ['nl_NL']
1210 };
1211
1212 if (currencyCache[currency_code]
1213 && currencyCache[currency_code]['unicode']
1214 && currencyCache[currency_code]['unicode'].length) {
1215 currency_symbol = currencyCache[currency_code]['unicode'].reduce(function (res, cur) {return res + cur}, '');
1216 }
1217
1218 if (currencyBeforeAmountCodes.currency.indexOf(currency_code) >= 0
1219 || currencyBeforeAmountCodes.language.indexOf(locale_code)) {
1220 // if we use a language or a currency where the symbol is placed before the amount
1221 return currency_symbol + amountAsLocalizedString;
1222 }
1223
1224 // by default: currency symbol after the amount
1225 return amountAsLocalizedString + ' ' + currency_symbol;
1226}
1227
1235function price2numjs(amount) {
1236 if (amount == '') return '';
1237
1238 var dec = <?php echo json_encode($dec) ?>;
1239 var thousand = <?php echo json_encode($thousand) ?>;
1240
1241 var main_max_dec_shown = <?php echo (int) str_replace('.', '', getDolGlobalInt('MAIN_MAX_DECIMALS_SHOWN')); ?>;
1242 var main_rounding_unit = <?php echo (int) getDolGlobalInt('MAIN_MAX_DECIMALS_UNIT'); ?>;
1243 var main_rounding_tot = <?php echo (int) getDolGlobalInt('MAIN_MAX_DECIMALS_TOT'); ?>;
1244
1245 var amount = amount.toString();
1246
1247 // rounding for unit price
1248 var rounding = main_rounding_unit;
1249 var pos = amount.indexOf(dec);
1250 var decpart = '';
1251 if (pos >= 0) {
1252 decpart = amount.substring(pos + 1).replace('/0+$/i', ''); // Remove 0 for decimal part
1253 }
1254 var nbdec = decpart.length;
1255 if (nbdec > rounding) {
1256 rounding = nbdec;
1257 }
1258 // If rounding higher than max shown
1259 if (rounding > main_max_dec_shown) rounding = main_max_dec_shown;
1260 if (thousand != ',' && thousand != '.') amount = amount.replace(',', '.');
1261 amount = amount.replace(' ', ''); // To avoid spaces
1262 amount = amount.replace(thousand, ''); // Replace of thousand before replace of dec to avoid pb if thousand is .
1263 amount = amount.replace(dec, '.');
1264
1265 //console.log("amount before="+amount+" rouding="+rounding)
1266 var res = Math.round10(amount, - rounding);
1267 // Other solution is
1268 // var res = dolroundjs(amount, rounding)
1269
1270 console.log("price2numjs text="+amount+" return="+res);
1271
1272 return res;
1273}
1274
1275
1276<?php
1277if (empty($conf->global->MAIN_DISABLE_JQUERY_JNOTIFY) && !defined('DISABLE_JQUERY_JNOTIFY')) {
1278 ?>
1279// Defined properties for JNotify
1280$(document).ready(function() {
1281 if (typeof $.jnotify == 'function') {
1282 $.jnotify.setup({
1283 delay: 3000 // the default time to show each notification (in milliseconds)
1284 , sticky: false // determines if the message should be considered "sticky" (user must manually close notification)
1285 , closeLabel: "&times;" // the HTML to use for the "Close" link
1286 , showClose: true // determines if the "Close" link should be shown if notification is also sticky
1287 , fadeSpeed: 1000 // the speed to fade messages out (in milliseconds)
1288 , slideSpeed: 250 // the speed used to slide messages out (in milliseconds)
1289 , classContainer: "jnotify-container"
1290 , classNotification: "jnotify-notification"
1291 , classBackground: "jnotify-background"
1292 , classClose: "jnotify-close"
1293 , classMessage: "jnotify-message"
1294 , init: null // callback that occurs when the main jnotify container is created
1295 , create: null // callback that occurs when when the note is created (occurs just before appearing in DOM)
1296 , beforeRemove: null // callback that occurs when before the notification starts to fade away
1297 });
1298 }
1299});
1300<?php } ?>
1301
1302
1303jQuery(document).ready(function() {
1304 // Force to hide menus when page is inside an iFrame so we can show any page into a dialog popup
1305 if (window.location && window.location.pathname.indexOf("externalsite/frametop.php") == -1 && window.location !== window.parent.location ) {
1306 console.log("Page is detected to be into an iframe, we hide by CSS the menus");
1307 // The page is in an iframe
1308 jQuery(".side-nav-vert, .side-nav, .websitebar").hide();
1309 jQuery(".id-container").css('width', '100%');
1310
1311 }
1312
1313 // Code to set tooltip on search field
1314 jQuery('table.liste tr.liste_titre_filter td.liste_titre input[name^="search"][type=text]:not(".maxwidthdate")').attr('title', '<?php echo dol_escape_js($langs->transnoentities("SearchSyntaxTooltipForStringOrNum")) ?>');
1315});
1316
1317
1318jQuery(document).ready(function() {
1319 jQuery(".butAction.dropdown-toggle").on("click", function(event) {
1320 console.log("Click on .butAction.dropdown-toggle");
1321 var parentholder = jQuery(".butAction.dropdown-toggle").closest(".dropdown");
1322 var offset = parentholder.offset();
1323 var widthdocument = $(document).width();
1324 var left = offset.left;
1325 var right = widthdocument - offset.left - parentholder.width();
1326 var widthpopup = parentholder.children(".dropdown-content").width();
1327 console.log("left="+left+" right="+right+" width="+widthpopup+" widthdocument="+widthdocument);
1328 if (widthpopup + right >= widthdocument) {
1329 right = 10;
1330 }
1331 parentholder.toggleClass("open");
1332 parentholder.children(".dropdown-content").css({"right": right+"px", "left": "auto"});
1333 });
1334});
1335
1336
1337<?php
1338if (empty($conf->global->MAIN_DISABLE_SELECT2_FOCUS_PROTECTION) && !defined('DISABLE_SELECT2_FOCUS_PROTECTION')) {
1339 ?>
1340/*
1341 * Hacky fix for a bug in select2 with jQuery 3.6.4's new nested-focus "protection"
1342 * This fix needs to click a second time when clicking into a combo with ajax (see Test4d and Test5a in test_forms.php
1343 * see: https://github.com/select2/select2/issues/5993
1344 * see: https://github.com/jquery/jquery/issues/4382
1345 *
1346 * TODO: Recheck with the select2 GH issue and remove once this is fixed on their side
1347 */
1348$(document).on('select2:open', (e) => {
1349 console.log("Execute the focus (click on combo or use space when on component");
1350 const target = $(e.target);
1351 if (target && target.length) {
1352 let id = target[0].id || target[0].name;
1353 if (id.substr(-2) == "[]") id = id.substr(0,id.length-2);
1354 document.querySelector('input[aria-controls*='+id+']').focus();
1355 }
1356});
1357 <?php
1358}
1359?>
1360
1361
1362// End of lib_head.js.php
getDolGlobalInt($key, $default=0)
Return dolibarr global constant int value.
dol_escape_js($stringtoescape, $mode=0, $noescapebackslashn=0)
Returns text escaped for inclusion into javascript code.
if(empty($user->rights->takepos->run) &&!defined('INCLUDE_PHONEPAGE_FROM_PUBLIC_PAGE')) if((getDolGlobalString( 'TAKEPOS_PHONE_BASIC_LAYOUT')==1 &&$conf->browser->layout=='phone')||defined( 'INCLUDE_PHONEPAGE_FROM_PUBLIC_PAGE')) fail($message)
Abort invoice creationg with a given error message.
Definition invoice.php:88
getParameterByName(name, valueifnotfound)
copyToClipboard(text, text2)
Function to output a dialog box for copy/paste.
document_preview(file, type, title)
Function show document preview.
pricejs(amount, mode='MT', currency_code='', force_locale='')
Function similar to PHP price()
newpopup(url, title)
Show a popup HTML page.
price2numjs(amount)
Function similar to PHP price2num()
if(!defined( 'NOREQUIREMENU')) if(!empty(GETPOST('seteventmessages', 'alpha'))) if(!function_exists("llxHeader")) top_httphead($contenttype='text/html', $forcenocache=0)
Show HTTP header.
ui dialog ui datepicker calendar ui widget content ui state ui datepicker calendar ui widget header ui state ui datepicker calendar ui button
0 = Do not include form tag and submit button -1 = Do not include form tag but include submit button
if(preg_match('/crypted:/i', $dolibarr_main_db_pass)||!empty($dolibarr_main_db_encrypted_pass)) $conf db type
Definition repair.php:120
$conf db name
Only used if Module[ID]Name translation string is not found.
Definition repair.php:123