lib_head.js.php 36 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155
  1. <?php
  2. /* Copyright (C) 2005-2014 Laurent Destailleur <eldy@users.sourceforge.net>
  3. * Copyright (C) 2005-2014 Regis Houssin <regis.houssin@capnetworks.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 <http://www.gnu.org/licenses/>.
  18. * or see http://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. */
  24. //if (! defined('NOREQUIREUSER')) define('NOREQUIREUSER','1'); // Not disabled cause need to load personalized language
  25. //if (! defined('NOREQUIREDB')) define('NOREQUIREDB','1');
  26. if (! defined('NOREQUIRESOC')) define('NOREQUIRESOC','1');
  27. //if (! defined('NOREQUIRETRAN')) define('NOREQUIRETRAN','1'); // Not disabled cause need to do translations
  28. if (! defined('NOCSRFCHECK')) define('NOCSRFCHECK',1);
  29. if (! defined('NOTOKENRENEWAL')) define('NOTOKENRENEWAL',1);
  30. if (! defined('NOLOGIN')) define('NOLOGIN',1);
  31. if (! defined('NOREQUIREMENU')) define('NOREQUIREMENU',1);
  32. if (! defined('NOREQUIREHTML')) define('NOREQUIREHTML',1);
  33. if (! defined('NOREQUIREAJAX')) define('NOREQUIREAJAX','1');
  34. session_cache_limiter(FALSE);
  35. require_once '../../main.inc.php';
  36. // Define javascript type
  37. top_httphead('text/javascript; charset=UTF-8');
  38. // Important: Following code is to avoid page request by browser and PHP CPU at each Dolibarr page access.
  39. if (empty($dolibarr_nocache)) header('Cache-Control: max-age=3600, public, must-revalidate');
  40. else header('Cache-Control: no-cache');
  41. ?>
  42. /*
  43. * =================================================================
  44. * Purpose:
  45. * Pour la saisie des dates par calendrier Input: base "/theme/eldy" dateFieldID
  46. * "dateo" Nom du champ format "dd/MM/yyyy" Format issu de Dolibarr de
  47. * SimpleDateFormat a utiliser pour retour
  48. * ==================================================================
  49. */
  50. function showDP(base,dateFieldID,format,codelang)
  51. {
  52. // check to see if another box is already showing
  53. var alreadybox=getObjectFromID("DPCancel");
  54. if (alreadybox) closeDPBox(); // This erase value of showDP.datefieldID
  55. // alert("showDP "+codelang);
  56. showDP.datefieldID=dateFieldID; // Must be after the close
  57. var dateField=getObjectFromID(dateFieldID);
  58. // get positioning
  59. var thetop=getTop(dateField)+dateField.offsetHeight;
  60. // var xxx=getObjectFromID('bottompage');
  61. // alert(xxx.style.pixelTop);
  62. // alert(document.body.clientHeight);
  63. // alert(document.body.style.offsetTop);
  64. // alert(thetop);
  65. // alert(window.innerHeight);
  66. if (thetop+160 > window.innerHeight)
  67. thetop=thetop-160-20;
  68. var theleft=getLeft(dateField);
  69. if (theleft+140 > window.innerWidth)
  70. theleft= theleft-140+dateField.offsetWidth-15;
  71. showDP.box=document.createElement("div");
  72. showDP.box.className="bodyline";
  73. showDP.box.style.display="block";
  74. showDP.box.style.zIndex="1000";
  75. showDP.box.style.position="absolute";
  76. showDP.box.style.top=thetop + "px";
  77. showDP.box.style.left=theleft + "px";
  78. if (dateField.value) // Si il y avait valeur initiale dans champ
  79. {
  80. selDate=getDateFromFormat(dateField.value,format);
  81. if (selDate)
  82. {
  83. // Success to parse value in field according to format
  84. year=selDate.getFullYear();
  85. month=selDate.getMonth()+1;
  86. day=selDate.getDate();
  87. datetime=selDate.getTime();
  88. ymd=formatDate(selDate,'yyyyMMdd');
  89. }
  90. else
  91. {
  92. // Failed to parse value in field according to format
  93. selDate=new Date();
  94. year=selDate.getFullYear();
  95. month=selDate.getUTCMonth()+1;
  96. day=selDate.getDate();
  97. datetime=selDate.getTime();
  98. ymd=formatDate(selDate,'yyyyMMdd');
  99. }
  100. }
  101. else
  102. {
  103. selDate=new Date();
  104. year=selDate.getFullYear();
  105. month=selDate.getUTCMonth()+1;
  106. day=selDate.getDate();
  107. datetime=selDate.getTime();
  108. ymd=formatDate(selDate,'yyyyMMdd');
  109. }
  110. loadMonth(base,month,year,ymd,codelang);
  111. hideSelectBoxes();
  112. document.body.appendChild(showDP.box);
  113. }
  114. function resetDP(base,dateFieldID,format,codelang)
  115. {
  116. var dateField=getObjectFromID(dateFieldID);
  117. dateField.value = formatDate(new Date(), format);
  118. dpChangeDay(dateFieldID,format);
  119. var alreadybox=getObjectFromID("DPCancel");
  120. if (alreadybox) showDP(base,dateFieldID,format,codelang);
  121. }
  122. function loadMonth(base,month,year,ymd,codelang)
  123. {
  124. /* showDP.box.innerHTML="Loading..."; */
  125. // alert(codelang);
  126. var theURL=base+"datepicker.php?cm=shw&lang="+codelang;
  127. theURL+="&m="+encodeURIComponent(month);
  128. theURL+="&y="+encodeURIComponent(year);
  129. if (selDate)
  130. {
  131. theURL+="&sd="+ymd;
  132. }
  133. var req=null;
  134. req=loadXMLDoc(theURL,null,false);
  135. if (req.responseText == '') alert('Failed to get URL '.theURL);
  136. // alert(theURL+' - '+req.responseText); // L'url doit avoir la meme racine
  137. // que la pages et elements sinon pb de securite.
  138. showDP.box.innerHTML=req.responseText;
  139. }
  140. function closeDPBox()
  141. {
  142. document.body.removeChild(showDP.box);
  143. displaySelectBoxes();
  144. showDP.box=null;
  145. showDP.datefieldID=null;
  146. }
  147. function dpChangeDay(dateFieldID,format)
  148. {
  149. showDP.datefieldID=dateFieldID;
  150. var thefield=getObjectFromID(showDP.datefieldID);
  151. var thefieldday=getObjectFromID(showDP.datefieldID+"day");
  152. var thefieldmonth=getObjectFromID(showDP.datefieldID+"month");
  153. var thefieldyear=getObjectFromID(showDP.datefieldID+"year");
  154. var date=getDateFromFormat(thefield.value,format);
  155. if (date)
  156. {
  157. thefieldday.value=date.getDate();
  158. if(thefieldday.onchange) thefieldday.onchange.call(thefieldday);
  159. thefieldmonth.value=date.getMonth()+1;
  160. if(thefieldmonth.onchange) thefieldmonth.onchange.call(thefieldmonth);
  161. thefieldyear.value=date.getFullYear();
  162. if(thefieldyear.onchange) thefieldyear.onchange.call(thefieldyear);
  163. }
  164. else
  165. {
  166. thefieldday.value='';
  167. if(thefieldday.onchange) thefieldday.onchange.call(thefieldday);
  168. thefieldmonth.value='';
  169. if(thefieldmonth.onchange) thefieldmonth.onchange.call(thefieldmonth);
  170. thefieldyear.value='';
  171. if(thefieldyear.onchange) thefieldyear.onchange.call(thefieldyear);
  172. }
  173. }
  174. function dpClickDay(year,month,day,format)
  175. {
  176. var thefield=getObjectFromID(showDP.datefieldID);
  177. var thefieldday=getObjectFromID(showDP.datefieldID+"day");
  178. var thefieldmonth=getObjectFromID(showDP.datefieldID+"month");
  179. var thefieldyear=getObjectFromID(showDP.datefieldID+"year");
  180. var dt = new Date(year, month-1, day);
  181. thefield.value=formatDate(dt,format);
  182. if(thefield.onchange) thefield.onchange.call(thefield);
  183. thefieldday.value=day;
  184. if(thefieldday.onchange) thefieldday.onchange.call(thefieldday);
  185. thefieldmonth.value=month;
  186. if(thefieldmonth.onchange) thefieldmonth.onchange.call(thefieldmonth);
  187. thefieldyear.value=year;
  188. if(thefieldyear.onchange) thefieldyear.onchange.call(thefieldyear);
  189. closeDPBox();
  190. }
  191. function dpHighlightDay(year,month,day,months){
  192. var displayinfo=getObjectFromID("dpExp");
  193. displayinfo.innerHTML=months[month-1]+" "+day+", "+year;
  194. }
  195. // Returns an object given an id
  196. function getObjectFromID(id){
  197. var theObject;
  198. if(document.getElementById)
  199. theObject=document.getElementById(id);
  200. else
  201. theObject=document.all[id];
  202. return theObject;
  203. }
  204. // This Function returns the top position of an object
  205. function getTop(theitem){
  206. var offsetTrail = theitem;
  207. var offsetTop = 0;
  208. while (offsetTrail) {
  209. offsetTop += offsetTrail.offsetTop;
  210. offsetTrail = offsetTrail.offsetParent;
  211. }
  212. if (navigator.userAgent.indexOf("Mac") != -1 && typeof document.body.leftMargin != "undefined")
  213. offsetTop += document.body.TopMargin;
  214. return offsetTop;
  215. }
  216. // This Function returns the left position of an object
  217. function getLeft(theitem){
  218. var offsetTrail = theitem;
  219. var offsetLeft = 0;
  220. while (offsetTrail) {
  221. offsetLeft += offsetTrail.offsetLeft;
  222. offsetTrail = offsetTrail.offsetParent;
  223. }
  224. if (navigator.userAgent.indexOf("Mac") != -1 && typeof document.body.leftMargin != "undefined")
  225. offsetLeft += document.body.leftMargin;
  226. return offsetLeft;
  227. }
  228. // Create XMLHttpRequest object and load url
  229. // Used by calendar or other ajax processes
  230. // Return req built or false if error
  231. function loadXMLDoc(url,readyStateFunction,async)
  232. {
  233. // req must be defined by caller with
  234. // var req = false;
  235. // branch for native XMLHttpRequest object (Mozilla, Safari...)
  236. if (window.XMLHttpRequest)
  237. {
  238. req = new XMLHttpRequest();
  239. // if (req.overrideMimeType) {
  240. // req.overrideMimeType('text/xml');
  241. // }
  242. }
  243. // branch for IE/Windows ActiveX version
  244. else if (window.ActiveXObject)
  245. {
  246. try
  247. {
  248. req = new ActiveXObject("Msxml2.XMLHTTP");
  249. }
  250. catch (e)
  251. {
  252. try {
  253. req = new ActiveXObject("Microsoft.XMLHTTP");
  254. } catch (e) {}
  255. }
  256. }
  257. // If XMLHttpRequestObject req is ok, call URL
  258. if (! req)
  259. {
  260. alert('Cannot create XMLHTTP instance');
  261. return false;
  262. }
  263. if (readyStateFunction) req.onreadystatechange = readyStateFunction;
  264. // Exemple of function for readyStateFuncyion:
  265. // function ()
  266. // {
  267. // if ( (req.readyState == 4) && (req.status == 200) ) {
  268. // if (req.responseText == 1) { newStatus = 'AAA'; }
  269. // if (req.responseText == 0) { newStatus = 'BBB'; }
  270. // if (currentStatus != newStatus) {
  271. // if (newStatus == "AAA") { obj.innerHTML = 'AAA'; }
  272. // else { obj.innerHTML = 'BBB'; }
  273. // currentStatus = newStatus;
  274. // }
  275. // }
  276. // }
  277. req.open("GET", url, async);
  278. req.send(null);
  279. return req;
  280. }
  281. /* To hide/show select Boxes with IE6 (and only IE6 because IE6 has a bug and
  282. * not put popup completely on the front)
  283. * Used only bu popup calendar
  284. */
  285. function hideSelectBoxes() {
  286. var brsVersion = parseInt(window.navigator.appVersion.charAt(0), 10);
  287. if (brsVersion <= 6 && window.navigator.userAgent.indexOf("MSIE 6") > -1)
  288. {
  289. for(var i = 0; i < document.all.length; i++)
  290. {
  291. if(document.all[i].tagName)
  292. if(document.all[i].tagName == "SELECT")
  293. document.all[i].style.visibility="hidden";
  294. }
  295. }
  296. }
  297. /* To hide/show select Boxes with IE6 (and only IE6 because IE6 has a bug and
  298. * not put popup completely on the front)
  299. * Used only bu popup calendar
  300. */
  301. function displaySelectBoxes() {
  302. var brsVersion = parseInt(window.navigator.appVersion.charAt(0), 10);
  303. if (brsVersion <= 6 && window.navigator.userAgent.indexOf("MSIE 6") > -1)
  304. {
  305. for(var i = 0; i < document.all.length; i++)
  306. {
  307. if(document.all[i].tagName)
  308. if(document.all[i].tagName == "SELECT")
  309. document.all[i].style.visibility="visible";
  310. }
  311. }
  312. }
  313. /*
  314. * =================================================================
  315. * Function:
  316. * formatDate (javascript object Date(), format) Purpose: Returns a date in the
  317. * output format specified. The format string can use the following tags: Field |
  318. * Tags -------------+------------------------------- Year | yyyy (4 digits), yy
  319. * (2 digits) Month | MM (2 digits) Day of Month | dd (2 digits) Hour (1-12) |
  320. * hh (2 digits) Hour (0-23) | HH (2 digits) Minute | mm (2 digits) Second | ss
  321. * (2 digits) Author: Laurent Destailleur Author: Matelli (see
  322. * http://matelli.fr/showcases/patchs-dolibarr/update-date-input-in-action-form.html)
  323. * Licence: GPL
  324. * ==================================================================
  325. */
  326. function formatDate(date,format)
  327. {
  328. // alert('formatDate date='+date+' format='+format);
  329. // Force parametres en chaine
  330. format=format+"";
  331. var result="";
  332. var year=date.getYear()+""; if (year.length < 4) { year=""+(year-0+1900); }
  333. var month=date.getMonth()+1;
  334. var day=date.getDate();
  335. var hour=date.getHours();
  336. var minute=date.getMinutes();
  337. var seconde=date.getSeconds();
  338. var i=0;
  339. while (i < format.length)
  340. {
  341. c=format.charAt(i); // Recupere char du format
  342. substr="";
  343. j=i;
  344. while ((format.charAt(j)==c) && (j < format.length)) // Recupere char successif identiques
  345. {
  346. substr += format.charAt(j++);
  347. }
  348. // alert('substr='+substr);
  349. if (substr == 'yyyy') { result=result+year; }
  350. else if (substr == 'yy') { result=result+year.substring(2,4); }
  351. else if (substr == 'M') { result=result+month; }
  352. else if (substr == 'MM') { result=result+(month<1||month>9?"":"0")+month; }
  353. else if (substr == 'd') { result=result+day; }
  354. else if (substr == 'dd') { result=result+(day<1||day>9?"":"0")+day; }
  355. else if (substr == 'hh') { if (hour > 12) hour-=12; result=result+(hour<0||hour>9?"":"0")+hour; }
  356. else if (substr == 'HH') { result=result+(hour<0||hour>9?"":"0")+hour; }
  357. else if (substr == 'mm') { result=result+(minute<0||minute>9?"":"0")+minute; }
  358. else if (substr == 'ss') { result=result+(seconde<0||seconde>9?"":"0")+seconde; }
  359. else { result=result+substr; }
  360. i+=substr.length;
  361. }
  362. // alert(result);
  363. return result;
  364. }
  365. /*
  366. * =================================================================
  367. * Function:
  368. * getDateFromFormat(date_string, format_string) Purpose: This function takes a
  369. * date string and a format string. It parses the date string with format and it
  370. * returns the date as a javascript Date() object. If date does not match
  371. * format, it returns 0. The format string can use the following tags:
  372. * Field | Tags
  373. * -------------+-----------------------------------
  374. * Year | yyyy (4 digits), yy (2 digits)
  375. * Month | MM (2 digits)
  376. * Day of Month | dd (2 digits)
  377. * Hour (1-12) | hh (2 digits)
  378. * Hour (0-23) | HH (2 digits)
  379. * Minute | mm (2 digits)
  380. * Second | ss (2 digits)
  381. * Author: Laurent Destailleur
  382. * Licence: GPL
  383. * ==================================================================
  384. */
  385. function getDateFromFormat(val,format)
  386. {
  387. // alert('getDateFromFormat val='+val+' format='+format);
  388. // Force parametres en chaine
  389. val=val+"";
  390. format=format+"";
  391. if (val == '') return 0;
  392. var now=new Date();
  393. var year=now.getYear(); if (year.length < 4) { year=""+(year-0+1900); }
  394. var month=now.getMonth()+1;
  395. var day=now.getDate();
  396. var hour=now.getHours();
  397. var minute=now.getMinutes();
  398. var seconde=now.getSeconds();
  399. var i=0;
  400. var d=0; // -d- follows the date string while -i- follows the format
  401. // string
  402. while (i < format.length)
  403. {
  404. c=format.charAt(i); // Recupere char du format
  405. substr="";
  406. j=i;
  407. while ((format.charAt(j)==c) && (j < format.length)) // Recupere char
  408. // successif
  409. // identiques
  410. {
  411. substr += format.charAt(j++);
  412. }
  413. // alert('substr='+substr);
  414. if (substr == "yyyy") year=getIntegerInString(val,d,4,4);
  415. if (substr == "yy") year=""+(getIntegerInString(val,d,2,2)-0+1900);
  416. if (substr == "MM" ||substr == "M")
  417. {
  418. month=getIntegerInString(val,d,1,2);
  419. d -= 2- month.length;
  420. }
  421. if (substr == "dd")
  422. {
  423. day=getIntegerInString(val,d,1,2);
  424. d -= 2- day.length;
  425. }
  426. if (substr == "HH" ||substr == "hh" )
  427. {
  428. hour=getIntegerInString(val,d,1,2);
  429. d -= 2- hour.length;
  430. }
  431. if (substr == "mm"){
  432. minute=getIntegerInString(val,d,1,2);
  433. d -= 2- minute.length;
  434. }
  435. if (substr == "ss")
  436. {
  437. seconde=getIntegerInString(val,d,1,2);
  438. d -= 2- seconde.length;
  439. }
  440. i+=substr.length;
  441. d+=substr.length;
  442. }
  443. // Check if format param are ok
  444. if (year==null||year<1) { return 0; }
  445. if (month==null||(month<1)||(month>12)) { return 0; }
  446. if (day==null||(day<1)||(day>31)) { return 0; }
  447. if (hour==null||(hour<0)||(hour>24)) { return 0; }
  448. if (minute==null||(minute<0)||(minute>60)) { return 0; }
  449. if (seconde==null||(seconde<0)||(seconde>60)) { return 0; }
  450. // alert(year+' '+month+' '+day+' '+hour+' '+minute+' '+seconde);
  451. return new Date(year,month-1,day,hour,minute,seconde);
  452. }
  453. /*
  454. * =================================================================
  455. * Function:
  456. * stringIsInteger(string)
  457. * Purpose: Return true if string is an integer
  458. * ==================================================================
  459. */
  460. function stringIsInteger(str)
  461. {
  462. var digits="1234567890";
  463. for (var i=0; i < str.length; i++)
  464. {
  465. if (digits.indexOf(str.charAt(i))==-1)
  466. {
  467. return false;
  468. }
  469. }
  470. return true;
  471. }
  472. /*
  473. * =================================================================
  474. * Function:
  475. * getIntegerInString(string,pos,minlength,maxlength)
  476. * Purpose: Return part of string from position i that is integer
  477. * ==================================================================
  478. */
  479. function getIntegerInString(str,i,minlength,maxlength)
  480. {
  481. for (var x=maxlength; x>=minlength; x--)
  482. {
  483. var substr=str.substring(i,i+x);
  484. if (substr.length < minlength) { return null; }
  485. if (stringIsInteger(substr)) { return substr; }
  486. }
  487. return null;
  488. }
  489. /*
  490. * =================================================================
  491. * Purpose:
  492. * Clean string to have it url encoded
  493. * Input: s
  494. * Author: Laurent Destailleur
  495. * Licence: GPL
  496. * ==================================================================
  497. */
  498. function urlencode(s) {
  499. news=s;
  500. news=news.replace(/\+/gi,'%2B');
  501. news=news.replace(/&/gi,'%26');
  502. return news;
  503. }
  504. /*
  505. * =================================================================
  506. * Purpose:
  507. * Applique un delai avant execution. Used for autocompletion of companies.
  508. * Input: funct, delay
  509. * Author: Regis Houssin
  510. * Licence: GPL
  511. * ==================================================================
  512. */
  513. function ac_delay(funct,delay) {
  514. // delay before start of action
  515. setTimeout(funct,delay);
  516. }
  517. /*
  518. * =================================================================
  519. * Purpose:
  520. * Clean values of a "Sortable.serialize". Used by drag and drop.
  521. * Input: expr
  522. * Author: Regis Houssin
  523. * Licence: GPL
  524. * ==================================================================
  525. */
  526. function cleanSerialize(expr) {
  527. if (typeof(expr) != 'string') return '';
  528. var reg = new RegExp("(&)", "g");
  529. var reg2 = new RegExp("[^A-Z0-9,]", "g");
  530. var liste1 = expr.replace(reg, ",");
  531. return liste1.replace(reg2, "");
  532. }
  533. /*
  534. * =================================================================
  535. * Purpose: Display a temporary message in input text fields (For showing help message on
  536. * input field).
  537. * Input: fieldId
  538. * Input: message
  539. * Author: Regis Houssin
  540. * Licence: GPL
  541. * ==================================================================
  542. */
  543. function displayMessage(fieldId,message) {
  544. var textbox = document.getElementById(fieldId);
  545. if (textbox.value == '') {
  546. textbox.style.color = 'grey';
  547. textbox.value = message;
  548. }
  549. }
  550. /*
  551. * =================================================================
  552. * Purpose: Hide a temporary message in input text fields (For showing help message on
  553. * input field).
  554. * Input: fiedId
  555. * Input: message
  556. * Author: Regis Houssin
  557. * Licence: GPL
  558. * ==================================================================
  559. */
  560. function hideMessage(fieldId,message) {
  561. var textbox = document.getElementById(fieldId);
  562. textbox.style.color = 'black';
  563. if (textbox.value == message) textbox.value = '';
  564. }
  565. /*
  566. * Used by button to set on/off
  567. *
  568. * @param string url Url
  569. * @param string code Code
  570. * @param string intput Input
  571. * @param int entity Entity
  572. * @param int strict Strict
  573. */
  574. function setConstant(url, code, input, entity, strict) {
  575. $.get( url, {
  576. action: "set",
  577. name: code,
  578. entity: entity
  579. },
  580. function() {
  581. $("#set_" + code).hide();
  582. $("#del_" + code).show();
  583. $.each(input, function(type, data) {
  584. // Enable another element
  585. if (type == "disabled" && strict != 1) {
  586. $.each(data, function(key, value) {
  587. var newvalue=((value.search("^#") < 0 && value.search("^\.") < 0) ? "#" : "") + value;
  588. $(newvalue).removeAttr("disabled");
  589. if ($(newvalue).hasClass("butActionRefused") == true) {
  590. $(newvalue).removeClass("butActionRefused");
  591. $(newvalue).addClass("butAction");
  592. }
  593. });
  594. } else if (type == "enabled") {
  595. $.each(data, function(key, value) {
  596. var newvalue=((value.search("^#") < 0 && value.search("^\.") < 0) ? "#" : "") + value;
  597. if (strict == 1)
  598. $(newvalue).removeAttr("disabled");
  599. else
  600. $(newvalue).attr("disabled", true);
  601. if ($(newvalue).hasClass("butAction") == true) {
  602. $(newvalue).removeClass("butAction");
  603. $(newvalue).addClass("butActionRefused");
  604. }
  605. });
  606. // Show another element
  607. } else if (type == "showhide" || type == "show") {
  608. $.each(data, function(key, value) {
  609. var newvalue=((value.search("^#") < 0 && value.search("^\.") < 0) ? "#" : "") + value;
  610. $(newvalue).show();
  611. });
  612. // Set another constant
  613. } else if (type == "set") {
  614. $.each(data, function(key, value) {
  615. $("#set_" + key).hide();
  616. $("#del_" + key).show();
  617. $.get( url, {
  618. action: "set",
  619. name: key,
  620. value: value,
  621. entity: entity
  622. });
  623. });
  624. }
  625. });
  626. });
  627. }
  628. /*
  629. * Used by button to set on/off
  630. *
  631. * @param string url Url
  632. * @param string code Code
  633. * @param string intput Input
  634. * @param int entity Entity
  635. * @param int strict Strict
  636. */
  637. function delConstant(url, code, input, entity, strict) {
  638. $.get( url, {
  639. action: "del",
  640. name: code,
  641. entity: entity
  642. },
  643. function() {
  644. $("#del_" + code).hide();
  645. $("#set_" + code).show();
  646. $.each(input, function(type, data) {
  647. // Disable another element
  648. if (type == "disabled") {
  649. $.each(data, function(key, value) {
  650. var newvalue=((value.search("^#") < 0 && value.search("^\.") < 0) ? "#" : "") + value;
  651. $(newvalue).attr("disabled", true);
  652. if ($(newvalue).hasClass("butAction") == true) {
  653. $(newvalue).removeClass("butAction");
  654. $(newvalue).addClass("butActionRefused");
  655. }
  656. });
  657. } else if (type == "enabled" && strict != 1) {
  658. $.each(data, function(key, value) {
  659. var newvalue=((value.search("^#") < 0 && value.search("^\.") < 0) ? "#" : "") + value;
  660. $(newvalue).removeAttr("disabled");
  661. if ($(newvalue).hasClass("butActionRefused") == true) {
  662. $(newvalue).removeClass("butActionRefused");
  663. $(newvalue).addClass("butAction");
  664. }
  665. });
  666. // Hide another element
  667. } else if (type == "showhide" || type == "hide") {
  668. $.each(data, function(key, value) {
  669. var newvalue=((value.search("^#") < 0 && value.search("^\.") < 0) ? "#" : "") + value;
  670. $(newvalue).hide();
  671. });
  672. // Delete another constant
  673. } else if (type == "del") {
  674. $.each(data, function(key, value) {
  675. $("#del_" + value).hide();
  676. $("#set_" + value).show();
  677. $.get( url, {
  678. action: "del",
  679. name: value,
  680. entity: entity
  681. });
  682. });
  683. }
  684. });
  685. });
  686. }
  687. /*
  688. * Used by button to set on/off
  689. *
  690. * @param string action Action
  691. * @param string url Url
  692. * @param string code Code
  693. * @param string intput Input
  694. * @param string box Box
  695. * @param int entity Entity
  696. * @param int yesButton yesButton
  697. * @param int noButton noButton
  698. * @param int strict Strict
  699. */
  700. function confirmConstantAction(action, url, code, input, box, entity, yesButton, noButton, strict) {
  701. var boxConfirm = box;
  702. $("#confirm_" + code)
  703. .attr("title", boxConfirm.title)
  704. .html(boxConfirm.content)
  705. .dialog({
  706. resizable: false,
  707. height: 170,
  708. width: 500,
  709. modal: true,
  710. buttons: [
  711. {
  712. id : 'yesButton_' + code,
  713. text : yesButton,
  714. click : function() {
  715. if (action == "set") {
  716. setConstant(url, code, input, entity, strict);
  717. } else if (action == "del") {
  718. delConstant(url, code, input, entity, strict);
  719. }
  720. // Close dialog
  721. $(this).dialog("close");
  722. // Execute another method
  723. if (boxConfirm.method) {
  724. var fnName = boxConfirm.method;
  725. if (window.hasOwnProperty(fnName)) {
  726. window[fnName]();
  727. }
  728. }
  729. }
  730. },
  731. {
  732. id : 'noButton_' + code,
  733. text : noButton,
  734. click : function() {
  735. $(this).dialog("close");
  736. }
  737. }
  738. ]
  739. });
  740. // For information dialog box only, hide the noButton
  741. if (boxConfirm.info) {
  742. $("#noButton_" + code).button().hide();
  743. }
  744. }
  745. /*
  746. * =================================================================
  747. * This is to allow to transform all select box into ajax autocomplete box
  748. * with just one line:
  749. * $(function() { $( "#idofmylist" ).combobox(); });
  750. * Do not use it on large combo boxes
  751. * =================================================================
  752. */
  753. (function( $ ) {
  754. $.widget( "ui.combobox", {
  755. options: {
  756. minLengthToAutocomplete: 0
  757. },
  758. _create: function() {
  759. var savMinLengthToAutocomplete = this.options.minLengthToAutocomplete;
  760. var self = this,
  761. select = this.element.hide(),
  762. selected = select.children( ":selected" ),
  763. value = selected.val() ? selected.text() : "";
  764. var input = this.input = $( "<input>" )
  765. .insertAfter( select )
  766. .val( value )
  767. .attr('id', 'inputautocomplete'+select.attr('id'))
  768. .autocomplete({
  769. delay: 0,
  770. minLength: this.options.minLengthToAutocomplete,
  771. source: function( request, response ) {
  772. var matcher = new RegExp( $.ui.autocomplete.escapeRegex(request.term), "i" );
  773. response( select.children( "option:enabled" ).map(function() {
  774. var text = $( this ).text();
  775. if ( this.value && ( !request.term || matcher.test(text) ) )
  776. return {
  777. label: text.replace(
  778. new RegExp(
  779. "(?![^&;]+;)(?!<[^<>]*)(" +
  780. $.ui.autocomplete.escapeRegex(request.term) +
  781. ")(?![^<>]*>)(?![^&;]+;)", "gi"
  782. ), "<strong>$1</strong>" ),
  783. value: text,
  784. option: this
  785. };
  786. }) );
  787. },
  788. select: function( event, ui ) {
  789. ui.item.option.selected = true;
  790. self._trigger( "selected", event, {
  791. item: ui.item.option
  792. });
  793. },
  794. change: function( event, ui ) {
  795. if ( !ui.item ) {
  796. var matcher = new RegExp( "^" + $.ui.autocomplete.escapeRegex( $(this).val() ) + "$", "i" ),
  797. valid = false;
  798. select.children( "option" ).each(function() {
  799. if ( $( this ).text().match( matcher ) ) {
  800. this.selected = valid = true;
  801. return false;
  802. }
  803. });
  804. if ( !valid ) {
  805. // remove invalid value, as it didnt match anything
  806. $( this ).val( "" );
  807. select.val( "" );
  808. input.data("ui-autocomplete").term = "";
  809. return false;
  810. }
  811. }
  812. }
  813. })
  814. .addClass( "ui-widget ui-widget-content ui-corner-left dolibarrcombobox" );
  815. input.data("ui-autocomplete")._renderItem = function( ul, item ) {
  816. return $("<li>")
  817. .data( "ui-autocomplete-item", item ) // jQuery UI > 1.10.0
  818. .append( "<a>" + item.label + "</a>" )
  819. .appendTo( ul );
  820. };
  821. this.button = $( "<button type=\'button\'>&nbsp;</button>" )
  822. .attr( "tabIndex", -1 )
  823. .attr( "title", "Show All Items" )
  824. .insertAfter( input )
  825. .button({
  826. icons: {
  827. primary: "ui-icon-triangle-1-s"
  828. },
  829. text: false
  830. })
  831. .removeClass( "ui-corner-all" )
  832. .addClass( "ui-corner-right ui-button-icon" )
  833. .click(function() {
  834. // close if already visible
  835. if ( input.autocomplete( "widget" ).is( ":visible" ) ) {
  836. input.autocomplete( "close" );
  837. return;
  838. }
  839. // pass empty string as value to search for, displaying all results
  840. input.autocomplete({ minLength: 0 });
  841. input.autocomplete( "search", "" );
  842. input.autocomplete({ minLength: savMinLengthToAutocomplete });
  843. input.focus();
  844. });
  845. },
  846. destroy: function() {
  847. this.input.remove();
  848. this.button.remove();
  849. this.element.show();
  850. $.Widget.prototype.destroy.call( this );
  851. }
  852. });
  853. })( jQuery );
  854. /**
  855. * Function to output a dialog bog for copy/paste
  856. *
  857. * @param string text Text to put into copy/paste area
  858. * @param string text2 Text to put under the copy/paste area
  859. */
  860. function copyToClipboard(text,text2)
  861. {
  862. text = text.replace(/<br>/g,"\n");
  863. var newElem = '<textarea id="coordsforpopup" style="border: none; width: 90%; height: 120px;">'+text+'</textarea><br><br>'+text2;
  864. /* alert(newElem); */
  865. $("#dialogforpopup").html(newElem);
  866. $("#dialogforpopup").dialog();
  867. $("#coordsforpopup").select();
  868. return false;
  869. }
  870. /**
  871. * Show a popup HTML page. Use the "window.open" function.
  872. *
  873. * @param string url Url
  874. * @param string title Title of popup
  875. * @return boolean False
  876. * @see document_preview
  877. */
  878. function newpopup(url,title) {
  879. var argv = newpopup.arguments;
  880. var argc = newpopup.arguments.length;
  881. tmp=url;
  882. var l = (argc > 2) ? argv[2] : 600;
  883. var h = (argc > 3) ? argv[3] : 400;
  884. var left = (screen.width - l)/2;
  885. var top = (screen.height - h)/2;
  886. var wfeatures = "directories=0,menubar=0,status=0,resizable=0,scrollbars=1,toolbar=0,width=" + l +",height=" + h + ",left=" + left + ",top=" + top;
  887. fen=window.open(tmp,title,wfeatures);
  888. return false;
  889. }
  890. /**
  891. * Function show document preview. Use the "dialog" function.
  892. *
  893. * @param string file Url
  894. * @param string type Mime file type ("image/jpeg", "application/pdf", "text/html")
  895. * @param string title Title of popup
  896. * @return void
  897. * @see newpopup
  898. */
  899. function document_preview(file, type, title)
  900. {
  901. var ValidImageTypes = ["image/gif", "image/jpeg", "image/png"];
  902. console.log("document_preview A click was done. file="+file+", type="+type+", title="+title);
  903. if ($.inArray(type, ValidImageTypes) < 0) {
  904. var width='85%';
  905. var object_width='100%';
  906. var height = $( window ).height()*0.90;
  907. var object_height='98%';
  908. show_preview();
  909. } else {
  910. var object_width=0;
  911. var object_height=0;
  912. var img = new Image();
  913. img.onload = function() {
  914. object_width = this.width;
  915. object_height = this.height;
  916. width = $( window ).width()*0.90;
  917. if(object_width < width){
  918. width = object_width + 30
  919. }
  920. height = $( window ).height()*0.85;
  921. if(object_height < height){
  922. height = object_height + 80
  923. }
  924. show_preview();
  925. };
  926. img.src = file;
  927. }
  928. function show_preview(){
  929. /* console.log("file="+file+" type="+type+" width="+width+" height="+height); */
  930. var newElem = '<object name="objectpreview" data="'+file+'" type="'+type+'" width="'+object_width+'" height="'+object_height+'" param="noparam"></object>';
  931. $("#dialogforpopup").html(newElem);
  932. $("#dialogforpopup").dialog({
  933. closeOnEscape: true,
  934. resizable: true,
  935. width: width,
  936. height: height,
  937. modal: true,
  938. title: title
  939. });
  940. }
  941. }
  942. /*
  943. * Provide a function to get an URL GET parameter in javascript
  944. *
  945. * @param string name Name of parameter
  946. * @param mixed valueifnotfound Value if not found
  947. * @return string Value
  948. */
  949. function getParameterByName(name, valueifnotfound)
  950. {
  951. name = name.replace(/[\[]/, "\\[").replace(/[\]]/, "\\]");
  952. var regex = new RegExp("[\\?&]" + name + "=([^&#]*)"),
  953. results = regex.exec(location.search);
  954. return results === null ? valueifnotfound : decodeURIComponent(results[1].replace(/\+/g, " "));
  955. }
  956. // Code in the public domain from https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/round
  957. (function() {
  958. /**
  959. * Decimal adjustment of a number.
  960. *
  961. * @param {String} type The type of adjustment.
  962. * @param {Number} value The number.
  963. * @param {Integer} exp The exponent (the 10 logarithm of the adjustment base).
  964. * @returns {Number} The adjusted value.
  965. */
  966. function decimalAdjust(type, value, exp) {
  967. // If the exp is undefined or zero...
  968. if (typeof exp === 'undefined' || +exp === 0) {
  969. return Math[type](value);
  970. }
  971. value = +value;
  972. exp = +exp;
  973. // If the value is not a number or the exp is not an integer...
  974. if (isNaN(value) || !(typeof exp === 'number' && exp % 1 === 0)) {
  975. return NaN;
  976. }
  977. // Shift
  978. value = value.toString().split('e');
  979. value = Math[type](+(value[0] + 'e' + (value[1] ? (+value[1] - exp) : -exp)));
  980. // Shift back
  981. value = value.toString().split('e');
  982. return +(value[0] + 'e' + (value[1] ? (+value[1] + exp) : exp));
  983. }
  984. // Decimal round
  985. if (!Math.round10) {
  986. Math.round10 = function(value, exp) {
  987. return decimalAdjust('round', value, exp);
  988. };
  989. }
  990. // Decimal floor
  991. if (!Math.floor10) {
  992. Math.floor10 = function(value, exp) {
  993. return decimalAdjust('floor', value, exp);
  994. };
  995. }
  996. // Decimal ceil
  997. if (!Math.ceil10) {
  998. Math.ceil10 = function(value, exp) {
  999. return decimalAdjust('ceil', value, exp);
  1000. };
  1001. }
  1002. })();
  1003. // Another solution, easier, to build a javascript rounding function
  1004. function dolroundjs(number, decimals) { return +(Math.round(number + "e+" + decimals) + "e-" + decimals); }
  1005. /**
  1006. * Function similar to PHP price2num()
  1007. *
  1008. * @param {number|string} amount The amount to convert/clean
  1009. * @return {string} The amount in universal numeric format (Example: '99.99999')
  1010. * @todo Implement rounding parameter
  1011. */
  1012. function price2numjs(amount) {
  1013. if (amount == '') return '';
  1014. <?php
  1015. $dec = ',';
  1016. $thousand = ' ';
  1017. if ($langs->transnoentitiesnoconv("SeparatorDecimal") != "SeparatorDecimal") {
  1018. $dec = $langs->transnoentitiesnoconv("SeparatorDecimal");
  1019. }
  1020. if ($langs->transnoentitiesnoconv("SeparatorThousand") != "SeparatorThousand") {
  1021. $thousand = $langs->transnoentitiesnoconv("SeparatorThousand");
  1022. }
  1023. if ($thousand == 'Space') $thousand=' ';
  1024. print "var dec='" . dol_escape_js($dec) . "'; var thousand='" . dol_escape_js($thousand) . "';\n"; // Set var in javascript
  1025. ?>
  1026. var main_max_dec_shown = <?php echo (int) str_replace('.', '', $conf->global->MAIN_MAX_DECIMALS_SHOWN); ?>;
  1027. var main_rounding_unit = <?php echo (int) $conf->global->MAIN_MAX_DECIMALS_UNIT; ?>;
  1028. var main_rounding_tot = <?php echo (int) $conf->global->MAIN_MAX_DECIMALS_TOT; ?>;
  1029. var amount = amount.toString();
  1030. // rounding for unit price
  1031. var rounding = main_rounding_unit;
  1032. var pos = amount.indexOf(dec);
  1033. var decpart = '';
  1034. if (pos >= 0) decpart = amount.substr(pos + 1).replace('/0+$/i', ''); // Remove 0 for decimal part
  1035. var nbdec = decpart.length;
  1036. if (nbdec > rounding) rounding = nbdec;
  1037. // If rounding higher than max shown
  1038. if (rounding > main_max_dec_shown) rounding = main_max_dec_shown;
  1039. if (thousand != ',' && thousand != '.') amount = amount.replace(',', '.');
  1040. amount = amount.replace(' ', ''); // To avoid spaces
  1041. amount = amount.replace(thousand, ''); // Replace of thousand before replace of dec to avoid pb if thousand is .
  1042. amount = amount.replace(dec, '.');
  1043. //console.log("amount before="+amount+" rouding="+rounding)
  1044. var res = Math.round10(amount, - rounding);
  1045. // Other solution is
  1046. // var res = dolroundjs(amount, rounding)
  1047. console.log("res="+res)
  1048. return res;
  1049. }