2017-11-09 01:00:43 +01:00
< ? php
2024-11-19 21:02:05 +01:00
/* Copyright ( C ) 2017 Laurent Destailleur < eldy @ users . sourceforge . net >
2024-11-04 23:53:20 +01:00
* Copyright ( C ) 2024 Frédéric France < frederic . france @ free . fr >
2017-11-09 01:00:43 +01: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 21:55:30 +02:00
* along with this program . If not , see < https :// www . gnu . org / licenses />.
* or see https :// www . gnu . org /
2017-11-09 01:00:43 +01:00
*/
/**
* \file htdocs / core / js / lib_foot . js . php
* \brief File that include javascript functions ( included if option use_javascript activated )
*/
2020-12-30 21:18:12 +01: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 01:00:43 +01:00
2018-12-18 15:06:00 +01:00
session_cache_limiter ( 'public' );
2017-11-09 01:00:43 +01:00
require_once '../../main.inc.php' ;
2024-11-04 23:53:20 +01:00
/**
* @ var Conf $conf
* @ var Translate $langs
2024-11-19 21:02:05 +01:00
*
* @ var int $dolibarr_nocache
2024-11-04 23:53:20 +01:00
*/
2017-11-09 01:00:43 +01:00
2021-07-08 23:19:43 +02:00
/*
* View
*/
2017-11-09 01:00:43 +01: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.
2020-12-30 21:18:12 +01:00
if ( empty ( $dolibarr_nocache )) {
header ( 'Cache-Control: max-age=10800, public, must-revalidate' );
} else {
header ( 'Cache-Control: no-cache' );
}
2017-11-09 01:00:43 +01:00
//var_dump($conf);
2017-11-19 12:22:01 +01:00
2017-11-09 01:00:43 +01:00
// Wrapper to show tooltips (html or onclick popup)
2023-01-30 23:24:23 +01:00
print " \n /* JS CODE TO ENABLE Tooltips on all object with class classfortooltip */
jQuery ( document ) . ready ( function () { \n " ;
2019-03-09 18:37:07 +01:00
2020-12-30 21:18:12 +01:00
if ( empty ( $conf -> dol_no_mouse_hover )) {
2023-01-30 23:24:23 +01:00
print '
2024-11-19 21:02:05 +01:00
/* for standard tooltip */
2023-01-30 23:24:23 +01:00
jQuery ( " .classfortooltip " ) . tooltip ({
2023-10-12 12:49:57 +02:00
tooltipClass : " mytooltip " ,
2021-02-06 00:05:24 +01:00
show : { collision : " flipfit " , effect : " toggle " , delay : 50 , duration : 20 },
hide : { delay : 250 , duration : 20 },
content : function () {
2023-01-30 23:24:23 +01:00
console . log ( " Return title for popup " );
return $ ( this ) . prop ( " title " ); /* To force to get title as is */
}
});
2023-04-10 00:28:29 +02:00
2023-10-12 12:49:57 +02:00
var opendelay = 100 ;
2023-04-10 00:28:29 +02:00
var elemtostoretooltiptimer = jQuery ( " #dialogforpopup " );
2023-04-10 00:48:17 +02:00
var currenttoken = jQuery ( " meta[name=anti-csrf-currenttoken] " ) . attr ( " content " );
2023-04-10 00:28:29 +02:00
2023-10-12 12:49:57 +02:00
/* for ajax tooltip */
2023-04-10 00:28:29 +02:00
target = jQuery ( " .classforajaxtooltip " );
target . tooltip ({
2023-01-30 23:24:23 +01:00
tooltipClass : " mytooltip " ,
2023-04-10 00:28:29 +02:00
show : { collision : " flipfit " , effect : " toggle " , delay : 0 , duration : 20 },
hide : { delay : 250 , duration : 20 }
});
target . off ( " mouseover mouseout " );
target . on ( " mouseover " , function ( event ) {
console . log ( " we will create timer for ajax call " );
2024-11-19 21:02:05 +01:00
event . stopImmediatePropagation ();
2024-02-14 03:38:17 +01:00
clearTimeout ( elemtostoretooltiptimer . data ( " openTimeoutId " ));
2023-04-10 00:28:29 +02:00
var params = JSON . parse ( $ ( this ) . attr ( " data-params " ));
params . token = currenttoken ;
2023-04-10 00:48:17 +02:00
var elemfortooltip = $ ( this );
2023-04-10 00:28:29 +02:00
2024-11-19 21:02:05 +01:00
elemtostoretooltiptimer . data ( " openTimeoutId " , setTimeout ( function () {
2023-04-10 00:28:29 +02:00
target . tooltip ( " close " );
2023-01-30 23:24:23 +01:00
$ . ajax ({
2024-11-19 21:02:05 +01:00
url : " '. DOL_URL_ROOT.'/core/ajax/ajaxtooltip.php " ,
type : " post " ,
async : true ,
data : params ,
success : function ( response ){
// Setting content option
console . log ( " ajax success " );
if ( elemfortooltip . is ( " :hover " )) {
elemfortooltip . tooltip ( " option " , " content " , response );
elemfortooltip . tooltip ( " open " );
2023-04-10 00:28:29 +02:00
}
2024-11-19 21:02:05 +01:00
}
});
}, opendelay ));
2023-04-10 00:28:29 +02:00
});
target . on ( " mouseout " , function ( event ) {
2024-01-23 13:14:25 +01:00
console . log ( " mouse out of a .classforajaxtooltip " );
2023-04-10 00:28:29 +02:00
event . stopImmediatePropagation ();
clearTimeout ( elemtostoretooltiptimer . data ( " openTimeoutId " ));
target . tooltip ( " close " );
2023-01-30 23:24:23 +01:00
});
' ;
2017-11-09 01:00:43 +01:00
}
2019-03-09 18:37:07 +01:00
print '
2023-01-30 23:24:23 +01:00
jQuery ( " .classfortooltiponclicktext " ) . dialog ({
closeOnEscape : true , classes : { " ui-dialog " : " highlight " },
2023-06-06 00:19:55 +02:00
maxHeight : window . innerHeight - 60 , width : '.($conf->browser->layout == ' phone ' ? max((empty($_SESSION[' dol_screenwidth ']) ? 0 : $_SESSION[' dol_screenwidth ']) - 20, 320) : 700).' ,
2023-01-30 23:24:23 +01:00
modal : true ,
autoOpen : false
}) . css ( " z-index: 5000 " );
jQuery ( " .classfortooltiponclick " ) . click ( function () {
console . log ( " We click on tooltip for element with dolid= " + $ ( this ) . attr ( \ ' dolid\ ' ));
if ( $ ( this ) . attr ( \ ' dolid\ ' )) {
obj = $ ( " #idfortooltiponclick_ " + $ ( this ) . attr ( \ ' dolid\ ' )); /* obj is a div component */
obj . dialog ( " open " );
return false ;
}
});
});
' ;
2019-03-09 18:37:07 +01:00
2017-11-09 01:00:43 +01:00
// Wrapper to manage dropdown
2020-12-30 21:18:12 +01:00
if ( ! defined ( 'JS_JQUERY_DISABLE_DROPDOWN' )) {
2020-02-23 21:38:24 +01:00
print " \n /* JS CODE TO ENABLE dropdown (hamburger, linkto, ...) */ \n " ;
2021-08-04 20:07:12 +02:00
print ' jQuery ( document ) . ready ( function () {
2020-02-23 21:38:24 +01:00
var lastopendropdown = null ;
// Click onto the link "link to" or "hamburger", toggle dropdown
2021-05-05 17:25:12 +02:00
$ ( document ) . on ( \ ' click\ ' , \ ' . dropdown dt a\ ' , function () {
2020-02-23 21:38:24 +01:00
console . log ( " toggle dropdown dt a " );
2022-06-30 14:28:02 +02:00
setTimeout (() => { $ ( \ ' . inputsearch_dropdownselectedfields\ ' ) . focus (); }, 200 );
2020-02-23 21:38:24 +01:00
//$(this).parent().parent().find(\'dd ul\').slideToggle(\'fast\');
2022-12-20 13:11:54 +01:00
$ ( " .ulselectedfields " ) . removeClass ( " open " );
2020-02-23 21:38:24 +01: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 01:00:43 +01: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 21:38:24 +01: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 01:00:43 +01:00
$ ( " .dropdowncloseonclick " ) . on ( \ ' click\ ' , function () {
2020-02-23 21:38:24 +01: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 01:00:43 +01:00
});
2020-02-23 21:38:24 +01:00
// Click outside of any dropdown
2017-11-09 01:00:43 +01:00
$ ( document ) . bind ( \ ' click\ ' , function ( e ) {
2020-02-23 21:38:24 +01:00
var $clicked = $ ( e . target ); // This is element we click on
if ( ! $clicked . parents () . hasClass ( " dropdown " )) {
2020-03-11 23:57:36 +01:00
//console.log("close dropdown dd ul - we click outside");
2020-02-23 21:38:24 +01: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 01:00:43 +01:00
});
2020-02-23 21:38:24 +01:00
});
2017-11-09 01:00:43 +01:00
' ;
}
// Wrapper to manage document_preview
2020-12-30 21:18:12 +01:00
if ( $conf -> browser -> layout != 'phone' ) {
2020-04-10 10:59:32 +02:00
print " \n /* JS CODE TO ENABLE document_preview */ \n " ; // Function document_preview is into header
2021-08-04 20:07:12 +02:00
print ' jQuery ( document ) . ready ( function () {
2024-10-01 13:19:39 +02:00
// Click on the preview picto
2017-11-09 01:00:43 +01:00
jQuery ( " .documentpreview " ) . click ( function () {
console . log ( " We click on preview for element with href= " + $ ( this ) . attr ( \ ' href\ ' ) + " mime= " + $ ( this ) . attr ( \ ' mime\ ' ));
document_preview ( $ ( this ) . attr ( \ 'href\'), $(this).attr(\'mime\'), \'' . dol_escape_js ( $langs -> transnoentities ( " Preview " )) . ' \ ' );
return false ;
});
2021-08-04 20:07:12 +02:00
}); ' . " \n " ;
2017-11-09 01:00:43 +01:00
}
2018-04-19 13:59:20 +02:00
// Code to manage reposition
2017-11-09 09:50:55 +01: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 11:06:44 +01: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 20:07:12 +02: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 17:26:00 +02:00
$ ( this ) . children ( " .clipboardCPButton, .clipboardCPText " ) . css ( " display " , " inline-block " ); /* better than .show() because the show set the display to "inline" */
2021-08-04 20:07:12 +02:00
},
function () {
console . log ( " We hover out the value with a copy paste feature " );
$ ( this ) . children ( " .clipboardCPButton, .clipboardCPText " ) . hide ();
}
);
2022-05-10 10:57:51 +02:00
jQuery ( \ ' . clipboardCPValue , . clipboardCPButton , . clipboardCPValueToPrint\ ' ) . click ( function () {
2021-08-24 13:19:53 +02:00
console . log ( " We click on a clipboardCPButton or clipboardCPValueToPrint class and we want to copy content of clipboardCPValue class " );
2021-08-04 20:07:12 +02:00
2021-08-24 13:19:53 +02:00
if ( window . getSelection ) {
2022-07-25 10:26:27 +02:00
jqobj = $ ( this ) . parent () . children ( " .clipboardCPValue " );
console . log ( jqobj . html ());
2021-08-04 20:07:12 +02:00
2021-08-24 13:19:53 +02:00
selection = window . getSelection (); /* get the object used for selection */
selection . removeAllRanges (); /* clear current selection */
2022-07-25 10:26:27 +02: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 13:19:53 +02:00
selection . addRange ( range ); /* make the new selection with the value to copy */
2022-07-25 10:26:27 +02: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 13:19:53 +02:00
2022-07-25 10:26:27 +02:00
succeed = document . execCommand ( \ ' copy\ ' );
console . log ( " We set the style display back to inline-block " );
2024-10-16 17:26:00 +02:00
jqobj . css ( " display " , " inline-block " ); /* better than .show() because the show set the display to "inline" */
2022-07-25 10:26:27 +02:00
} catch ( e ) {
succeed = false ;
}
/* Remove the selection to avoid to see the hidden field to copy selected */
window . getSelection () . removeAllRanges ();
}
2021-08-04 20:07:12 +02:00
2024-10-16 17:26:00 +02:00
/* Show result - message */
var lastparent = $ ( this ) . parent (); /* .parent is clipboardCP */
2021-10-24 16:35:42 +02:00
var lastchild = this . parentNode . lastChild ; /* .parentNode is clipboardCP and last child is clipboardCPText */
2021-08-04 20:07:12 +02:00
var tmp = lastchild . innerHTML
2021-08-24 13:19:53 +02:00
if ( succeed ) {
2024-10-16 17:26:00 +02: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 13:19:53 +02:00
} else {
2021-10-24 16:35:42 +02:00
lastchild . innerHTML = \ '<div class="clipboardCPTextDivInside opacitymedium">' . dol_escape_js ( $langs -> trans ( 'Error' )) . ' </ div > \ ' ;
2021-08-24 13:19:53 +02:00
}
2024-10-16 17:26:00 +02:00
setTimeout (() => { lastchild . innerHTML = tmp ; lastparent . children ( " .clipboardCPTick " ) . hide (); }, 2000 );
2021-08-04 20:07:12 +02: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 03:43:21 +02: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 20:07:12 +02:00
$ . ajax ({
2024-11-19 21:02:05 +01:00
url : this . href ,
type : \ ' GET\ ' ,
data : { token : currenttoken }
2021-08-04 20:07:12 +02:00
}) . done ( function ( xhr , textStatus , errorThrown ) {
/* do nothing */
}) . fail ( function ( xhr , textStatus , errorThrown ) {
alert ( " Error: " + textStatus );
});
return false ;
});
}); ' . " \n " ;
2021-07-04 22:59:53 +02:00
2021-08-04 20:07:12 +02:00
// Code to manage the confirm dialog box
2021-07-08 22:29:41 +02:00
print " \n /* JS CODE TO ENABLE DIALOG CONFIRM POPUP ON ACTION BUTTON */ \n " ;
2021-08-04 20:07:12 +02: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 13:19:39 +02:00
window . location . replace ( confirmUrl );
}
2021-08-04 20:07:12 +02:00
},
{
text : confirmCancelBtnLabel ,
" class " : \ ' ui - state - information\ ' ,
click : function () {
2024-10-01 13:19:39 +02:00
$ ( this ) . dialog ( " close " );
}
2021-08-04 20:07:12 +02:00
}
],
close : function ( event , ui ) {
$ ( \ ' #\'+confirmBox).remove();
2021-07-04 22:59:53 +02:00
},
2021-08-04 20:07:12 +02:00
open : function ( event , ui ) {
$confirmBox . html ( confirmContent );
2021-07-04 22:59:53 +02:00
}
2021-08-04 20:07:12 +02:00
});
2021-07-04 22:59:53 +02:00
});
});
' . " \n " ;