lib_head.js.php 42 KB

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