2015-12-07 14:10:23 +00:00
< ? php
2018-11-29 11:20:47 +00:00
/* Copyright ( C ) 2005 - 2018 Laurent Destailleur < eldy @ users . sourceforge . net >
2018-10-27 12:43:12 +00:00
* Copyright ( C ) 2005 - 2014 Regis Houssin < regis . houssin @ inodbox . com >
2015-12-07 14:10:23 +00:00
* Copyright ( C ) 2015 Raphaël Doursenaud < rdoursenaud @ gpcsolutions . fr >
2024-03-19 17:49:01 +00:00
* Copyright ( C ) 2024 MDW < mdeweerd @ users . noreply . github . com >
2026-02-04 13:49:13 +00:00
* Copyright ( C ) 2024 - 2026 Frédéric France < frederic . france @ free . fr >
2015-12-07 14:10:23 +00:00
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation ; either version 3 of the License , or
* ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
2019-09-23 19:55:30 +00:00
* along with this program . If not , see < https :// www . gnu . org / licenses />.
* or see https :// www . gnu . org /
2015-12-07 14:10:23 +00:00
*/
/**
2017-12-14 20:28:51 +00:00
* \file htdocs / core / js / lib_head . js . php
* \brief File that include javascript functions ( included if option use_javascript activated )
* JQuery ( providing object $ ) and JQuery - UI ( providing $datepicker ) libraries must be loaded before this file .
2015-12-07 14:10:23 +00:00
*/
2025-09-15 11:26:47 +00:00
if ( ! defined ( 'MAIN_ALREADY_INCLUDED' )) {
if ( ! defined ( 'NOREQUIRESOC' )) {
define ( 'NOREQUIRESOC' , '1' );
}
if ( ! defined ( 'NOCSRFCHECK' )) {
define ( 'NOCSRFCHECK' , 1 );
}
if ( ! defined ( 'NOTOKENRENEWAL' )) {
define ( 'NOTOKENRENEWAL' , 1 );
}
if ( ! defined ( 'NOLOGIN' )) {
define ( 'NOLOGIN' , 1 );
}
if ( ! defined ( 'NOREQUIREMENU' )) {
define ( 'NOREQUIREMENU' , 1 );
}
if ( ! defined ( 'NOREQUIREHTML' )) {
define ( 'NOREQUIREHTML' , 1 );
}
if ( ! defined ( 'NOREQUIREAJAX' )) {
define ( 'NOREQUIREAJAX' , '1' );
}
2015-12-07 14:10:23 +00:00
2025-09-15 11:26:47 +00:00
session_cache_limiter ( 'public' );
2015-12-07 14:10:23 +00:00
2025-09-15 11:26:47 +00:00
require_once '../../main.inc.php' ;
}
2024-11-04 22:53:20 +00:00
/**
* @ var Conf $conf
* @ var Translate $langs
*/
2021-07-08 21:19:43 +00:00
2025-09-15 11:26:47 +00:00
/**
2021-07-08 21:19:43 +00:00
* View
*/
2025-09-15 11:26:47 +00:00
if ( ! defined ( 'MAIN_ALREADY_INCLUDED' )) {
// Define javascript type
top_httphead ( 'text/javascript; charset=UTF-8' );
// Important: Following code is to avoid page request by browser and PHP CPU at each Dolibarr page access.
2026-04-25 10:13:25 +00:00
header ( 'Cache-Control: max-age=10800, public, must-revalidate' );
2021-02-23 21:03:23 +00:00
}
2017-10-13 20:01:56 +00:00
// Define tradMonths javascript array (we define this in datepicker AND in parent page to avoid errors with IE8)
2020-04-10 08:59:32 +00:00
$tradMonths = array (
2018-11-29 11:20:47 +00:00
dol_escape_js ( $langs -> transnoentitiesnoconv ( " Month01 " )),
dol_escape_js ( $langs -> transnoentitiesnoconv ( " Month02 " )),
dol_escape_js ( $langs -> transnoentitiesnoconv ( " Month03 " )),
dol_escape_js ( $langs -> transnoentitiesnoconv ( " Month04 " )),
dol_escape_js ( $langs -> transnoentitiesnoconv ( " Month05 " )),
dol_escape_js ( $langs -> transnoentitiesnoconv ( " Month06 " )),
dol_escape_js ( $langs -> transnoentitiesnoconv ( " Month07 " )),
dol_escape_js ( $langs -> transnoentitiesnoconv ( " Month08 " )),
dol_escape_js ( $langs -> transnoentitiesnoconv ( " Month09 " )),
dol_escape_js ( $langs -> transnoentitiesnoconv ( " Month10 " )),
dol_escape_js ( $langs -> transnoentitiesnoconv ( " Month11 " )),
dol_escape_js ( $langs -> transnoentitiesnoconv ( " Month12 " ))
2017-10-13 20:01:56 +00:00
);
2020-04-10 08:59:32 +00:00
$tradMonthsShort = array (
2018-11-29 11:20:47 +00:00
$langs -> trans ( " MonthShort01 " ),
$langs -> trans ( " MonthShort02 " ),
$langs -> trans ( " MonthShort03 " ),
$langs -> trans ( " MonthShort04 " ),
$langs -> trans ( " MonthShort05 " ),
$langs -> trans ( " MonthShort06 " ),
$langs -> trans ( " MonthShort07 " ),
$langs -> trans ( " MonthShort08 " ),
$langs -> trans ( " MonthShort09 " ),
$langs -> trans ( " MonthShort10 " ),
$langs -> trans ( " MonthShort11 " ),
$langs -> trans ( " MonthShort12 " )
2017-10-13 20:01:56 +00:00
);
2020-04-10 08:59:32 +00:00
$tradDays = array (
2017-10-13 20:01:56 +00:00
$langs -> trans ( " Sunday " ),
$langs -> trans ( " Monday " ),
$langs -> trans ( " Tuesday " ),
$langs -> trans ( " Wednesday " ),
$langs -> trans ( " Thursday " ),
$langs -> trans ( " Friday " ),
$langs -> trans ( " Saturday " )
);
2020-04-10 08:59:32 +00:00
$tradDaysShort = array (
2017-10-13 20:01:56 +00:00
$langs -> trans ( " ShortSunday " ),
$langs -> trans ( " ShortMonday " ),
$langs -> trans ( " ShortTuesday " ),
$langs -> trans ( " ShortWednesday " ),
$langs -> trans ( " ShortThursday " ),
$langs -> trans ( " ShortFriday " ),
$langs -> trans ( " ShortSaturday " )
);
2020-04-10 08:59:32 +00:00
$tradDaysMin = array (
2017-10-13 20:01:56 +00:00
$langs -> trans ( " SundayMin " ),
$langs -> trans ( " MondayMin " ),
$langs -> trans ( " TuesdayMin " ),
$langs -> trans ( " WednesdayMin " ),
$langs -> trans ( " ThursdayMin " ),
$langs -> trans ( " FridayMin " ),
$langs -> trans ( " SaturdayMin " )
);
2022-05-06 16:30:19 +00:00
$dec = ',' ;
$thousand = ' ' ;
if ( $langs -> transnoentitiesnoconv ( " SeparatorDecimal " ) != " SeparatorDecimal " ) {
$dec = $langs -> transnoentitiesnoconv ( " SeparatorDecimal " );
}
if ( $langs -> transnoentitiesnoconv ( " SeparatorThousand " ) != " SeparatorThousand " ) {
$thousand = $langs -> transnoentitiesnoconv ( " SeparatorThousand " );
}
if ( $thousand == 'Space' ) {
$thousand = ' ' ;
}
2015-12-07 14:10:23 +00:00
?>
2017-09-24 19:02:20 +00:00
// Javascript libraries for Dolibarr ERP CRM (https://www.dolibarr.org)
2017-09-24 18:36:27 +00:00
2025-05-06 17:15:13 +00:00
2026-07-23 09:44:05 +00:00
/*
* To start / stop Block UI
*/
2025-05-06 17:15:13 +00:00
function dolBlockUI ( message = 'Loading...' , indicatorUrl = '<?php echo DOL_URL_ROOT."/theme/".$conf->theme."/img/working.gif" ; ?>' ) {
const block = document . getElementById ( 'dol-block-ui' );
if ( block != null ) {
const msgDiv = block . querySelector ( '.message' );
if ( msgDiv != null ) {
msgDiv . innerText = message ;
msgDiv . style . backgroundImage = `url('${indicatorUrl}')` ;
block . style . display = 'flex' ;
}
}
}
function dolUnblockUI () {
document . getElementById ( 'dol-block-ui' ) . style . display = 'none' ;
}
2026-07-23 09:44:05 +00:00
/*
* For jQuery date picker
*/
2017-10-13 20:01:56 +00:00
var tradMonths = < ? php echo json_encode ( $tradMonths ) ?> ;
var tradMonthsShort = < ? php echo json_encode ( $tradMonthsShort ) ?> ;
var tradDays = < ? php echo json_encode ( $tradDays ) ?> ;
var tradDaysShort = < ? php echo json_encode ( $tradDaysShort ) ?> ;
var tradDaysMin = < ? php echo json_encode ( $tradDaysMin ) ?> ;
2022-05-06 16:30:19 +00:00
var currencyCache = < ? php echo json_encode ( $langs -> cache_currencies ) ?> ;
2017-10-13 20:01:56 +00:00
2017-10-13 20:37:30 +00:00
// For JQuery date picker
$ ( document ) . ready ( function () {
$ . datepicker . setDefaults ({
autoSize : true ,
changeMonth : true ,
changeYear : true ,
altField : '#timestamp' ,
altFormat : '@' // Gives a timestamp dateformat
});
});
jQuery ( function ( $ ){
2025-12-13 12:47:19 +00:00
$ . datepicker . regional [ '<?php echo dol_escape_js($langs->defaultlang) ?>' ] = {
closeText : '<?php echo dol_escape_js($langs->trans("Close2")) ?>' ,
prevText : '<?php echo dol_escape_js($langs->trans("Previous")) ?>' ,
nextText : '<?php echo dol_escape_js($langs->trans("Next")) ?>' ,
currentText : '<?php echo dol_escape_js($langs->trans("Now")) ?>' ,
2017-10-13 20:37:30 +00:00
monthNames : tradMonths ,
monthNamesShort : tradMonthsShort ,
dayNames : tradDays ,
dayNamesShort : tradDaysShort ,
dayNamesMin : tradDaysMin ,
2025-12-13 12:47:19 +00:00
weekHeader : '<?php echo dol_escape_js($langs->trans("Week")); ?>' ,
dateFormat : '<?php echo dol_escape_js($langs->trans("FormatDateShortJQuery")); ?>' , /* Note dd/mm/yy means year on 4 digit in jquery format */
2025-10-23 12:31:45 +00:00
firstDay : < ? php echo getDolGlobalInt ( 'MAIN_START_WEEK' , 1 ); ?> ,
2023-12-04 11:05:17 +00:00
isRTL : < ? php echo ( $langs -> trans ( " DIRECTION " ) == 'rtl' ? 'true' : 'false' ); ?> ,
2017-10-13 20:37:30 +00:00
showMonthAfterYear : false , /* TODO add specific to country */
2021-02-23 21:03:23 +00:00
yearSuffix : '' /* TODO add specific to country */
2017-10-13 20:37:30 +00:00
};
2025-12-13 12:47:19 +00:00
$ . datepicker . setDefaults ( $ . datepicker . regional [ '<?php echo dol_escape_js($langs->defaultlang) ?>' ]);
2017-10-13 20:37:30 +00:00
});
2017-09-24 18:36:27 +00:00
/**
2017-10-21 17:05:24 +00:00
* Set array used for select2 translations
2017-09-24 18:36:27 +00:00
*/
2017-10-21 17:05:24 +00:00
var select2arrayoflanguage = {
matches : function ( matches ) { return matches + " <?php echo dol_escape_js( $langs->transnoentitiesnoconv ( " Select2ResultFoundUseArrows " )); ?> " ; },
noResults : function () { return " <?php echo dol_escape_js( $langs->transnoentitiesnoconv ( " Select2NotFound " )); ?> " ; },
inputTooShort : function ( input ) {
var n = input . minimum ;
2024-02-26 18:14:00 +00:00
/*console.log(input); console.log(input.minimum);*/
2017-10-21 17:05:24 +00:00
if ( n > 1 ) return " <?php echo dol_escape_js( $langs->transnoentitiesnoconv ( " Select2Enter " )); ?> " + n + " <?php echo dol_escape_js( $langs->transnoentitiesnoconv ( " Select2MoreCharacters " )); ?> " ;
else return " <?php echo dol_escape_js( $langs->transnoentitiesnoconv ( " Select2Enter " )); ?> " + n + " <?php echo dol_escape_js( $langs->transnoentitiesnoconv ( " Select2MoreCharacter " )); ?> "
},
loadMore : function ( pageNumber ) { return " <?php echo dol_escape_js( $langs->transnoentitiesnoconv ( " Select2LoadingMoreResults " )); ?> " ; },
searching : function () { return " <?php echo dol_escape_js( $langs->transnoentitiesnoconv ( " Select2SearchInProgress " )); ?> " ; }
};
2017-09-24 18:36:27 +00:00
2017-10-21 17:05:24 +00:00
/**
* For calendar input
2010-08-29 17:52:06 +00:00
*/
2017-09-24 18:55:48 +00:00
// Returns an object given an id
function getObjectFromID ( id ){
var theObject ;
if ( document . getElementById )
theObject = document . getElementById ( id );
else
theObject = document . all [ id ];
return theObject ;
}
2024-12-15 14:38:38 +00:00
// Called after the selection or typing of a date to save details into detailed fields
2021-02-19 21:00:44 +00:00
function dpChangeDay ( dateFieldID , format )
2017-09-24 18:55:48 +00:00
{
2025-12-31 13:54:54 +00:00
console . log ( " Call dpChangeDay, we save date from field " + dateFieldID + " into detailed fields from format = " + format );
2017-09-24 18:55:48 +00:00
2024-12-15 14:38:38 +00:00
var thefield = getObjectFromID ( dateFieldID );
var thefieldday = getObjectFromID ( dateFieldID + " day " );
var thefieldmonth = getObjectFromID ( dateFieldID + " month " );
var thefieldyear = getObjectFromID ( dateFieldID + " year " );
2017-09-24 18:55:48 +00:00
2025-12-31 13:54:54 +00:00
console . log ( " string date value is " + thefield . value );
2024-12-15 14:38:38 +00:00
var date = getDateFromFormat ( thefield . value , format );
2025-12-31 13:54:54 +00:00
2017-09-24 18:55:48 +00:00
if ( date )
{
2024-12-15 14:38:38 +00:00
thefieldday . value = date . getDate ();
if ( thefieldday . onchange ) thefieldday . onchange . call ( thefieldday );
thefieldmonth . value = date . getMonth () + 1 ;
if ( thefieldmonth . onchange ) thefieldmonth . onchange . call ( thefieldmonth );
thefieldyear . value = date . getFullYear ();
if ( thefieldyear . onchange ) thefieldyear . onchange . call ( thefieldyear );
return 1 ;
2017-09-24 18:55:48 +00:00
}
2024-12-15 14:38:38 +00:00
// Replace yyyy into yy
newformat = format . replace ( / yyyy / g , 'yy' );
if ( newformat != format ) {
console . log ( " dpChangeDay, we try now from format = " + newformat );
var date = getDateFromFormat ( thefield . value , newformat );
//console.log(date);
if ( date )
{
thefieldday . value = date . getDate ();
if ( thefieldday . onchange ) thefieldday . onchange . call ( thefieldday );
thefieldmonth . value = date . getMonth () + 1 ;
if ( thefieldmonth . onchange ) thefieldmonth . onchange . call ( thefieldmonth );
thefieldyear . value = date . getFullYear ();
if ( thefieldyear . onchange ) thefieldyear . onchange . call ( thefieldyear );
return 2 ;
}
2017-09-24 18:55:48 +00:00
}
2024-12-15 14:38:38 +00:00
thefieldday . value = '' ;
if ( thefieldday . onchange ) thefieldday . onchange . call ( thefieldday );
thefieldmonth . value = '' ;
if ( thefieldmonth . onchange ) thefieldmonth . onchange . call ( thefieldmonth );
thefieldyear . value = '' ;
if ( thefieldyear . onchange ) thefieldyear . onchange . call ( thefieldyear );
return 0 ;
2017-09-24 18:55:48 +00:00
}
2026-07-23 09:44:05 +00:00
2010-08-29 17:52:06 +00:00
/*
2017-08-22 07:23:35 +00:00
* =================================================================
2023-10-26 12:03:13 +00:00
* Function : formatDate ( javascript object Date (), format )
* Purpose : Returns a date in the output format specified . The format string can use the following tags :
* Year | yyyy ( 4 digits ), yy ( 2 digits )
* Month | MM ( 2 digits )
* Day of Month | dd ( 2 digits )
* Hour ( 1 - 12 ) | hh ( 2 digits ) Hour ( 0 - 23 ) | HH ( 2 digits )
* Minute | mm ( 2 digits )
* Second | ss ( 2 digits )
* Author : Laurent Destailleur Author : Matelli ( see http :// matelli . fr / showcases / patchs - dolibarr / update - date - input - in - action - form . html )
2010-08-29 17:52:06 +00:00
* Licence : GPL
* ==================================================================
*/
2007-01-21 21:43:04 +00:00
function formatDate ( date , format )
2007-02-11 19:02:09 +00:00
{
2010-08-29 17:52:06 +00:00
// alert('formatDate date='+date+' format='+format);
2017-08-22 07:23:35 +00:00
2026-02-04 13:49:13 +00:00
// Force parameters to string
2007-02-11 19:02:09 +00:00
format = format + " " ;
2017-08-22 07:23:35 +00:00
2007-01-21 21:43:04 +00:00
var result = " " ;
2024-09-26 01:55:28 +00:00
var year = date . getFullYear ();
2007-02-11 19:02:09 +00:00
var month = date . getMonth () + 1 ;
var day = date . getDate ();
var hour = date . getHours ();
2008-12-03 21:41:07 +00:00
var minute = date . getMinutes ();
2007-02-11 19:02:09 +00:00
var seconde = date . getSeconds ();
2007-01-21 21:43:04 +00:00
var i = 0 ;
while ( i < format . length )
2007-02-11 19:02:09 +00:00
{
c = format . charAt ( i ); // Recupere char du format
2023-06-29 11:47:28 +00:00
var substr = '' ;
2007-01-21 21:43:04 +00:00
j = i ;
2013-11-16 17:12:13 +00:00
while (( format . charAt ( j ) == c ) && ( j < format . length )) // Recupere char successif identiques
2007-02-11 19:02:09 +00:00
{
substr += format . charAt ( j ++ );
}
2007-01-21 21:43:04 +00:00
2010-08-29 17:52:06 +00:00
// alert('substr='+substr);
2007-02-11 19:02:09 +00:00
if ( substr == 'yyyy' ) { result = result + year ; }
else if ( substr == 'yy' ) { result = result + year . substring ( 2 , 4 ); }
2009-08-09 19:25:17 +00:00
else if ( substr == 'M' ) { result = result + month ; }
2007-02-11 19:02:09 +00:00
else if ( substr == 'MM' ) { result = result + ( month < 1 || month > 9 ? " " : " 0 " ) + month ; }
else if ( substr == 'd' ) { result = result + day ; }
else if ( substr == 'dd' ) { result = result + ( day < 1 || day > 9 ? " " : " 0 " ) + day ; }
2008-12-03 21:41:07 +00:00
else if ( substr == 'hh' ) { if ( hour > 12 ) hour -= 12 ; result = result + ( hour < 0 || hour > 9 ? " " : " 0 " ) + hour ; }
else if ( substr == 'HH' ) { result = result + ( hour < 0 || hour > 9 ? " " : " 0 " ) + hour ; }
else if ( substr == 'mm' ) { result = result + ( minute < 0 || minute > 9 ? " " : " 0 " ) + minute ; }
else if ( substr == 'ss' ) { result = result + ( seconde < 0 || seconde > 9 ? " " : " 0 " ) + seconde ; }
2007-01-21 21:43:04 +00:00
else { result = result + substr ; }
2017-08-22 07:23:35 +00:00
2007-02-11 19:02:09 +00:00
i += substr . length ;
2007-01-21 21:43:04 +00:00
}
2010-08-29 17:52:06 +00:00
// alert(result);
2007-01-21 21:43:04 +00:00
return result ;
}
2010-08-29 17:52:06 +00:00
/*
2017-08-22 07:23:35 +00:00
* =================================================================
2017-10-21 17:05:24 +00:00
* Function : getDateFromFormat ( date_string , format_string )
* Purpose : This function takes a date string and a format string .
* It parses the date string with format and it
2010-08-29 17:52:06 +00:00
* returns the date as a javascript Date () object . If date does not match
2017-08-22 07:23:35 +00:00
* format , it returns 0. The format string can use the following tags :
2010-11-19 21:24:48 +00:00
* Field | Tags
* -------------+-----------------------------------
2017-08-22 07:23:35 +00:00
* Year | yyyy ( 4 digits ), yy ( 2 digits )
* Month | MM ( 2 digits )
* Day of Month | dd ( 2 digits )
* Hour ( 1 - 12 ) | hh ( 2 digits )
* Hour ( 0 - 23 ) | HH ( 2 digits )
* Minute | mm ( 2 digits )
2010-11-19 21:24:48 +00:00
* Second | ss ( 2 digits )
2017-08-22 07:23:35 +00:00
* Author : Laurent Destailleur
2010-11-19 21:24:48 +00:00
* Licence : GPL
2010-08-29 17:52:06 +00:00
* ==================================================================
*/
2024-12-15 14:38:38 +00:00
function getDateFromFormat ( val , format )
2007-02-11 19:02:09 +00:00
{
2010-08-29 17:52:06 +00:00
// alert('getDateFromFormat val='+val+' format='+format);
2007-01-21 21:43:04 +00:00
2026-02-04 13:49:13 +00:00
// Force parameters to string
2024-12-15 14:38:38 +00:00
val = val + " " ;
format = format + " " ;
2007-01-21 21:43:04 +00:00
2010-11-19 21:24:48 +00:00
if ( val == '' ) return 0 ;
2017-08-22 07:23:35 +00:00
2007-02-11 19:02:09 +00:00
var now = new Date ();
2024-09-26 01:55:28 +00:00
var year = now . getFullYear ();
2007-02-11 19:02:09 +00:00
var month = now . getMonth () + 1 ;
var day = now . getDate ();
var hour = now . getHours ();
var minute = now . getMinutes ();
var seconde = now . getSeconds ();
2007-01-21 21:43:04 +00:00
var i = 0 ;
2024-12-15 14:38:38 +00:00
var d = 0 ; // -d- follows the date string while -i- follows the format string
2009-05-05 00:18:23 +00:00
2007-01-21 21:43:04 +00:00
while ( i < format . length )
2007-02-11 19:02:09 +00:00
{
c = format . charAt ( i ); // Recupere char du format
2007-01-21 21:43:04 +00:00
substr = " " ;
2007-02-11 19:02:09 +00:00
j = i ;
2024-12-15 14:38:38 +00:00
while (( format . charAt ( j ) == c ) && ( j < format . length )) // Get successive similar characters
2007-02-11 19:02:09 +00:00
{
substr += format . charAt ( j ++ );
}
2007-01-21 21:43:04 +00:00
2010-08-29 17:52:06 +00:00
// alert('substr='+substr);
2021-02-23 21:03:23 +00:00
if ( substr == " yyyy " ) year = getIntegerInString ( val , d , 4 , 4 );
2024-02-23 12:40:30 +00:00
if ( substr == " yy " ) year = " " + ( getIntegerInString ( val , d , 2 , 2 ) - 0 + 2000 ); /* #28334 */
2021-02-23 21:03:23 +00:00
if ( substr == " MM " || substr == " M " )
{
month = getIntegerInString ( val , d , 1 , 2 );
if ( month ) d -= 2 - month . length ;
}
if ( substr == " dd " )
{
day = getIntegerInString ( val , d , 1 , 2 );
if ( day ) d -= 2 - day . length ;
}
if ( substr == " HH " || substr == " hh " )
{
hour = getIntegerInString ( val , d , 1 , 2 );
if ( dhouray ) d -= 2 - hour . length ;
}
if ( substr == " mm " ){
minute = getIntegerInString ( val , d , 1 , 2 );
if ( minute ) d -= 2 - minute . length ;
}
if ( substr == " ss " )
{
seconde = getIntegerInString ( val , d , 1 , 2 );
if ( seconde ) d -= 2 - seconde . length ;
}
2017-08-22 07:23:35 +00:00
2007-01-21 21:43:04 +00:00
i += substr . length ;
2009-05-05 00:18:23 +00:00
d += substr . length ;
2007-01-21 21:43:04 +00:00
}
2017-08-22 07:23:35 +00:00
2007-01-21 21:43:04 +00:00
// Check if format param are ok
2007-02-11 19:02:09 +00:00
if ( year == null || year < 1 ) { return 0 ; }
if ( month == null || ( month < 1 ) || ( month > 12 )) { return 0 ; }
if ( day == null || ( day < 1 ) || ( day > 31 )) { return 0 ; }
if ( hour == null || ( hour < 0 ) || ( hour > 24 )) { return 0 ; }
if ( minute == null || ( minute < 0 ) || ( minute > 60 )) { return 0 ; }
if ( seconde == null || ( seconde < 0 ) || ( seconde > 60 )) { return 0 ; }
2017-08-22 07:23:35 +00:00
2010-08-29 17:52:06 +00:00
// alert(year+' '+month+' '+day+' '+hour+' '+minute+' '+seconde);
2013-09-05 14:37:23 +00:00
return new Date ( year , month - 1 , day , hour , minute , seconde );
2007-01-21 21:43:04 +00:00
}
2010-08-29 17:52:06 +00:00
/*
2017-08-22 07:23:35 +00:00
* =================================================================
2017-10-21 17:05:24 +00:00
* Function : stringIsInteger ( string )
* Purpose : Return true if string is an integer
2010-08-29 17:52:06 +00:00
* ==================================================================
*/
2007-01-21 21:43:04 +00:00
function stringIsInteger ( str )
2007-02-11 19:02:09 +00:00
{
var digits = " 1234567890 " ;
2007-01-21 21:43:04 +00:00
for ( var i = 0 ; i < str . length ; i ++ )
2007-02-11 19:02:09 +00:00
{
2007-01-21 21:43:04 +00:00
if ( digits . indexOf ( str . charAt ( i )) ==- 1 )
{
return false ;
2007-02-11 19:02:09 +00:00
}
}
return true ;
}
2007-01-21 21:43:04 +00:00
2010-08-29 17:52:06 +00:00
/*
2017-08-22 07:23:35 +00:00
* =================================================================
2017-10-21 17:05:24 +00:00
* Function : getIntegerInString ( string , pos , minlength , maxlength )
* Purpose : Return part of string from position i that is integer
2010-08-29 17:52:06 +00:00
* ==================================================================
*/
2007-01-21 21:43:04 +00:00
function getIntegerInString ( str , i , minlength , maxlength )
2007-02-11 19:02:09 +00:00
{
2007-01-21 21:43:04 +00:00
for ( var x = maxlength ; x >= minlength ; x -- )
2007-02-11 19:02:09 +00:00
{
var substr = str . substring ( i , i + x );
if ( substr . length < minlength ) { return null ; }
if ( stringIsInteger ( substr )) { return substr ; }
}
return null ;
2007-01-21 21:43:04 +00:00
}
2006-06-05 18:26:46 +00:00
2007-01-18 22:05:49 +00:00
2010-08-29 17:52:06 +00:00
/*
2017-08-22 07:23:35 +00:00
* =================================================================
2017-10-21 17:05:24 +00:00
* Purpose : Clean string to have it url encoded
* Input : s
* Author : Laurent Destailleur
2010-08-29 17:52:06 +00:00
* Licence : GPL
* ==================================================================
*/
2010-08-21 15:30:17 +00:00
function urlencode ( s ) {
2023-06-29 11:47:28 +00:00
var news = s ;
2026-07-24 05:21:20 +00:00
if ( typeof news === " number " ) {
news = news . toString ();
}
2023-06-29 11:47:28 +00:00
news = news . replace ( / \ +/ gi , '%2B' );
news = news . replace ( /&/ gi , '%26' );
2011-06-08 15:26:54 +00:00
return news ;
2010-08-21 15:30:17 +00:00
}
2026-07-23 09:44:05 +00:00
2017-10-26 18:06:23 +00:00
/*
* =================================================================
2023-07-22 14:17:06 +00:00
* Purpose : Clean string to get a HTML coded string .
2017-10-26 18:06:23 +00:00
* Input : s
* Author : Laurent Destailleur
* Licence : GPL
* ==================================================================
*/
function htmlEntityDecodeJs ( inp ){
var replacements = { '<' : '<' , '>' : '>' , '/' : '/' , '"' : '"' , ''' : '\'' , '&' : '&' , ' ' : ' ' };
2023-06-29 11:47:28 +00:00
if ( inp ) {
2017-10-26 18:06:23 +00:00
for ( var r in replacements ){
2021-02-23 21:03:23 +00:00
inp = inp . replace ( new RegExp ( r , 'g' ), replacements [ r ]);
2017-10-26 18:06:23 +00:00
}
return inp . replace ( /& #(\d+);/g, function(match, dec) {
2021-02-23 21:03:23 +00:00
return String . fromCharCode ( dec );
2017-10-26 18:06:23 +00:00
});
2023-06-29 11:47:28 +00:00
} else {
return '' ;
2017-10-26 18:06:23 +00:00
}
}
2010-08-21 15:30:17 +00:00
2010-08-29 17:52:06 +00:00
/*
2017-08-22 07:23:35 +00:00
* =================================================================
2017-10-21 17:05:24 +00:00
* Purpose : Applique un delai avant execution . Used for autocompletion of companies .
2017-08-22 07:23:35 +00:00
* Input : funct , delay
* Author : Regis Houssin
2010-09-06 11:34:53 +00:00
* Licence : GPL
2010-08-29 17:52:06 +00:00
* ==================================================================
*/
2009-08-28 01:14:35 +00:00
function ac_delay ( funct , delay ) {
2021-02-23 21:03:23 +00:00
// delay before start of action
setTimeout ( funct , delay );
2007-08-01 07:41:53 +00:00
}
2010-08-29 17:52:06 +00:00
/*
2017-08-22 07:23:35 +00:00
* =================================================================
2010-08-29 17:52:06 +00:00
* Purpose :
2010-09-06 11:34:53 +00:00
* Clean values of a " Sortable.serialize " . Used by drag and drop .
2017-08-22 07:23:35 +00:00
* Input : expr
* Author : Regis Houssin
2010-09-06 11:34:53 +00:00
* Licence : GPL
2010-08-29 17:52:06 +00:00
* ==================================================================
*/
2007-08-01 07:41:53 +00:00
function cleanSerialize ( expr ) {
2023-06-29 11:47:28 +00:00
if ( typeof ( expr ) != 'string' ) {
return '' ;
}
2007-08-01 07:41:53 +00:00
var reg = new RegExp ( " (&) " , " g " );
2007-08-02 22:02:58 +00:00
var reg2 = new RegExp ( " [^A-Z0-9,] " , " g " );
2007-08-01 07:41:53 +00:00
var liste1 = expr . replace ( reg , " , " );
2013-09-06 08:22:13 +00:00
return liste1 . replace ( reg2 , " " );
2007-08-04 10:10:45 +00:00
}
2010-08-18 08:11:42 +00:00
2010-08-29 17:52:06 +00:00
/*
2025-12-13 12:47:19 +00:00
* Purpose : Fonction to open a confirm popup on a click of a link
2025-09-28 18:01:36 +00:00
* Input : msg
2025-12-13 12:47:19 +00:00
* Input : id
* Input : popupWidth
2025-12-17 11:57:44 +00:00
* Input : popupHeight
2025-12-13 12:47:19 +00:00
* Input : disableCancelButton
2010-09-06 11:34:53 +00:00
* Licence : GPL
2025-12-13 12:47:19 +00:00
* See also document_preview () that also maje a dialogforpopup . dialog () .
* See also newpopup that use window . open .
2010-08-29 17:52:06 +00:00
*/
2025-12-17 11:57:44 +00:00
function confirmDolibarr ( msg , id , popupWidth = 400 , popupHeight = 300 , disableCancelButton = 0 ) {
2025-12-13 12:47:19 +00:00
let alink = document . getElementById ( id );
2026-01-20 23:58:54 +00:00
let title = '<?php echo dol_escape_js($langs->transnoentitiesnoconv("Note")); ?>' ;
2025-12-13 12:47:19 +00:00
if ( alink . getAttribute ( " data-alreadyclicked " ) === " 1 " ) {
return true ;
}
console . log ( " Call confirmDolibarr disableCancelButton= " + disableCancelButton );
let buttons = {};
if ( disableCancelButton === 0 ) {
2026-01-20 23:58:54 +00:00
buttons [ '<?php echo dol_escape_js($langs->transnoentitiesnoconv("Cancel")); ?>' ] = function () {
2025-12-13 12:47:19 +00:00
$ ( this ) . dialog ( " close " );
};
}
2026-01-20 23:58:54 +00:00
buttons [ '<?php echo dol_escape_js($langs->transnoentitiesnoconv("Confirm")); ?>' ] = function () {
2025-12-13 12:47:19 +00:00
console . log ( " We click OK " ); $ ( this ) . dialog ( " close " ); alink . setAttribute ( " data-alreadyclicked " , " 1 " ); alink . click (); return false ;
};
new Promise ( res => {
$ ( " #dialogforpopup " ) . text ( msg ) . dialog ({
closeOnEscape : true ,
resizable : true ,
modal : true ,
width : popupWidth ,
height : popupHeight ,
title : title ,
buttons : buttons
});
2025-09-28 18:01:36 +00:00
});
2025-12-13 12:47:19 +00:00
return false ;
2009-12-18 14:34:25 +00:00
}
2011-02-05 03:28:56 +00:00
2013-11-16 17:12:13 +00:00
2012-08-13 18:53:48 +00:00
/*
2020-09-18 23:45:40 +00:00
* Used by button to set on / off .
* Call url then make complementary action ( like show / hide , enable / disable or set another option ) .
2017-02-04 10:02:10 +00:00
*
2021-02-23 10:13:57 +00:00
* @ param string url Url ( warning : as any url called in ajax mode , the url called here must not renew the token )
2017-02-04 10:02:10 +00:00
* @ param string code Code
2024-01-13 18:48:20 +00:00
* @ param string input Array of complementary actions to do if success
2017-02-04 10:02:10 +00:00
* @ param int entity Entity
2024-06-29 17:24:16 +00:00
* @ param int strict Strict ( 0 = ? , 1 = ? )
2020-02-18 08:37:59 +00:00
* @ param int forcereload Force reload
2020-03-25 15:00:42 +00:00
* @ param int userid User id
2020-09-18 23:45:40 +00:00
* @ param string token Token
2024-10-30 01:38:59 +00:00
* @ param int value Value to set
* @ param int userconst 1 = On / Off of user constant instead of global const
2024-01-13 18:48:20 +00:00
* @ return boolean
2012-08-13 18:53:48 +00:00
*/
2024-10-30 01:38:59 +00:00
function setConstant ( url , code , input , entity , strict , forcereload , userid , token , value , userconst ) {
2021-02-23 15:56:45 +00:00
var saved_url = url ; /* avoid undefined url */
2024-10-30 01:38:59 +00:00
2020-09-19 10:50:47 +00:00
$ . post ( url , {
2012-08-13 18:53:48 +00:00
action : " set " ,
name : code ,
2020-09-18 23:45:40 +00:00
entity : entity ,
2021-08-05 12:42:28 +00:00
token : token ,
2024-10-30 01:38:59 +00:00
value : value ,
userconst : userconst
2012-08-13 18:53:48 +00:00
},
2021-02-23 10:03:34 +00:00
function () { /* handler for success of post */
2022-02-06 21:11:44 +00:00
console . log ( " Ajax url request to set constant is a success. Make complementary actions and then forcereload= " + forcereload + " value= " + value );
2021-08-05 12:42:28 +00:00
if ( value == 0 ) {
$ ( " #set_ " + code ) . show ();
$ ( " #del_ " + code ) . hide ();
} else {
$ ( " #set_ " + code ) . hide ();
$ ( " #del_ " + code ) . show ();
}
2012-08-13 18:53:48 +00:00
$ . each ( input , function ( type , data ) {
// Enable another element
2014-08-17 13:12:20 +00:00
if ( type == " disabled " && strict != 1 ) {
2012-08-13 18:53:48 +00:00
$ . each ( data , function ( key , value ) {
2013-03-13 22:05:34 +00:00
var newvalue = (( value . search ( " ^# " ) < 0 && value . search ( " ^ \ . " ) < 0 ) ? " # " : " " ) + value ;
$ ( newvalue ) . removeAttr ( " disabled " );
if ( $ ( newvalue ) . hasClass ( " butActionRefused " ) == true ) {
$ ( newvalue ) . removeClass ( " butActionRefused " );
$ ( newvalue ) . addClass ( " butAction " );
2012-08-13 18:53:48 +00:00
}
});
2013-03-13 22:05:34 +00:00
} else if ( type == " enabled " ) {
$ . each ( data , function ( key , value ) {
var newvalue = (( value . search ( " ^# " ) < 0 && value . search ( " ^ \ . " ) < 0 ) ? " # " : " " ) + value ;
2014-08-17 13:12:20 +00:00
if ( strict == 1 )
$ ( newvalue ) . removeAttr ( " disabled " );
else
$ ( newvalue ) . attr ( " disabled " , true );
2013-03-13 22:05:34 +00:00
if ( $ ( newvalue ) . hasClass ( " butAction " ) == true ) {
$ ( newvalue ) . removeClass ( " butAction " );
$ ( newvalue ) . addClass ( " butActionRefused " );
}
2017-08-22 07:23:35 +00:00
});
2012-08-13 18:53:48 +00:00
// Show another element
} else if ( type == " showhide " || type == " show " ) {
$ . each ( data , function ( key , value ) {
2013-03-13 22:05:34 +00:00
var newvalue = (( value . search ( " ^# " ) < 0 && value . search ( " ^ \ . " ) < 0 ) ? " # " : " " ) + value ;
$ ( newvalue ) . show ();
2012-08-13 18:53:48 +00:00
});
// Set another constant
} else if ( type == " set " ) {
$ . each ( data , function ( key , value ) {
$ ( " #set_ " + key ) . hide ();
$ ( " #del_ " + key ) . show ();
2021-02-23 15:56:45 +00:00
$ . post ( saved_url , {
2012-08-13 18:53:48 +00:00
action : " set " ,
name : key ,
value : value ,
2021-02-22 16:33:54 +00:00
entity : entity ,
token : token
2012-08-13 18:53:48 +00:00
});
});
}
});
2026-04-20 20:22:06 +00:00
// Execute js context Dolibarr Hooks
if ( typeof Dolibarr != 'undefined' ) {
Dolibarr . executeHook ( 'setConstant' , { url : saved_url , code , input , entity , strict , forcereload , userid , token , value , userconst });
}
2020-02-18 08:37:59 +00:00
if ( forcereload ) {
2022-02-06 21:11:44 +00:00
var url = window . location . href ;
2025-07-17 16:12:46 +00:00
/* reset action param */
url = url . replace ( / action = \w +/ g , '' );
/* reset dol_resetcache param */
2022-02-06 21:11:44 +00:00
if ( url . indexOf ( 'dol_resetcache' ) < 0 ) {
if ( url . indexOf ( '?' ) > - 1 ) {
url = url + " &dol_resetcache=1 " ;
} else {
url = url + " ?dol_resetcache=1 " ;
}
}
2025-07-17 16:12:46 +00:00
/* reset page_y param */
2022-05-09 09:45:44 +00:00
var page_y = $ ( document ) . scrollTop ();
url = url . replace ( / page_y = \d +/ g , '' );
if ( page_y > 0 ) {
if ( url . indexOf ( '?' ) > - 1 ) {
url = url + " &page_y= " + page_y ;
} else {
url = url + " ?page_y= " + page_y ;
}
}
url = url . replace ( /&&+/ , '&' );
console . log ( " url ro redirect = " + url );
2022-02-06 21:11:44 +00:00
window . location . href = url ;
//location.reload();
return false ;
2020-02-18 08:37:59 +00:00
}
2026-04-20 20:22:06 +00:00
}) . fail ( function ( error ) { console . error ( " Error, we force reload " ); location . reload (); }); /* When it fails, we always force reload to have setEventErrorMessages in session visible */
2023-05-01 12:33:08 +00:00
return true ;
2012-08-13 18:53:48 +00:00
}
2011-02-05 03:28:56 +00:00
2012-08-13 18:53:48 +00:00
/*
2017-02-04 10:02:10 +00:00
* Used by button to set on / off
2020-09-18 23:45:40 +00:00
* Call url then make complementary action ( like show / hide , enable / disable or set another option ) .
2017-02-04 10:02:10 +00:00
*
2024-10-30 01:38:59 +00:00
* @ param string url Url ( warning : as any url called in ajax mode , the url called here must not renew the token )
* @ param string code Code
* @ param string input Array of complementary actions to do if success
* @ param int entity Entity
* @ param int strict Strict
* @ param int forcereload Force reload
* @ param int userid User id
* @ param string token Token
* @ param int userconst 1 = On / Off of user constant instead of global const
2023-05-01 12:33:08 +00:00
* @ return boolean
2012-08-13 18:53:48 +00:00
*/
2024-10-30 01:38:59 +00:00
function delConstant ( url , code , input , entity , strict , forcereload , userid , token , userconst ) {
2021-02-23 15:56:45 +00:00
var saved_url = url ; /* avoid undefined url */
2024-10-30 01:38:59 +00:00
2020-09-19 10:50:47 +00:00
$ . post ( url , {
2012-08-13 18:53:48 +00:00
action : " del " ,
name : code ,
2020-09-18 23:45:40 +00:00
entity : entity ,
2024-10-30 01:38:59 +00:00
token : token ,
userconst : userconst
2012-08-13 18:53:48 +00:00
},
function () {
2022-02-06 21:11:44 +00:00
console . log ( " Ajax url request to delete constant is success. Make complementary actions and then forcereload= " + forcereload );
2012-08-13 18:53:48 +00:00
$ ( " #del_ " + code ) . hide ();
$ ( " #set_ " + code ) . show ();
$ . each ( input , function ( type , data ) {
// Disable another element
if ( type == " disabled " ) {
$ . each ( data , function ( key , value ) {
2013-03-13 22:05:34 +00:00
var newvalue = (( value . search ( " ^# " ) < 0 && value . search ( " ^ \ . " ) < 0 ) ? " # " : " " ) + value ;
$ ( newvalue ) . attr ( " disabled " , true );
if ( $ ( newvalue ) . hasClass ( " butAction " ) == true ) {
$ ( newvalue ) . removeClass ( " butAction " );
$ ( newvalue ) . addClass ( " butActionRefused " );
2012-08-13 18:53:48 +00:00
}
});
2014-08-17 13:12:20 +00:00
} else if ( type == " enabled " && strict != 1 ) {
2013-03-13 22:05:34 +00:00
$ . each ( data , function ( key , value ) {
var newvalue = (( value . search ( " ^# " ) < 0 && value . search ( " ^ \ . " ) < 0 ) ? " # " : " " ) + value ;
$ ( newvalue ) . removeAttr ( " disabled " );
if ( $ ( newvalue ) . hasClass ( " butActionRefused " ) == true ) {
$ ( newvalue ) . removeClass ( " butActionRefused " );
$ ( newvalue ) . addClass ( " butAction " );
}
2017-08-22 07:23:35 +00:00
});
2012-08-13 18:53:48 +00:00
// Hide another element
} else if ( type == " showhide " || type == " hide " ) {
$ . each ( data , function ( key , value ) {
2013-03-13 22:05:34 +00:00
var newvalue = (( value . search ( " ^# " ) < 0 && value . search ( " ^ \ . " ) < 0 ) ? " # " : " " ) + value ;
$ ( newvalue ) . hide ();
2012-08-13 18:53:48 +00:00
});
// Delete another constant
} else if ( type == " del " ) {
$ . each ( data , function ( key , value ) {
$ ( " #del_ " + value ) . hide ();
$ ( " #set_ " + value ) . show ();
2021-02-23 15:56:45 +00:00
$ . post ( saved_url , {
2012-08-13 18:53:48 +00:00
action : " del " ,
name : value ,
2021-02-22 16:33:54 +00:00
entity : entity ,
token : token
2012-08-13 18:53:48 +00:00
});
});
}
});
2026-04-20 20:22:06 +00:00
// Execute js context Dolibarr Hooks
if ( typeof Dolibarr != 'undefined' ) {
Dolibarr . executeHook ( 'delConstant' , { url : saved_url , code , input , entity , strict , forcereload , userid , token , userconst });
}
2020-02-18 08:37:59 +00:00
if ( forcereload ) {
2022-02-06 21:11:44 +00:00
var url = window . location . href ;
if ( url . indexOf ( 'dol_resetcache' ) < 0 ) {
if ( url . indexOf ( '?' ) > - 1 ) {
url = url + " &dol_resetcache=1 " ;
} else {
url = url + " ?dol_resetcache=1 " ;
}
}
2022-05-09 09:45:44 +00:00
var page_y = $ ( document ) . scrollTop ();
url = url . replace ( / page_y = \d +/ g , '' );
if ( page_y > 0 ) {
if ( url . indexOf ( '?' ) > - 1 ) {
url = url + " &page_y= " + page_y ;
} else {
url = url + " ?page_y= " + page_y ;
}
}
url = url . replace ( /&&+/ , '&' );
console . log ( " url ro redirect = " + url );
2022-02-06 21:11:44 +00:00
window . location . href = url ;
//location.reload();
return false ;
2020-02-18 08:37:59 +00:00
}
2022-02-06 21:11:44 +00:00
}) . fail ( function ( error ) { console . log ( " Error, we force reload " ); location . reload (); }); /* When it fails, we always force reload to have setEventErrorMessages in session visible */
2023-05-01 12:33:08 +00:00
return true ;
2012-08-13 18:53:48 +00:00
}
2011-02-05 03:28:56 +00:00
2012-08-13 18:53:48 +00:00
/*
2021-02-23 10:03:34 +00:00
* Call the setConstant or delConstant but with a confirmation before .
* Used by button to set on / off .
2017-02-04 10:02:10 +00:00
*
* @ param string action Action
* @ param string url Url
* @ param string code Code
2024-01-13 18:48:20 +00:00
* @ param string input Array of complementary actions to do if success
2017-02-04 10:02:10 +00:00
* @ param string box Box
* @ param int entity Entity
* @ param int yesButton yesButton
* @ param int noButton noButton
* @ param int strict Strict
2020-03-25 15:00:42 +00:00
* @ param int userid User id
2020-09-18 23:53:22 +00:00
* @ param string token Token
2023-05-01 12:33:08 +00:00
* @ return boolean
2012-08-13 18:53:48 +00:00
*/
2020-09-18 23:53:22 +00:00
function confirmConstantAction ( action , url , code , input , box , entity , yesButton , noButton , strict , userid , token ) {
2012-10-25 12:57:56 +00:00
var boxConfirm = box ;
2012-08-13 18:53:48 +00:00
$ ( " #confirm_ " + code )
2012-10-25 12:57:56 +00:00
. attr ( " title " , boxConfirm . title )
. html ( boxConfirm . content )
2012-08-13 18:53:48 +00:00
. dialog ({
resizable : false ,
height : 170 ,
width : 500 ,
modal : true ,
buttons : [
{
2012-12-01 14:45:05 +00:00
id : 'yesButton_' + code ,
2012-08-13 18:53:48 +00:00
text : yesButton ,
click : function () {
if ( action == " set " ) {
2021-08-05 12:42:28 +00:00
setConstant ( url , code , input , entity , strict , 0 , userid , token , 1 );
2012-08-13 18:53:48 +00:00
} else if ( action == " del " ) {
2020-09-18 23:53:22 +00:00
delConstant ( url , code , input , entity , strict , 0 , userid , token );
2012-08-13 18:53:48 +00:00
}
// Close dialog
$ ( this ) . dialog ( " close " );
2012-10-25 12:57:56 +00:00
// Execute another method
if ( boxConfirm . method ) {
var fnName = boxConfirm . method ;
2012-08-13 18:53:48 +00:00
if ( window . hasOwnProperty ( fnName )) {
window [ fnName ]();
}
}
}
},
{
2012-12-01 14:45:05 +00:00
id : 'noButton_' + code ,
2012-08-13 18:53:48 +00:00
text : noButton ,
click : function () {
$ ( this ) . dialog ( " close " );
}
}
]
});
2012-12-01 14:45:05 +00:00
// For information dialog box only, hide the noButton
if ( boxConfirm . info ) {
$ ( " #noButton_ " + code ) . button () . hide ();
}
2023-05-01 12:33:08 +00:00
return true ;
2012-08-13 18:53:48 +00:00
}
2011-02-05 03:28:56 +00:00
2017-10-21 17:05:24 +00:00
2017-08-22 07:23:35 +00:00
/*
* =================================================================
2012-10-26 22:23:16 +00:00
* This is to allow to transform all select box into ajax autocomplete box
2017-08-22 07:23:35 +00:00
* with just one line :
2013-11-16 17:12:13 +00:00
* $ ( function () { $ ( " #idofmylist " ) . combobox (); });
2017-08-22 07:23:35 +00:00
* Do not use it on large combo boxes
* =================================================================
2011-02-05 03:28:56 +00:00
*/
2012-03-15 09:14:54 +00:00
( function ( $ ) {
$ . widget ( " ui.combobox " , {
2013-01-29 14:22:07 +00:00
options : {
2013-09-05 18:28:24 +00:00
minLengthToAutocomplete : 0
2013-01-29 14:22:07 +00:00
},
2021-02-23 21:03:23 +00:00
_create : function () {
var savMinLengthToAutocomplete = this . options . minLengthToAutocomplete ;
var self = this ,
select = this . element . hide (),
selected = select . children ( " :selected " ),
value = selected . val () ? selected . text () : " " ;
var input = this . input = $ ( " <input> " )
. insertAfter ( select )
. val ( value )
. attr ( 'id' , 'inputautocomplete' + select . attr ( 'id' ))
. autocomplete ({
delay : 0 ,
minLength : this . options . minLengthToAutocomplete ,
source : function ( request , response ) {
var matcher = new RegExp ( $ . ui . autocomplete . escapeRegex ( request . term ), " i " );
response ( select . children ( " option:enabled " ) . map ( function () {
var text = $ ( this ) . text ();
if ( this . value && ( ! request . term || matcher . test ( text ) ) )
return {
label : text . replace (
new RegExp (
" (?![^&;]+;)(?!<[^<>]*)( " +
$ . ui . autocomplete . escapeRegex ( request . term ) +
" )(?![^<>]*>)(?![^&;]+;) " , " gi "
), " <strong> $ 1</strong> " ),
value : text ,
option : this
};
}) );
},
select : function ( event , ui ) {
ui . item . option . selected = true ;
self . _trigger ( " selected " , event , {
item : ui . item . option
});
},
change : function ( event , ui ) {
if ( ! ui . item ) {
var matcher = new RegExp ( " ^ " + $ . ui . autocomplete . escapeRegex ( $ ( this ) . val () ) + " $ " , " i " ),
valid = false ;
select . children ( " option " ) . each ( function () {
if ( $ ( this ) . text () . match ( matcher ) ) {
this . selected = valid = true ;
return false ;
}
});
if ( ! valid ) {
2024-01-13 18:48:20 +00:00
// remove invalid value, as it didn't match anything
2021-02-23 21:03:23 +00:00
$ ( this ) . val ( " " );
select . val ( " " );
input . data ( " ui-autocomplete " ) . term = " " ;
return false ;
}
}
}
})
. addClass ( " ui-widget ui-widget-content ui-corner-left dolibarrcombobox " );
2026-03-25 00:14:37 +00:00
const widgetInstance = input . data ( " ui-autocomplete " );
if ( widgetInstance ) {
widgetInstance . _renderItem = function ( ul , item ) {
return $ ( " <li> " )
. data ( " ui-autocomplete-item " , item ) // jQuery UI > 1.10.0
. append ( " <a> " + item . label + " </a> " )
. appendTo ( ul );
};
}
2021-02-23 21:03:23 +00:00
this . button = $ ( " <button type= \ 'button \ '> </button> " )
. attr ( " tabIndex " , - 1 )
. attr ( " title " , " Show All Items " )
. insertAfter ( input )
. button ({
icons : {
primary : " ui-icon-triangle-1-s "
},
text : false
})
. removeClass ( " ui-corner-all " )
. addClass ( " ui-corner-right ui-button-icon " )
. click ( function () {
// close if already visible
if ( input . autocomplete ( " widget " ) . is ( " :visible " ) ) {
input . autocomplete ( " close " );
return ;
}
// pass empty string as value to search for, displaying all results
input . autocomplete ({ minLength : 0 });
input . autocomplete ( " search " , " " );
input . autocomplete ({ minLength : savMinLengthToAutocomplete });
input . focus ();
});
},
destroy : function () {
this . input . remove ();
this . button . remove ();
this . element . show ();
$ . Widget . prototype . destroy . call ( this );
}
});
2011-02-05 03:28:56 +00:00
})( jQuery );
2012-08-22 15:42:40 +00:00
2014-02-19 10:08:43 +00:00
2017-10-21 17:05:24 +00:00
2017-02-04 10:02:10 +00:00
/**
2019-03-09 17:37:07 +00:00
* Function to output a dialog box for copy / paste
2017-08-22 07:23:35 +00:00
*
2026-05-12 00:53:35 +00:00
* @ param text Text to put into copy / paste area
* @ param text2 Text to put under the copy / paste area
* @ param popupTitle Text to show as title
2014-02-19 10:08:43 +00:00
*/
2026-05-12 00:53:35 +00:00
function copyToClipboard ( text , text2 , popupTitle = '' )
2014-02-19 10:08:43 +00:00
{
text = text . replace ( /< br >/ g , " \n " );
2016-01-01 23:27:14 +00:00
var newElem = '<textarea id="coordsforpopup" style="border: none; width: 90%; height: 120px;">' + text + '</textarea><br><br>' + text2 ;
/* alert(newElem); */
$ ( " #dialogforpopup " ) . html ( newElem );
2026-05-12 00:53:35 +00:00
$ ( " #dialogforpopup " ) . dialog ({ title : popupTitle });
2016-01-01 23:27:14 +00:00
$ ( " #coordsforpopup " ) . select ();
2023-05-01 12:33:08 +00:00
2014-02-19 10:08:43 +00:00
return false ;
}
2016-08-05 13:30:28 +00:00
2017-02-04 10:02:10 +00:00
/**
* Show a popup HTML page . Use the " window.open " function .
2017-08-22 07:23:35 +00:00
*
2023-05-01 12:33:08 +00:00
* @ param url Url
* @ param title Title of popup
* @ return boolean False
2025-12-13 12:47:19 +00:00
* @ see document_preview () and confirmDolibarr ()
2017-02-04 10:02:10 +00:00
*/
2019-05-22 14:08:21 +00:00
function newpopup ( url , title ) {
2017-02-04 10:02:10 +00:00
var argv = newpopup . arguments ;
var argc = newpopup . arguments . length ;
2023-06-29 11:47:28 +00:00
var tmp = url ;
2019-05-22 14:08:21 +00:00
console . log ( " newpopup " + argv [ 2 ] + " " + argv [ 3 ]);
2017-02-04 10:02:10 +00:00
var l = ( argc > 2 ) ? argv [ 2 ] : 600 ;
var h = ( argc > 3 ) ? argv [ 3 ] : 400 ;
var left = ( screen . width - l ) / 2 ;
var top = ( screen . height - h ) / 2 ;
2024-07-14 15:23:42 +00:00
var wfeatures = " directories=0,menubar=0,status=0,resizable=0,scrollbars=1,toolbar=0,location=0,width= " + l + " ,height= " + h + " ,left= " + left + " ,top= " + top ;
fen = window . open ( tmp , title , wfeatures );
2023-05-01 12:33:08 +00:00
2017-02-04 10:02:10 +00:00
return false ;
}
/**
2025-06-06 00:09:42 +00:00
* Function to show a document preview popup . It uses the " dialog " function .
* The " a " tag around the " img " must have the src = '' , class = 'documentpreview' , mime = 'image/xxx' , target = '_blank' from getAdvancedPreviewUrl () .
2016-08-05 10:18:51 +00:00
*
2023-05-01 12:33:08 +00:00
* @ param file Url
* @ param type Mime file type ( " image/jpeg " , " application/pdf " , " text/html " )
* @ param title Title of popup
2017-02-04 10:02:10 +00:00
* @ return void
2025-12-13 12:47:19 +00:00
* @ see also confirmDolibarr () that also make a dialogforpopup . dialog ()
* @ see also newpopup () that use window . open
2016-08-02 01:35:22 +00:00
*/
2016-08-05 10:18:51 +00:00
function document_preview ( file , type , title )
{
2020-06-03 12:05:18 +00:00
var ValidImageTypes = [ " image/gif " , " image/jpeg " , " image/png " , " image/webp " ];
2017-08-22 11:14:10 +00:00
var showOriginalSizeButton = false ;
2023-10-21 00:39:27 +00:00
console . log ( " document_preview A click was done: file= " + file + " , type= " + type + " , title= " + title );
2017-08-22 07:23:35 +00:00
2016-08-02 01:35:22 +00:00
if ( $ . inArray ( type , ValidImageTypes ) < 0 ) {
2020-06-03 12:05:18 +00:00
/* Not an image */
2025-07-23 12:43:51 +00:00
var object_width = '100%' ;
var object_height = '98%' ;
2016-08-02 01:35:22 +00:00
2025-07-24 13:39:37 +00:00
var popupWidth = '85%' ;
var popupHeight = $ ( window ) . height () * 0.90 - 100 ;
2017-08-22 11:14:10 +00:00
show_preview ( 'notimage' );
2016-08-02 01:35:22 +00:00
} else {
2020-06-03 12:05:18 +00:00
/* This is an image */
2025-07-23 12:43:51 +00:00
var object_width = 0 ;
var object_height = 0 ;
2016-08-02 01:35:22 +00:00
var img = new Image ();
2025-07-23 12:43:51 +00:00
img . src = file ;
2016-08-02 01:35:22 +00:00
img . onload = function () {
2025-07-23 12:43:51 +00:00
object_width = this . width ; /* the real width of image */
object_height = this . height ; /* the real height of image */
/* Complete title with size of image */
title = title + ' (' + object_width + ' x ' + object_height + ')' ;
2016-08-02 01:35:22 +00:00
2025-07-24 13:39:37 +00:00
popupWidth = $ ( window ) . width () * 0.85 - 50 ;
2025-07-23 12:43:51 +00:00
console . log ( " object_width= " + object_width + " popup window width= " + popupWidth );
if ( object_width < popupWidth ) {
2017-08-22 11:14:10 +00:00
console . log ( " Object width is small, we set width of popup according to image width. " );
2025-07-23 12:43:51 +00:00
popupWidth = object_width + 50
2016-08-02 01:35:22 +00:00
}
2025-08-13 13:37:46 +00:00
if ( popupWidth < 250 ) { /* Set a minimal width because we need to have neough space for the buttons */
popupWidth = 250 ;
}
popupHeight = $ ( window ) . height () * 0.90 - 160 ;
2025-07-23 12:43:51 +00:00
console . log ( " object_height= " + object_height + " popup window height= " + popupHeight );
2025-08-13 13:37:46 +00:00
if ( object_height < ( popupHeight - 160 )) {
2017-08-22 11:14:10 +00:00
console . log ( " Object height is small, we set height of popup according to image height. " );
2025-08-13 13:37:46 +00:00
popupHeight = object_height + 160
2025-07-23 12:43:51 +00:00
} else {
2017-08-22 11:14:10 +00:00
showOriginalSizeButton = true ;
}
2016-08-02 01:35:22 +00:00
2025-08-13 13:37:46 +00:00
console . log ( " popupWidth= " + popupWidth + " popupHeight= " + popupHeight );
2017-08-22 11:14:10 +00:00
show_preview ( 'image' );
2016-08-02 01:35:22 +00:00
};
}
2022-05-03 10:08:24 +00:00
2024-12-28 16:38:05 +00:00
/* This function is local to document_preview. Variables like file, type, title, object_width and object_height are global inside this function */
2017-08-22 11:14:10 +00:00
function show_preview ( mode ) {
2025-07-23 12:43:51 +00:00
/* console.log("mode="+mode+" file="+file+" type="+type+" title=title+" width="+popupWidth+" height="+popupHeight); */
2017-05-18 11:01:48 +00:00
var newElem = '<object name="objectpreview" data="' + file + '" type="' + type + '" width="' + object_width + '" height="' + object_height + '" param="noparam"></object>' ;
2016-08-02 01:35:22 +00:00
2017-08-22 11:14:10 +00:00
optionsbuttons = {}
2025-07-23 12:43:51 +00:00
if ( mode == 'image' ) {
2023-08-08 18:40:42 +00:00
var curRot = 0 ;
2025-07-23 12:43:51 +00:00
var savMaxHeight = 0 ;
2017-08-22 11:14:10 +00:00
optionsbuttons = {
2025-07-23 12:43:51 +00:00
'<?php echo dol_escape_js($langs->transnoentitiesnoconv("RotateImage")); ?>' : function () { curRot += 90 ; jQuery ( " .ui-dialog-content.ui-widget-content > object " ) . css ( " transform " , " rotate( " + curRot + " deg) " ); },
2025-08-13 13:37:46 +00:00
'<?php echo dol_escape_js($langs->transnoentitiesnoconv("CloseWindowShort")); ?>' : function () { $ ( this ) . dialog ( " close " ); }
2025-07-23 12:43:51 +00:00
};
if ( showOriginalSizeButton ) {
optionsbuttons = {
'<?php echo dol_escape_js($langs->transnoentitiesnoconv("OriginalSize")); ?>' : function () { console . log ( " Click on original size button " ); savMaxHeight = jQuery ( " .ui-dialog-content.ui-widget-content > object " ) . css ( " max-height " ); console . log ( " savMaxHeight= " + savMaxHeight ); jQuery ( " .ui-dialog-content.ui-widget-content > object " ) . css ({ " max-height " : ( savMaxHeight == " none " ? " 100% " : " none " ) }); },
... optionsbuttons
2017-08-22 11:14:10 +00:00
};
2025-07-23 12:43:51 +00:00
}
2017-08-22 11:14:10 +00:00
}
2025-06-06 00:09:42 +00:00
$ ( " #dialogforpopup " ) . addClass ( " center " );
2016-08-02 01:35:22 +00:00
$ ( " #dialogforpopup " ) . html ( newElem );
2022-05-03 10:08:24 +00:00
2016-08-02 01:35:22 +00:00
$ ( " #dialogforpopup " ) . dialog ({
closeOnEscape : true ,
resizable : true ,
2025-07-23 12:43:51 +00:00
width : popupWidth ,
height : popupHeight ,
2016-08-02 01:35:22 +00:00
modal : true ,
2017-08-22 11:14:10 +00:00
title : title ,
buttons : optionsbuttons
2016-08-02 01:35:22 +00:00
});
2017-08-22 11:14:10 +00:00
2025-07-23 12:43:51 +00:00
if ( showOriginalSizeButton ) {
2017-08-22 11:14:10 +00:00
jQuery ( " .ui-dialog-content.ui-widget-content > object " ) . css ({ " max-height " : " 100% " , " width " : " auto " , " margin-left " : " auto " , " margin-right " : " auto " , " display " : " block " });
}
2016-08-02 01:35:22 +00:00
}
}
2015-11-13 02:35:55 +00:00
/*
2017-08-22 07:23:35 +00:00
* Provide a function to get an URL GET parameter in javascript
*
2023-05-01 12:33:08 +00:00
* @ param name Name of parameter
* @ param valueifnotfound Value if not found
* @ return string Value
2012-08-22 15:42:40 +00:00
*/
2017-08-22 07:23:35 +00:00
function getParameterByName ( name , valueifnotfound )
2015-11-13 02:35:55 +00:00
{
2021-02-23 21:03:23 +00:00
name = name . replace ( / [ \ [] / , " \\ [ " ) . replace ( / [ \ ]] / , " \\ ] " );
var regex = new RegExp ( " [ \\ ?&] " + name + " =([^&#]*) " ),
results = regex . exec ( location . search );
return results === null ? valueifnotfound : decodeURIComponent ( results [ 1 ] . replace ( / \ +/ g , " " ));
2015-11-13 02:35:55 +00:00
}
2015-12-07 14:10:23 +00:00
2024-10-30 20:29:41 +00:00
/**
2025-02-22 12:57:07 +00:00
* Get the list of possible operators for a given field type that we can use in the generic filter .
2024-10-30 20:29:41 +00:00
*/
2024-12-01 22:32:32 +00:00
function getOperatorsForFieldType ( type , maybenull = 0 ) {
2025-02-22 12:57:07 +00:00
console . log ( 'Get list of operators for type=' + type );
2024-10-30 20:29:41 +00:00
// Define the list of operators for each general field category
const operatorList = {
2024-11-19 17:07:35 +00:00
selectlink : {
Is : '<?php print dol_escape_js($langs->trans(' Is ')); ?>' ,
IsNot : '<?php print dol_escape_js($langs->trans(' IsNot ')); ?>' ,
},
2024-10-30 20:29:41 +00:00
text : {
2024-11-05 00:43:48 +00:00
Contains : '<?php print dol_escape_js($langs->trans(' Contains ')); ?>' ,
DoesNotContain : '<?php print dol_escape_js($langs->trans(' DoesNotContain ')); ?>' ,
Is : '<?php print dol_escape_js($langs->trans(' Is ')); ?>' ,
IsNot : '<?php print dol_escape_js($langs->trans(' IsNot ')); ?>' ,
StartsWith : '<?php print dol_escape_js($langs->trans(' StartsWith ')); ?>' ,
EndsWith : '<?php print dol_escape_js($langs->trans(' EndsWith ')); ?>'
2024-10-30 20:29:41 +00:00
},
number : {
2024-11-05 00:43:48 +00:00
'=' : '<?php print dol_escape_js($langs->trans(' Is ')); ?>' ,
'!=' : '<?php print dol_escape_js($langs->trans(' IsNot ')); ?>' ,
'<' : '<?php print dol_escape_js($langs->trans(' IsLowerThan ')); ?>' ,
'>' : '<?php print dol_escape_js($langs->trans(' IsHigherThan ')); ?>' ,
'<=' : '<?php print dol_escape_js($langs->trans(' IsLowerThanOrEqual ')); ?>' ,
'>=' : '<?php print dol_escape_js($langs->trans(' IsHigherThanOrEqual ')); ?>' ,
2024-10-30 20:29:41 +00:00
},
date : {
2024-11-05 00:43:48 +00:00
Is : '<?php print dol_escape_js($langs->trans(' Is ')); ?>' ,
IsNot : '<?php print dol_escape_js($langs->trans(' IsNot ')); ?>' ,
IsBefore : '<?php print dol_escape_js($langs->trans(' IsBefore ')); ?>' ,
IsAfter : '<?php print dol_escape_js($langs->trans(' IsAfter ')); ?>' ,
IsOnOrBefore : '<?php print dol_escape_js($langs->trans(' IsOnOrBefore ')); ?>' ,
IsOnOrAfter : '<?php print dol_escape_js($langs->trans(' IsOnOrAfter ')); ?>'
2024-10-30 20:29:41 +00:00
},
html : {
2024-11-05 00:43:48 +00:00
Contains : '<?php print $langs->trans(' Contains '); ?>'
2024-10-30 20:29:41 +00:00
}
};
// Determine the general category for the given type using regex
let generalType = " " ;
2024-12-01 22:32:32 +00:00
if ( /^ select $ / i . test ( type ) || /^ link $ / i . test ( type )) {
generalType = " selectlink " ;
2025-02-22 12:57:07 +00:00
} else if ( /^ ( varchar | char | text | blob | nchar | mediumtext | longtext ) \ ( \d + \ ) $ / i . test ( type ) || /^ ( varchar | mail | phone | ip ) $ / i . test ( type )) {
2024-10-30 20:29:41 +00:00
generalType = " text " ;
} else if ( /^ ( int | integer | float | double | decimal | numeric )( \ ( \d + , \d + \ )) ? $ / i . test ( type )) {
generalType = " number " ;
} else if ( /^ ( date | datetime | timestamp ) $ / i . test ( type )) {
generalType = " date " ;
} else if ( /^ ( tinyint | smallint ) \ ( \d + \ ) $ / i . test ( type )) {
generalType = " number " ;
} else if ( /^ html $ / i . test ( type )) {
generalType = " html " ;
} else {
// Handle unknown or unsupported types
2024-11-19 17:07:35 +00:00
console . log ( " The type of field " + type + " is not supported " );
2024-10-30 20:29:41 +00:00
return [];
}
2024-12-01 22:32:32 +00:00
// If maybenull is true, then append the "IsDefined" and "IsNotDefined" operators
if ( maybenull === 1 ) {
operatorList [ generalType ][ " IsDefined " ] = '<?php print dol_escape_js($langs->trans(' IsDefined ')); ?>' ;
operatorList [ generalType ][ " IsNotDefined " ] = '<?php print dol_escape_js($langs->trans(' IsNotDefined ')); ?>' ;
}
2024-10-30 20:29:41 +00:00
// Return the operators for the general type, or an empty array if not found
return operatorList [ generalType ] || [];
}
/**
* Generate a filter string based on the given column , operator , context and field type
*/
function generateFilterString ( column , operator , context , fieldType ) {
let filter = " " ;
2025-04-25 14:43:31 +00:00
console . log ( " generateFilterString column= " + column + " operator= " + operator + " context= " + context + " fieldType= " + fieldType );
2024-10-30 20:29:41 +00:00
switch ( operator ) {
case " Contains " :
filter = column + " like \ '% " + context + " % \ ' " ;
break ;
case " DoesNotContain " :
filter = column + " notlike \ '% " + context + " % \ ' " ;
break ;
case " Is " :
filter = column + " = \ ' " + context + " \ ' " ;
break ;
case " IsNot " :
filter = column + " != \ ' " + context + " \ ' " ;
break ;
case " StartsWith " :
filter = column + " like \ ' " + context + " % \ ' " ;
break ;
case " EndsWith " :
filter = column + " like \ '% " + context + " \ ' " ;
break ;
2024-12-01 22:32:32 +00:00
case " IsDefined " :
filter = column + " :isnot:null " ;
break ;
case " IsNotDefined " :
filter = column + " :is:null " ;
break ;
2024-10-30 20:29:41 +00:00
case " = " :
filter = column + " = \ ' " + context + " \ ' " ;
break ;
case " != " :
filter = column + " != \ ' " + context + " \ ' " ;
break ;
case " < " :
filter = column + " < \ ' " + context + " \ ' " ;
break ;
case " > " :
filter = column + " > \ ' " + context + " \ ' " ;
break ;
case " <= " :
filter = column + " <= \ ' " + context + " \ ' " ;
break ;
case " >= " :
filter = column + " >= \ ' " + context + " \ ' " ;
break ;
case " IsBefore " :
filter = column + " < \ ' " + context + " \ ' " ;
break ;
case " IsAfter " :
filter = column + " > \ ' " + context + " \ ' " ;
break ;
case " IsOnOrBefore " :
filter = column + " <= \ ' " + context + " \ ' " ;
break ;
case " IsOnOrAfter " :
filter = column + " >= \ ' " + context + " \ ' " ;
break ;
default :
filter = " " ;
}
return filter ;
}
2017-02-04 10:02:10 +00:00
2015-12-07 14:10:23 +00:00
// Code in the public domain from https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/round
( function () {
/**
* Decimal adjustment of a number .
*
* @ param { String } type The type of adjustment .
* @ param { Number } value The number .
* @ param { Integer } exp The exponent ( the 10 logarithm of the adjustment base ) .
* @ returns { Number } The adjusted value .
*/
function decimalAdjust ( type , value , exp ) {
// If the exp is undefined or zero...
if ( typeof exp === 'undefined' || + exp === 0 ) {
return Math [ type ]( value );
}
value = + value ;
exp = + exp ;
// If the value is not a number or the exp is not an integer...
if ( isNaN ( value ) || ! ( typeof exp === 'number' && exp % 1 === 0 )) {
return NaN ;
}
// Shift
value = value . toString () . split ( 'e' );
value = Math [ type ]( + ( value [ 0 ] + 'e' + ( value [ 1 ] ? ( + value [ 1 ] - exp ) : - exp )));
// Shift back
value = value . toString () . split ( 'e' );
return + ( value [ 0 ] + 'e' + ( value [ 1 ] ? ( + value [ 1 ] + exp ) : exp ));
}
// Decimal round
if ( ! Math . round10 ) {
Math . round10 = function ( value , exp ) {
return decimalAdjust ( 'round' , value , exp );
};
}
// Decimal floor
if ( ! Math . floor10 ) {
Math . floor10 = function ( value , exp ) {
return decimalAdjust ( 'floor' , value , exp );
};
}
// Decimal ceil
if ( ! Math . ceil10 ) {
Math . ceil10 = function ( value , exp ) {
return decimalAdjust ( 'ceil' , value , exp );
};
}
})();
2026-07-23 09:44:05 +00:00
2017-08-22 07:23:35 +00:00
// Another solution, easier, to build a javascript rounding function
2016-07-27 16:49:34 +00:00
function dolroundjs ( number , decimals ) { return + ( Math . round ( number + " e+ " + decimals ) + " e- " + decimals ); }
2026-07-23 09:44:05 +00:00
2019-03-27 11:40:32 +00:00
/**
* Function similar to PHP price ()
*
2022-05-06 16:30:19 +00:00
* Example use :
2022-05-06 16:38:10 +00:00
* pricejs ( 13312.448 , 'MT' , 'EUR' , 'fr_FR' )
2022-05-06 16:30:19 +00:00
* // (depending on conf for 'MT'): '13 312.45 €'
*
* pricejs ( 343000.121 , 'MT' )
2022-05-06 16:50:02 +00:00
* // assuming conf for 'MT' is 2 and $langs->defaultlang is 'en_US': '343,000.12'
2022-05-06 16:30:19 +00:00
*
2019-03-27 11:40:32 +00:00
* @ param { number | string } amount The amount to show
* @ param { string } mode 'MT' or 'MU'
2022-05-06 16:30:19 +00:00
* @ param { string } currency_code ISO code of currency ( empty by default )
* @ param { string } force_locale ISO code locale to use ( if empty , will use Dolibarr ' s current locale code )
2019-03-27 11:40:32 +00:00
* @ return { string } The amount with digits
2022-05-06 16:30:19 +00:00
*
2019-03-27 11:40:32 +00:00
*/
2022-05-06 16:38:10 +00:00
function pricejs ( amount , mode = 'MT' , currency_code = '' , force_locale = '' ) {
2024-03-19 17:49:01 +00:00
var main_max_dec_shown = < ? php echo ( int ) str_replace ( '.' , '' , getDolGlobalString ( 'MAIN_MAX_DECIMALS_SHOWN' )); ?> ;
2023-04-30 01:57:10 +00:00
var main_rounding_unit = < ? php echo ( int ) getDolGlobalInt ( 'MAIN_MAX_DECIMALS_UNIT' ); ?> ;
var main_rounding_tot = < ? php echo ( int ) getDolGlobalInt ( 'MAIN_MAX_DECIMALS_TOT' ); ?> ;
2022-05-06 16:30:19 +00:00
var main_decimal_separator = < ? php echo json_encode ( $dec ) ?> ;
var main_thousand_separator = < ? php echo json_encode ( $thousand ) ?> ;
var locale_code = force_locale || < ? php echo json_encode ( $langs -> defaultlang ) ?> ;
var amountAsLocalizedString ;
2022-05-06 16:38:10 +00:00
var useIntl = Boolean ( Intl && Intl . NumberFormat );
2022-05-06 16:30:19 +00:00
var nDigits ;
2025-11-18 11:03:23 +00:00
if ( currency_code === 'auto' ) currency_code = < ? php echo json_encode ( getDolCurrency ()) ?> ;
2022-05-06 16:30:19 +00:00
if ( mode === 'MU' ) nDigits = main_rounding_unit ;
else if ( mode === 'MT' ) nDigits = main_rounding_tot ;
else return 'Bad value for parameter mode' ;
if ( useIntl ) {
2022-05-06 16:38:10 +00:00
// simple version: let the browser decide how to format the number using the provided language / currency
// parameters
2022-05-06 16:30:19 +00:00
var formattingOptions = {
minimumFractionDigits : nDigits ,
maximumFractionDigits : nDigits
};
if ( currency_code ) {
formattingOptions [ 'style' ] = 'currency' ;
formattingOptions [ 'currency' ] = currency_code ;
}
return Intl . NumberFormat ( locale_code . replace ( '_' , '-' ), formattingOptions ) . format ( amount );
}
// No Intl -> attempt to format the number in a way similar to Dolibarr PHP's `price()` function
amountAsLocalizedString = amount . toFixed ( nDigits ) . replace (
/ (( ? !^ )( ? : \d { 3 }) * )( ? : \ . ( \d + )) ? $ / ,
( fullMatch , digitsByThree , decimals ) =>
digitsByThree . replace (
/ \d { 3 } / g ,
( groupOfThree ) => main_thousand_separator + groupOfThree
) + ( decimals !== undefined ? main_decimal_separator + decimals : '' )
) . replace ( / / , '  ' );
if ( ! currency_code ) return amountAsLocalizedString ;
// print with currency
var currency_symbol = currency_code ;
// codes of languages / currencies where the symbol must be placed before the amount
var currencyBeforeAmountCodes = {
currency : [ 'AUD' , 'CAD' , 'CNY' , 'COP' , 'CLP' , 'GBP' , 'HKD' , 'MXN' , 'PEN' , 'USD' ],
language : [ 'nl_NL' ]
};
2019-03-27 11:40:32 +00:00
2022-05-06 16:30:19 +00:00
if ( currencyCache [ currency_code ]
&& currencyCache [ currency_code ][ 'unicode' ]
&& currencyCache [ currency_code ][ 'unicode' ] . length ) {
currency_symbol = currencyCache [ currency_code ][ 'unicode' ] . reduce ( function ( res , cur ) { return res + cur }, '' );
}
if ( currencyBeforeAmountCodes . currency . indexOf ( currency_code ) >= 0
|| currencyBeforeAmountCodes . language . indexOf ( locale_code )) {
// if we use a language or a currency where the symbol is placed before the amount
return currency_symbol + amountAsLocalizedString ;
}
// by default: currency symbol after the amount
return amountAsLocalizedString + '  ' + currency_symbol ;
2019-03-27 11:40:32 +00:00
}
2015-12-07 14:10:23 +00:00
/**
* Function similar to PHP price2num ()
*
2017-02-04 10:02:10 +00:00
* @ param { number | string } amount The amount to convert / clean
2023-05-01 13:09:43 +00:00
* @ return { number } The amount in universal numeric format ( Example : '99.99999' )
2015-12-07 14:10:23 +00:00
* @ todo Implement rounding parameter
*/
function price2numjs ( amount ) {
if ( amount == '' ) return '' ;
2026-03-01 13:00:16 +00:00
if ( amount == null ) return '' ; /* null or undefined */
2015-12-07 14:10:23 +00:00
2022-05-06 16:30:19 +00:00
var dec = < ? php echo json_encode ( $dec ) ?> ;
var thousand = < ? php echo json_encode ( $thousand ) ?> ;
2015-12-07 14:10:23 +00:00
2024-03-19 17:49:01 +00:00
var main_max_dec_shown = < ? php echo ( int ) str_replace ( '.' , '' , getDolGlobalString ( 'MAIN_MAX_DECIMALS_SHOWN' )); ?> ;
2023-04-30 01:57:10 +00:00
var main_rounding_unit = < ? php echo ( int ) getDolGlobalInt ( 'MAIN_MAX_DECIMALS_UNIT' ); ?> ;
var main_rounding_tot = < ? php echo ( int ) getDolGlobalInt ( 'MAIN_MAX_DECIMALS_TOT' ); ?> ;
2015-12-07 14:10:23 +00:00
var amount = amount . toString ();
// rounding for unit price
var rounding = main_rounding_unit ;
var pos = amount . indexOf ( dec );
var decpart = '' ;
2023-05-01 13:09:43 +00:00
if ( pos >= 0 ) {
decpart = amount . substring ( pos + 1 ) . replace ( '/0+$/i' , '' ); // Remove 0 for decimal part
}
2015-12-07 14:10:23 +00:00
var nbdec = decpart . length ;
2023-05-01 13:09:43 +00:00
if ( nbdec > rounding ) {
rounding = nbdec ;
}
2015-12-07 14:10:23 +00:00
// If rounding higher than max shown
if ( rounding > main_max_dec_shown ) rounding = main_max_dec_shown ;
if ( thousand != ',' && thousand != '.' ) amount = amount . replace ( ',' , '.' );
2017-10-21 17:05:24 +00:00
amount = amount . replace ( ' ' , '' ); // To avoid spaces
2015-12-07 14:10:23 +00:00
amount = amount . replace ( thousand , '' ); // Replace of thousand before replace of dec to avoid pb if thousand is .
amount = amount . replace ( dec , '.' );
2023-05-01 13:09:43 +00:00
2024-01-13 18:48:20 +00:00
//console.log("amount before="+amount+" rounding="+rounding)
2016-07-27 16:49:34 +00:00
var res = Math . round10 ( amount , - rounding );
2017-08-22 07:23:35 +00:00
// Other solution is
2016-07-27 16:49:34 +00:00
// var res = dolroundjs(amount, rounding)
2023-05-01 13:09:43 +00:00
2021-09-16 11:07:02 +00:00
console . log ( " price2numjs text= " + amount + " return= " + res );
2023-05-01 13:09:43 +00:00
2016-07-27 16:49:34 +00:00
return res ;
2015-12-07 14:10:23 +00:00
}
2017-08-22 07:23:35 +00:00
2016-08-05 13:30:28 +00:00
2017-11-19 11:22:01 +00:00
< ? php
2023-11-27 10:39:32 +00:00
if ( ! getDolGlobalString ( 'MAIN_DISABLE_JQUERY_JNOTIFY' ) && ! defined ( 'DISABLE_JQUERY_JNOTIFY' )) {
2020-10-31 13:32:18 +00:00
?>
2017-11-19 11:22:01 +00:00
// Defined properties for JNotify
$ ( document ) . ready ( function () {
2023-05-09 15:32:17 +00:00
if ( typeof $ . jnotify == 'function' ) {
2017-11-24 13:23:25 +00:00
$ . jnotify . setup ({
delay : 3000 // the default time to show each notification (in milliseconds)
, sticky : false // determines if the message should be considered "sticky" (user must manually close notification)
, closeLabel : " × " // the HTML to use for the "Close" link
, showClose : true // determines if the "Close" link should be shown if notification is also sticky
, fadeSpeed : 1000 // the speed to fade messages out (in milliseconds)
, slideSpeed : 250 // the speed used to slide messages out (in milliseconds)
, classContainer : " jnotify-container "
2023-05-09 15:32:17 +00:00
, classNotification : " jnotify-notification "
, classBackground : " jnotify-background "
, classClose : " jnotify-close "
, classMessage : " jnotify-message "
, init : null // callback that occurs when the main jnotify container is created
, create : null // callback that occurs when when the note is created (occurs just before appearing in DOM)
, beforeRemove : null // callback that occurs when before the notification starts to fade away
2017-11-24 13:23:25 +00:00
});
}
2017-11-19 11:22:01 +00:00
});
2023-12-04 11:05:17 +00:00
< ? php
} ?>
2017-11-19 15:30:05 +00:00
2023-12-19 21:32:49 +00:00
2023-12-19 21:32:49 +00:00
2023-05-09 15:32:17 +00:00
jQuery ( document ) . ready ( function () {
// Force to hide menus when page is inside an iFrame so we can show any page into a dialog popup
2025-04-08 16:18:05 +00:00
if ( window . location && window . location . pathname . indexOf ( " core/frames.php " ) == - 1 && window . location . pathname . indexOf ( " externalsite/frametop.php " ) == - 1 && window . location !== window . parent . location ) {
2020-09-23 14:36:19 +00:00
console . log ( " Page is detected to be into an iframe, we hide by CSS the menus " );
// The page is in an iframe
2020-10-31 02:50:16 +00:00
jQuery ( " .side-nav-vert, .side-nav, .websitebar " ) . hide ();
2020-09-23 14:36:19 +00:00
jQuery ( " .id-container " ) . css ( 'width' , '100%' );
}
2023-05-09 15:32:17 +00:00
2025-05-05 11:24:11 +00:00
2023-05-09 15:32:17 +00:00
// Code to set tooltip on search field
2023-10-18 11:50:04 +00:00
jQuery ( 'table.liste tr.liste_titre_filter td.liste_titre input[name^="search"][type=text]:not(".maxwidthdate")' ) . attr ( 'title' , '<?php echo dol_escape_js($langs->transnoentities("SearchSyntaxTooltipForStringOrNum")) ?>' );
2020-09-23 14:36:19 +00:00
2022-04-07 15:51:38 +00:00
2025-05-05 11:24:11 +00:00
// Code to toggle dropdown components
2024-10-03 17:30:06 +00:00
jQuery ( document ) . on ( " click " , " .butAction.dropdown-toggle " , function ( event ) {
2023-12-19 21:32:49 +00:00
console . log ( " Click on .butAction.dropdown-toggle " );
2024-09-23 02:02:32 +00:00
let parentHolder = jQuery ( event . target ) . parent ();
let dropDownContent = parentHolder . children ( " .dropdown-content " );
let offset = parentHolder . offset ();
let widthDocument = $ ( document ) . width ();
let heightDocument = $ ( document ) . height ();
let right = widthDocument - offset . left - parentHolder . width ();
let widthPopup = parentHolder . children ( " .dropdown-content " ) . width ();
if ( widthPopup + right >= widthDocument ) {
//right = 10;
}
2024-10-06 19:55:46 +00:00
parentHolder . toggleClass ( " open " ); /* If open, it closes, if closed, it opens */
2024-09-23 02:02:32 +00:00
// Check tooltip is in viewport
let dropDownContentTop = dropDownContent . offset () . top ;
let dropDownContentLeft = dropDownContent . offset () . left ;
let dropDownContentHeight = dropDownContent . outerHeight ();
let dropDownContentBottom = dropDownContentTop + dropDownContentHeight ;
let viewportBottom = $ ( window ) . scrollTop () + $ ( window ) . height ();
// Change dropdown Up/Down orientation if dropdown is close to bottom viewport
2025-05-05 11:24:11 +00:00
if ( parentHolder . hasClass ( 'open' )
2024-09-23 02:02:32 +00:00
&& dropDownContentBottom > viewportBottom // Check bottom of dropdown is behind viewport
&& dropDownContentTop - dropDownContentHeight > 0 // check if set dropdown to --up will not go over the top of document
2025-05-05 11:24:11 +00:00
) {
2024-09-23 02:02:32 +00:00
parentHolder . addClass ( " --up " );
2025-05-05 11:24:11 +00:00
} else {
2024-09-23 02:02:32 +00:00
parentHolder . removeClass ( " --up " );
}
// Change dropdown left/right offset if dropdown is close to left viewport
2025-05-05 11:24:11 +00:00
if ( parentHolder . hasClass ( 'open' ) && dropDownContentLeft < 0 ) {
2024-09-23 02:02:32 +00:00
parentHolder . addClass ( " --left " );
2025-05-05 11:24:11 +00:00
} else {
2024-09-23 02:02:32 +00:00
parentHolder . removeClass ( " --left " );
2023-12-19 21:32:49 +00:00
}
});
2024-08-30 13:48:52 +00:00
2025-05-05 11:24:11 +00:00
2024-08-30 13:48:52 +00:00
// Close drop down
jQuery ( document ) . on ( " click " , function ( event ) {
// search if click was outside drop down
2024-10-06 19:55:46 +00:00
if ( ! $ ( event . target ) . closest ( '.butAction.dropdown-toggle' ) . length ) {
2026-07-23 09:44:05 +00:00
/* console.log("click close butAction - we click outside"); // disabled because too verbose */
2024-10-06 19:55:46 +00:00
let parentholder = jQuery ( " .butAction.dropdown-toggle " ) . closest ( " .dropdown.open " );
if ( parentholder ){
2026-07-23 09:44:05 +00:00
// Hide the dropdown.
2024-09-23 02:02:32 +00:00
parentholder . removeClass ( " open --up --left " );
2024-08-30 13:48:52 +00:00
}
}
});
2025-05-05 11:24:11 +00:00
2023-12-19 21:32:49 +00:00
});
2025-05-05 11:24:11 +00:00
// Code to manage the js for combo list with dependencies (called by extrafields_view.tpl.php)
function showOptions ( child_list , parent_list ) {
2025-10-17 13:48:40 +00:00
var parentInput = $ ( " select[name= " + parent_list + " ] " );
if ( parentInput . length === 0 ) { // when parent extra-field is in view mode and the child is edited directly on card (on line edit)
parentInput = $ ( " input[name= " + parent_list + " ] " );
}
if ( parentInput . length > 0 ) {
var val = parentInput . val ();
var parentVal = parent_list + " : " + val ;
if ( val > 0 ) {
$ ( " select[name= \" " + child_list + " \" ] option[parent] " ) . prop ( " disabled " , true ) . hide (); // hide not work with select2 element so disabled it
$ ( " select[name= \" " + child_list + " \" ] option[parent= \" " + parentVal + " \" ] " ) . prop ( 'disabled' , false ) . show (); // show not work with select2 element so enabled it
2025-05-05 11:24:11 +00:00
} else {
2025-10-17 13:48:40 +00:00
$ ( " select[name= \" " + child_list + " \" ] option " ) . prop ( " disabled " , false ) . show (); // show not work with select2 element so enabled it
2025-05-05 11:24:11 +00:00
}
2025-10-17 13:48:40 +00:00
}
2025-05-05 11:24:11 +00:00
}
function setListDependencies () {
console . log ( " setListDependencies " );
jQuery ( " select option[parent] " ) . parent () . each ( function () {
2026-06-12 11:55:29 +00:00
/* Skip selects inside line item extrafield containers — those are
* handled by setListDependencies_extra () generated by getJSListDependancies () .
* Both handlers binding on the same select would race showOptions ()
* ( prop disabled ) against showOptions_extra () ( clone / remove / append )
* and leave the child options permanently disabled . See #36880. */
if ( $ ( this ) . closest ( '[id^="extrafield_lines_area"]' ) . length > 0 ) {
return ;
}
2025-05-05 11:24:11 +00:00
var child_list = $ ( this ) . attr ( " name " );
var parent = $ ( this ) . find ( " option[parent]:first " ) . attr ( " parent " );
var infos = parent . split ( " : " );
var parent_list = infos [ 0 ];
showOptions ( child_list , parent_list );
/* Activate the handler to call showOptions on each future change */
$ ( " select[name= \" " + parent_list + " \" ] " ) . change ( function () {
showOptions ( child_list , parent_list );
});
});
}
2024-01-16 13:37:33 +00:00
< ? php
2024-01-18 11:10:29 +00:00
if ( ! getDolGlobalString ( 'MAIN_DISABLE_SELECT2_FOCUS_PROTECTION' ) && ! defined ( 'DISABLE_SELECT2_FOCUS_PROTECTION' )) {
2024-01-16 13:37:33 +00:00
?>
2025-06-17 13:14:08 +00:00
/**
2024-01-16 13:45:05 +00:00
* Hacky fix for a bug in select2 with jQuery 3.6 . 4 ' s new nested - focus " protection "
2025-03-24 11:48:38 +00:00
* This fix the need to click a second time when clicking into a combo with ajax ( see Test4d and Test5a in test_forms . php
2023-04-05 14:32:35 +00:00
* see : https :// github . com / select2 / select2 / issues / 5993
* see : https :// github . com / jquery / jquery / issues / 4382
*
* TODO : Recheck with the select2 GH issue and remove once this is fixed on their side
*/
2025-06-17 13:14:08 +00:00
2023-04-05 14:32:35 +00:00
$ ( document ) . on ( 'select2:open' , ( e ) => {
2024-12-19 00:05:39 +00:00
console . log ( " Execute the focus (click on combo or use space when on component) " );
2023-04-05 14:32:35 +00:00
const target = $ ( e . target );
if ( target && target . length ) {
2023-06-06 22:52:21 +00:00
let id = target [ 0 ] . id || target [ 0 ] . name ;
2025-06-17 13:14:08 +00:00
if ( id . substr ( - 2 ) == '[]' ) {
2024-12-19 00:05:39 +00:00
id = id . substr ( 0 , id . length - 2 );
}
2023-04-06 14:35:41 +00:00
document . querySelector ( 'input[aria-controls*=' + id + ']' ) . focus ();
2023-04-05 14:32:35 +00:00
}
});
2023-06-08 08:16:58 +00:00
< ? php
}
?>
2023-04-05 14:32:35 +00:00
2025-06-13 22:33:33 +00:00
2025-06-17 13:14:08 +00:00
/**
* Code to manage drag and drop inside kanban group by view - handles sortable columns and item movement between status columns
*/
$ ( document ) . ready ( function () {
if ( $ ( '.kanban .column' ) . length > 0 ) {
$ ( '.kanban .column' ) . sortable ({
items : '.kanban-draggable' ,
connectWith : '.kanban .column' ,
cursor : 'move' ,
opacity : 0.8 ,
tolerance : 'pointer' ,
start : function ( _ , ui ) {
ui . item . data ( 'original-column' , ui . item . parent ());
ui . placeholder . height ( ui . item . outerHeight ());
2025-06-13 22:33:33 +00:00
},
2025-06-17 13:14:08 +00:00
receive : function ( _ , ui ) {
var originalColumn = ui . item . data ( 'original-column' );
var newColumn = $ ( this );
if ( ! originalColumn . is ( newColumn )) {
onKanbanColumnChange ( ui . item , newColumn );
2025-06-13 23:45:50 +00:00
}
}
2025-06-13 22:33:33 +00:00
});
}
2025-06-17 13:14:08 +00:00
});
2025-06-13 22:33:33 +00:00
2025-06-17 13:14:08 +00:00
/**
* Function called when an item is moved to a different column
2025-07-24 13:39:37 +00:00
*
2025-06-17 13:14:08 +00:00
* @ param { jQuery } item - The dragged item
* @ param { jQuery } newColumn - The new column
*/
function onKanbanColumnChange ( item , newColumn ) {
2025-06-18 13:10:58 +00:00
console . log ( " Call onKanbanColumnChange " );
2025-06-17 13:14:08 +00:00
jQuery . ajax ({
method : 'POST' ,
url : '<?php echo DOL_URL_ROOT; ?>/core/ajax/saveinplace.php' ,
data : {
field : 'editval_' + newColumn . data ( 'groupbyfield' ),
element : item . data ( 'element' ),
table_element : item . data ( 'tableelement' ),
fk_element : item . data ( 'itemid' ),
value : newColumn . data ( 'groupbyid' ),
token : '<?php echo currentToken() ?>'
},
context : document . body ,
success : function () {
if ( newColumn . hasClass ( 'kanbancollapsed' )) {
item . hide ();
}
}
});
item . data ( 'original-column' , newColumn );
}
2025-06-13 22:33:33 +00:00
2026-01-11 17:41:11 +00:00
if ( typeof jQuery . fn . on === 'function' ) {
2025-09-22 20:20:52 +00:00
/*
2026-01-11 17:41:11 +00:00
* Intuitive table selection ( with keyboard selection )
*/
2025-09-22 20:20:52 +00:00
$ ( function () {
/**
* @ param { jQuery } el
* @ param { Integer } status
*/
let setLastClickedRowStatus = function ( el , status = 1 ){
$ ( '.row-with-select' ) . attr ( 'data-is-last-changed' , 0 );
el . attr ( 'data-is-last-changed' , status === 0 ? 0 : 1 );
}
/**
* Remove data - is - last - changed on double click
* Because if data - is - last - changed is present the user can ' t select text
*/
$ ( document ) . on ( " dblclick " , " .row-with-select " , function ( e ) {
$ ( '.row-with-select[data-is-last-changed]' ) . removeAttr ( 'data-is-last-changed' );
});
/**
* DISABLE on click a and button
* Because Ctrl + Click on link is also used for open ion a new tab
* we need to block select tool
*/
$ ( document ) . on ( " click " , " .row-with-select a, .row-with-select button " , function ( e ) {
// we need to block select tool
if ( e . ctrlKey ) {
e . stopPropagation ();
}
});
$ ( document ) . on ( " mousedown click " , " .row-with-select input.checkforselect " , function ( e ) {
// Prevents automatic change of “checked�
e . preventDefault ();
e . stopPropagation (); // parent click trigger will be done below
let parentRow = $ ( this ) . closest ( " .row-with-select " );
// this part of code prevent weird behavior when user (ctrl or maj) + click directly on checkbox
// We simulate a click on the parent line
2025-11-07 17:12:46 +00:00
console . log ( " Emulate click on parent line " );
2025-09-22 20:20:52 +00:00
parentRow . trigger ({
type : " click " ,
ctrlKey : ! e . shiftKey , // simulate ctrlKey click will automatically prop activate the checkbox with parent event but not if shift key is pressed.
metaKey : ! e . shiftKey , // simulate metaKey click will automatically prop activate the checkbox with parent event but not if shift key is pressed.
shiftKey : e . shiftKey ,
originalEvent : e
});
});
$ ( document ) . on ( " click " , " .row-with-select " , function ( e ) {
2025-11-07 17:12:46 +00:00
console . log ( " A click on line was done " );
2025-09-22 20:20:52 +00:00
let checkBox = $ ( this ) . find ( '.checkforselect' );
let nextCheckStatus = ! checkBox . is ( ':checked' )
if ( e . ctrlKey || e . metaKey ) {
// Add line to selection
2025-11-07 17:12:46 +00:00
if ( checkBox ) {
2025-09-22 20:20:52 +00:00
checkBox . prop ( 'checked' , nextCheckStatus ) . trigger ( 'change' );
}
setLastClickedRowStatus ( $ ( this ), 1 );
}
if ( e . shiftKey ) {
let lastLastChanged = $ ( this ) . closest ( 'table' ) . find ( '.row-with-select[data-is-last-changed="1"]' );
2025-11-07 17:12:46 +00:00
if ( lastLastChanged . length > 0 ) {
// Add all lines to selection beetwin last selected line
if ( $ ( this ) . index () === lastLastChanged . index ()) {
2025-09-22 20:20:52 +00:00
return null ;
}
2025-11-07 17:12:46 +00:00
if ( $ ( this ) . index () < lastLastChanged . index ()) {
2025-09-22 20:20:52 +00:00
$ ( this ) . nextUntil ( lastLastChanged , " .row-with-select " ) . find ( '.checkforselect' ) . prop ( 'checked' , nextCheckStatus ) . trigger ( 'change' );
} else {
lastLastChanged . nextUntil ( $ ( this ), " .row-with-select " ) . find ( '.checkforselect' ) . prop ( 'checked' , nextCheckStatus ) . trigger ( 'change' );
}
lastLastChanged . find ( '.checkforselect' ) . prop ( 'checked' , nextCheckStatus ) . trigger ( 'change' );
checkBox . prop ( 'checked' , nextCheckStatus ) . trigger ( 'change' );
setLastClickedRowStatus ( $ ( this ), 1 );
}
}
});
});
2023-04-05 14:32:35 +00:00
2026-01-11 17:41:11 +00:00
}
2017-11-19 15:30:05 +00:00
// End of lib_head.js.php