2017-11-09 00:00:43 +00:00
< ? php
2024-11-19 20:02:05 +00:00
/* Copyright ( C ) 2017 Laurent Destailleur < eldy @ users . sourceforge . net >
2024-11-04 22:53:20 +00:00
* Copyright ( C ) 2024 Frédéric France < frederic . france @ free . fr >
2017-11-09 00:00:43 +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 /
2017-11-09 00:00:43 +00:00
*/
/**
* \file htdocs / core / js / lib_foot . js . php
* \brief File that include javascript functions ( included if option use_javascript activated )
*/
2020-12-30 20:18:12 +00:00
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' );
}
2017-11-09 00:00:43 +00:00
2018-12-18 14:06:00 +00:00
session_cache_limiter ( 'public' );
2017-11-09 00:00:43 +00:00
require_once '../../main.inc.php' ;
2024-11-04 22:53:20 +00:00
/**
* @ var Conf $conf
* @ var Translate $langs
*/
2017-11-09 00:00:43 +00:00
2021-07-08 21:19:43 +00:00
/*
* View
*/
2017-11-09 00:00:43 +00:00
// 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' );
2017-11-09 00:00:43 +00:00
2026-03-05 00:13:38 +00:00
$jsConst = [
'DOL_URL_ROOT' => DOL_URL_ROOT ,
'classfortooltiponclicktextWidth' => ( $conf -> browser -> layout == 'phone' ? max (( empty ( $_SESSION [ 'dol_screenwidth' ]) ? 0 : $_SESSION [ 'dol_screenwidth' ]) - 20 , 320 ) : 700 ),
'dol_no_mouse_hover' => ! empty ( $conf -> dol_no_mouse_hover )
];
2017-11-19 11:22:01 +00:00
2023-04-09 22:28:29 +00:00
2026-03-05 00:13:38 +00:00
include __DIR__ . '/lib_initTooltips.js' ;
2023-04-09 22:28:29 +00:00
2026-03-05 00:13:38 +00:00
?>
2023-04-09 22:28:29 +00:00
2026-03-05 00:13:38 +00:00
// Wrapper to show tooltips (html or onclick popup)
/* JS CODE TO ENABLE Tooltips on all object with class classfortooltip */
jQuery ( function () {
const footerConst = < ? php print json_encode ( $jsConst ); ?> ;
if ( ! footerConst . dol_no_mouse_hover ) {
// --------------------------------
// Initial page load
// --------------------------------
initTooltips ( document . body ); // initialize all tooltips on page load
initAjaxTooltips ( document . body , footerConst . DOL_URL_ROOT ); // initialize all AJAX tooltips on page load
// --------------------------------
// Dynamic reload via Dolibarr hook
// --------------------------------
if ( typeof Dolibarr !== " undefined " && Dolibarr . on ) {
// Because Dolibarr context isn't in all Dolibarr page and lib_foot.js.php can be loaded everywhere
// it useful to check Dolibarr context is loaded before but we are already in a jQuery(function() so event Dolibarr:Ready can't be used here
Dolibarr . on ( 'initNewContent' , ({ targets }) => {
targets . forEach ( container => {
initTooltips ( container );
initAjaxTooltips ( container , footerConst . DOL_URL_ROOT );
})
2024-11-19 20:02:05 +00:00
});
2026-03-05 00:13:38 +00:00
};
}
// --------------------------------
// Initial page load
// --------------------------------
jQuery ( function () {
initTooltipDialogs ( document . body );
2023-01-30 22:24:23 +00:00
});
2017-11-09 00:00:43 +00:00
2026-03-05 00:13:38 +00:00
// --------------------------------
// Dynamic reload via Dolibarr hook
// --------------------------------
if ( typeof Dolibarr !== " undefined " && Dolibarr . on ) {
// Because Dolibarr context isn't in all Dolibarr page and lib_foot.js.php can be loaded everywhere
// it useful to check Dolibarr context is loaded before but we are already in a jQuery(function() so event Dolibarr:Ready can't be used here
Dolibarr . on ( 'initNewContent' , ({ targets }) => {
targets . forEach ( container => initTooltipDialogs ( container , footerConst . classfortooltiponclicktextWidth ));
});
};
2023-01-30 22:24:23 +00:00
});
2019-03-09 17:37:07 +00:00
2026-03-05 00:13:38 +00:00
< ? php
2017-11-09 00:00:43 +00:00
// Wrapper to manage dropdown
2020-12-30 20:18:12 +00:00
if ( ! defined ( 'JS_JQUERY_DISABLE_DROPDOWN' )) {
2020-02-23 20:38:24 +00:00
print " \n /* JS CODE TO ENABLE dropdown (hamburger, linkto, ...) */ \n " ;
2021-08-04 18:07:12 +00:00
print ' jQuery ( document ) . ready ( function () {
2020-02-23 20:38:24 +00:00
var lastopendropdown = null ;
// Click onto the link "link to" or "hamburger", toggle dropdown
2021-05-05 15:25:12 +00:00
$ ( document ) . on ( \ ' click\ ' , \ ' . dropdown dt a\ ' , function () {
2020-02-23 20:38:24 +00:00
console . log ( " toggle dropdown dt a " );
//$(this).parent().parent().find(\'dd ul\').slideToggle(\'fast\');
2022-12-20 12:11:54 +00:00
$ ( " .ulselectedfields " ) . removeClass ( " open " );
2020-02-23 20:38:24 +00:00
$ ( this ) . parent () . parent () . find ( \ ' dd ul\ ' ) . toggleClass ( " open " );
if ( $ ( this ) . parent () . parent () . find ( \ ' dd ul\ ' ) . hasClass ( " open " )) {
lastopendropdown = $ ( this ) . parent () . parent () . find ( \ ' dd ul\ ' );
//console.log(lastopendropdown);
} else {
// We closed the dropdown for hamburger selectfields
if ( $ ( " input:hidden[name=formfilteraction] " ) . val () == " listafterchangingselectedfields " ) {
console . log ( " resubmit the form saved into lastopendropdown after clicking on hamburger " );
//$(".dropdown dt a").parents(\'form:first\').submit();
//$(".dropdown dt a").closest("form").submit();
lastopendropdown . closest ( " form " ) . submit ();
}
}
2017-11-09 00:00:43 +00:00
// Note: Did not find a way to get exact height (value is update at exit) so i calculate a generic from nb of lines
heigthofcontent = 21 * $ ( this ) . parent () . parent () . find ( \ ' dd div ul li\ ' ) . length ;
if ( heigthofcontent > 300 ) heigthofcontent = 300 ; // limited by max-height on css .dropdown dd ul
posbottom = $ ( this ) . parent () . parent () . find ( \ ' dd\ ' ) . offset () . top + heigthofcontent + 8 ;
var scrollBottom = $ ( window ) . scrollTop () + $ ( window ) . height ();
diffoutsidebottom = ( posbottom - scrollBottom );
console . log ( " heigthofcontent= " + heigthofcontent + " , diffoutsidebottom (posbottom= " + posbottom + " - scrollBottom= " + scrollBottom + " ) = " + diffoutsidebottom );
if ( diffoutsidebottom > 0 )
{
pix = " - " + ( diffoutsidebottom + 8 ) + " px " ;
console . log ( " We reposition top by " + pix );
$ ( this ) . parent () . parent () . find ( \ ' dd\ ' ) . css ( " top " , pix );
}
});
2020-02-23 20:38:24 +00:00
// Click on a link into the popup "link to" or other dropdown that ask to close drop down on element click, so close dropdown
2017-11-09 00:00:43 +00:00
$ ( " .dropdowncloseonclick " ) . on ( \ ' click\ ' , function () {
2020-02-23 20:38:24 +00:00
console . log ( " Link has class dropdowncloseonclick, so we close/hide the popup ul " );
//$(this).parent().parent().hide(); // $(this).parent().parent() is ul
$ ( this ) . parent () . parent () . removeClass ( " open " ); // $(this).parent().parent() is ul
2017-11-09 00:00:43 +00:00
});
2020-02-23 20:38:24 +00:00
// Click outside of any dropdown
2017-11-09 00:00:43 +00:00
$ ( document ) . bind ( \ ' click\ ' , function ( e ) {
2020-02-23 20:38:24 +00:00
var $clicked = $ ( e . target ); // This is element we click on
if ( ! $clicked . parents () . hasClass ( " dropdown " )) {
2020-03-11 22:57:36 +00:00
//console.log("close dropdown dd ul - we click outside");
2020-02-23 20:38:24 +00:00
//$(".dropdown dd ul").hide();
$ ( " .dropdown dd ul " ) . removeClass ( " open " );
if ( $ ( " input:hidden[name=formfilteraction] " ) . val () == " listafterchangingselectedfields " ) {
console . log ( " resubmit form saved into lastopendropdown after clicking outside of dropdown and having change selectlist from selectlist field of hamburger dropdown " );
//$(".dropdown dt a").parents(\'form:first\').submit();
//$(".dropdown dt a").closest("form").submit();
lastopendropdown . closest ( " form " ) . submit ();
}
}
2017-11-09 00:00:43 +00:00
});
2020-02-23 20:38:24 +00:00
});
2017-11-09 00:00:43 +00:00
' ;
}
// Wrapper to manage document_preview
2020-12-30 20:18:12 +00:00
if ( $conf -> browser -> layout != 'phone' ) {
2020-04-10 08:59:32 +00:00
print " \n /* JS CODE TO ENABLE document_preview */ \n " ; // Function document_preview is into header
2021-08-04 18:07:12 +00:00
print ' jQuery ( document ) . ready ( function () {
2024-10-01 11:19:39 +00:00
// Click on the preview picto
2017-11-09 00:00:43 +00:00
jQuery ( " .documentpreview " ) . click ( function () {
console . log ( " We click on preview for element with href= " + $ ( this ) . attr ( \ ' href\ ' ) + " mime= " + $ ( this ) . attr ( \ ' mime\ ' ));
2025-07-23 12:43:51 +00:00
var titledocpreview = $ ( this ) . attr ( \ ' data - title\ ' );
if ( titledocpreview == undefined || titledocpreview == " " ) {
titledocpreview = \ '' . dol_escape_js ( $langs -> transnoentities ( " Preview " )) . ' \ '
}
document_preview ( $ ( this ) . attr ( \ ' href\ ' ), $ ( this ) . attr ( \ ' mime\ ' ), titledocpreview );
2017-11-09 00:00:43 +00:00
return false ;
});
2021-08-04 18:07:12 +00:00
}); ' . " \n " ;
2017-11-09 00:00:43 +00:00
}
2018-04-19 11:59:20 +00:00
// Code to manage reposition
2017-11-09 08:50:55 +00:00
print " \n /* JS CODE TO ENABLE reposition management (does not work if a redirect is done after action of submission) */ \n " ;
print '
2024-11-28 10:06:44 +00:00
jQuery ( document ) . ready ( function () {
/* If page_y set, we set scrollbar with it */
page_y = getParameterByName ( " page_y " , 0 ); /* search in GET parameter */
if ( page_y == 0 ) page_y = jQuery ( " #page_y " ) . text (); /* search in POST parameter that is filed at bottom of page */
if ( page_y > 0 ) {
console . log ( " page_y found is " + page_y );
jQuery ( " html, body " ) . scrollTop ( page_y );
}
/* Set handler to add page_y param on output (click on href links or submit button) */
jQuery ( " .reposition " ) . click ( function ( event ) {
var page_y = jQuery ( document ) . scrollTop ();
if ( page_y > 0 ) {
if ( this . href ) {
console . log ( " We click on tag with .reposition class. this.ref was " + this . href );
var url = new URL ( this . href , window . location . origin );
url . searchParams . delete ( " page_y " ); /* remove page_y param if already present */
url . searchParams . set ( " page_y " , page_y );
this . href = url . toString ();
console . log ( " We click on tag with .reposition class. this.ref is now " + this . href );
} else {
console . log ( " We click on tag with .reposition class but element is not an <a> html tag, so we try to update input form field with name=page_y with value " + page_y );
jQuery ( " input[type=hidden][name=page_y] " ) . val ( page_y );
}
}
});
});
' . " \n " ;
2021-08-04 18:07:12 +00:00
// Code to manage Copy To Clipboard click
print " \n /* JS CODE TO ENABLE ClipBoard copy paste */ \n " ;
print '
jQuery ( document ) . ready ( function () {
jQuery ( \ ' . clipboardCPShowOnHover\ ' ) . hover (
function () {
console . log ( " We hover a value with a copy paste feature " );
2024-10-16 15:26:00 +00:00
$ ( this ) . children ( " .clipboardCPButton, .clipboardCPText " ) . css ( " display " , " inline-block " ); /* better than .show() because the show set the display to "inline" */
2021-08-04 18:07:12 +00:00
},
function () {
console . log ( " We hover out the value with a copy paste feature " );
$ ( this ) . children ( " .clipboardCPButton, .clipboardCPText " ) . hide ();
}
);
2022-05-10 08:57:51 +00:00
jQuery ( \ ' . clipboardCPValue , . clipboardCPButton , . clipboardCPValueToPrint\ ' ) . click ( function () {
2021-08-24 11:19:53 +00:00
console . log ( " We click on a clipboardCPButton or clipboardCPValueToPrint class and we want to copy content of clipboardCPValue class " );
2021-08-04 18:07:12 +00:00
2021-08-24 11:19:53 +00:00
if ( window . getSelection ) {
2022-07-25 08:26:27 +00:00
jqobj = $ ( this ) . parent () . children ( " .clipboardCPValue " );
console . log ( jqobj . html ());
2021-08-04 18:07:12 +00:00
2021-08-24 11:19:53 +00:00
selection = window . getSelection (); /* get the object used for selection */
selection . removeAllRanges (); /* clear current selection */
2022-07-25 08:26:27 +00:00
/* We select the value to print using the parentNode.firstChild */
/* We should use the class clipboardCPValue but it may have several element with copy/paste so class to select is not enough */
range = document . createRange ();
range . selectNodeContents ( this . parentNode . firstChild );
2021-08-24 11:19:53 +00:00
selection . addRange ( range ); /* make the new selection with the value to copy */
2022-07-25 08:26:27 +00:00
/* copy selection into clipboard */
var succeed ;
try {
console . log ( " We set the style display to unset for the span so the copy will work " );
jqobj . css ( " display " , " unset " ); /* Because copy does not work on "block" object */
2021-08-24 11:19:53 +00:00
2022-07-25 08:26:27 +00:00
succeed = document . execCommand ( \ ' copy\ ' );
console . log ( " We set the style display back to inline-block " );
2024-10-16 15:26:00 +00:00
jqobj . css ( " display " , " inline-block " ); /* better than .show() because the show set the display to "inline" */
2022-07-25 08:26:27 +00:00
} catch ( e ) {
succeed = false ;
}
/* Remove the selection to avoid to see the hidden field to copy selected */
window . getSelection () . removeAllRanges ();
}
2021-08-04 18:07:12 +00:00
2024-10-16 15:26:00 +00:00
/* Show result - message */
var lastparent = $ ( this ) . parent (); /* .parent is clipboardCP */
2021-10-24 14:35:42 +00:00
var lastchild = this . parentNode . lastChild ; /* .parentNode is clipboardCP and last child is clipboardCPText */
2021-08-04 18:07:12 +00:00
var tmp = lastchild . innerHTML
2021-08-24 11:19:53 +00:00
if ( succeed ) {
2024-10-16 15:26:00 +00:00
$ ( this ) . parent () . children ( " .clipboardCPButton " ) . hide ();
$ ( this ) . parent () . children ( " .clipboardCPTick " ) . css ( " display " , " inline-block " ); /* better than .show() because the show set the display to "inline" */
//lastchild.innerHTML = \'<div class="clipboardCPTextDivInside opacitymedium">'.dol_escape_js($langs->trans('CopiedToClipboard')).'</div>\';
2021-08-24 11:19:53 +00:00
} else {
2021-10-24 14:35:42 +00:00
lastchild . innerHTML = \ '<div class="clipboardCPTextDivInside opacitymedium">' . dol_escape_js ( $langs -> trans ( 'Error' )) . ' </ div > \ ' ;
2021-08-24 11:19:53 +00:00
}
2024-10-16 15:26:00 +00:00
setTimeout (() => { lastchild . innerHTML = tmp ; lastparent . children ( " .clipboardCPTick " ) . hide (); }, 2000 );
2021-08-04 18:07:12 +00:00
});
}); ' . " \n " ;
// Code to manage clicktodial
print " \n /* JS CODE TO ENABLE clicktodial call of an URL */ \n " ;
print '
jQuery ( document ) . ready ( function () {
jQuery ( " .cssforclicktodial " ) . click ( function () {
event . preventDefault ();
2023-04-08 01:43:21 +00:00
var currenttoken = jQuery ( " meta[name=anti-csrf-currenttoken] " ) . attr ( " content " );
console . log ( " We click on a cssforclicktodial class with href= " + this . href );
2021-08-04 18:07:12 +00:00
$ . ajax ({
2024-11-19 20:02:05 +00:00
url : this . href ,
type : \ ' GET\ ' ,
data : { token : currenttoken }
2021-08-04 18:07:12 +00:00
}) . done ( function ( xhr , textStatus , errorThrown ) {
/* do nothing */
}) . fail ( function ( xhr , textStatus , errorThrown ) {
alert ( " Error: " + textStatus );
});
return false ;
});
}); ' . " \n " ;
2021-07-04 20:59:53 +00:00
2021-08-04 18:07:12 +00:00
// Code to manage the confirm dialog box
2021-07-08 20:29:41 +00:00
print " \n /* JS CODE TO ENABLE DIALOG CONFIRM POPUP ON ACTION BUTTON */ \n " ;
2021-08-04 18:07:12 +00:00
print '
jQuery ( document ) . ready ( function () {
$ ( document ) . on ( " click " , \ ' . butActionConfirm\ ' , function ( event ) {
event . preventDefault ();
// I don\'t use jquery $(this).data(\'confirm-url\'); to get $(this).attr(\'data-confirm-url\'); because .data() can doesn\'t work with ajax
var confirmUrl = $ ( this ) . attr ( \ ' data - confirm - url\ ' );
var confirmTitle = $ ( this ) . attr ( \ ' data - confirm - title\ ' );
var confirmContent = $ ( this ) . attr ( \ ' data - confirm - content\ ' );
var confirmActionBtnLabel = $ ( this ) . attr ( \ ' data - confirm - action - btn - label\ ' );
var confirmCancelBtnLabel = $ ( this ) . attr ( \ ' data - confirm - cancel - btn - label\ ' );
var confirmModal = $ ( this ) . attr ( \ ' data - confirm - modal\ ' );
if ( confirmModal == undefined ){ confirmModal = false ; }
var confirmId = \ ' confirm - dialog - box\ ' ;
if ( $ ( this ) . attr ( \ ' id\ ' ) != undefined ){ var confirmId = confirmId + " - " + $ ( this ) . attr ( \ ' id\ ' ); }
if ( $ ( " # " + confirmId ) != undefined ) { $ ( \ ' #\' + confirmId).remove(); }
// Create modal box
var $confirmBox = $ ( \ ' < div /> \ ' , {
id : confirmId ,
title : confirmTitle
}) . appendTo ( \ ' body\ ' );
$confirmBox . dialog ({
autoOpen : true ,
modal : confirmModal ,
//width: Math.min($( window ).width() - 50, 1700),
width : \ ' auto\ ' ,
dialogClass : \ ' confirm - dialog - box\ ' ,
buttons : [
{
text : confirmActionBtnLabel ,
" class " : \ ' ui - state - information\ ' ,
click : function () {
2024-10-01 11:19:39 +00:00
window . location . replace ( confirmUrl );
}
2021-08-04 18:07:12 +00:00
},
{
text : confirmCancelBtnLabel ,
" class " : \ ' ui - state - information\ ' ,
click : function () {
2024-10-01 11:19:39 +00:00
$ ( this ) . dialog ( " close " );
}
2021-08-04 18:07:12 +00:00
}
],
close : function ( event , ui ) {
$ ( \ ' #\'+confirmBox).remove();
2021-07-04 20:59:53 +00:00
},
2021-08-04 18:07:12 +00:00
open : function ( event , ui ) {
$confirmBox . html ( confirmContent );
2021-07-04 20:59:53 +00:00
}
2021-08-04 18:07:12 +00:00
});
2021-07-04 20:59:53 +00:00
});
});
' . " \n " ;
2025-03-25 09:57:15 +00:00
// JS CODE USED by form::getSearchFilterToolInput
include __DIR__ . '/lib_foot_search_tool.js' ;
2025-11-17 21:36:21 +00:00
include __DIR__ . '/lib_tooltip-freeze-by-alt-keypress.js' ;