411 lines
16 KiB
PHP
411 lines
16 KiB
PHP
<?php
|
|
/* Copyright (C) 2017 Laurent Destailleur <eldy@users.sourceforge.net>
|
|
*
|
|
* 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
|
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
* or see https://www.gnu.org/
|
|
*/
|
|
|
|
/**
|
|
* \file htdocs/core/js/lib_foot.js.php
|
|
* \brief File that include javascript functions (included if option use_javascript activated)
|
|
*/
|
|
|
|
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');
|
|
}
|
|
|
|
session_cache_limiter('public');
|
|
|
|
require_once '../../main.inc.php';
|
|
|
|
|
|
/*
|
|
* View
|
|
*/
|
|
|
|
// 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.
|
|
if (empty($dolibarr_nocache)) {
|
|
header('Cache-Control: max-age=10800, public, must-revalidate');
|
|
} else {
|
|
header('Cache-Control: no-cache');
|
|
}
|
|
|
|
//var_dump($conf);
|
|
|
|
|
|
// Wrapper to show tooltips (html or onclick popup)
|
|
print "\n/* JS CODE TO ENABLE Tooltips on all object with class classfortooltip */
|
|
jQuery(document).ready(function () {\n";
|
|
|
|
if (empty($conf->dol_no_mouse_hover)) {
|
|
print '
|
|
/* for standard tooltip */
|
|
jQuery(".classfortooltip").tooltip({
|
|
tooltipClass: "mytooltip",
|
|
show: { collision: "flipfit", effect:"toggle", delay:50, duration: 20 },
|
|
hide: { delay: 250, duration: 20 },
|
|
content: function () {
|
|
console.log("Return title for popup");
|
|
return $(this).prop("title"); /* To force to get title as is */
|
|
}
|
|
});
|
|
|
|
var opendelay = 100;
|
|
var elemtostoretooltiptimer = jQuery("#dialogforpopup");
|
|
var currenttoken = jQuery("meta[name=anti-csrf-currenttoken]").attr("content");
|
|
|
|
/* for ajax tooltip */
|
|
target = jQuery(".classforajaxtooltip");
|
|
target.tooltip({
|
|
tooltipClass: "mytooltip",
|
|
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");
|
|
event.stopImmediatePropagation();
|
|
clearTimeout(elemtostoretooltiptimer.data("openTimeoutId"));
|
|
|
|
var params = JSON.parse($(this).attr("data-params"));
|
|
params.token = currenttoken;
|
|
var elemfortooltip = $(this);
|
|
|
|
elemtostoretooltiptimer.data("openTimeoutId", setTimeout(function() {
|
|
target.tooltip("close");
|
|
$.ajax({
|
|
url:"'. DOL_URL_ROOT.'/core/ajax/ajaxtooltip.php",
|
|
type: "post",
|
|
async: true,
|
|
data: params,
|
|
success: function(response){
|
|
// Setting content option
|
|
console.log("ajax success");
|
|
elemfortooltip.tooltip("option","content",response);
|
|
elemfortooltip.tooltip("open");
|
|
}
|
|
});
|
|
}, opendelay));
|
|
});
|
|
target.on("mouseout", function(event) {
|
|
console.log("mouse out of a .classforajaxtooltip");
|
|
event.stopImmediatePropagation();
|
|
clearTimeout(elemtostoretooltiptimer.data("openTimeoutId"));
|
|
target.tooltip("close");
|
|
});
|
|
';
|
|
}
|
|
|
|
print '
|
|
jQuery(".classfortooltiponclicktext").dialog({
|
|
closeOnEscape: true, classes: { "ui-dialog": "highlight" },
|
|
maxHeight: window.innerHeight-60, width: '.($conf->browser->layout == 'phone' ? max((empty($_SESSION['dol_screenwidth']) ? 0 : $_SESSION['dol_screenwidth']) - 20, 320) : 700).',
|
|
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;
|
|
}
|
|
});
|
|
});
|
|
';
|
|
|
|
|
|
// Wrapper to manage dropdown
|
|
if (!defined('JS_JQUERY_DISABLE_DROPDOWN')) {
|
|
print "\n/* JS CODE TO ENABLE dropdown (hamburger, linkto, ...) */\n";
|
|
print ' jQuery(document).ready(function () {
|
|
var lastopendropdown = null;
|
|
|
|
// Click onto the link "link to" or "hamburger", toggle dropdown
|
|
$(document).on(\'click\', \'.dropdown dt a\', function () {
|
|
console.log("toggle dropdown dt a");
|
|
setTimeout(() => { $(\'.inputsearch_dropdownselectedfields\').focus(); }, 200);
|
|
|
|
//$(this).parent().parent().find(\'dd ul\').slideToggle(\'fast\');
|
|
$(".ulselectedfields").removeClass("open");
|
|
$(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();
|
|
}
|
|
}
|
|
|
|
// 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);
|
|
}
|
|
});
|
|
|
|
// Click on a link into the popup "link to" or other dropdown that ask to close drop down on element click, so close dropdown
|
|
$(".dropdowncloseonclick").on(\'click\', function () {
|
|
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
|
|
});
|
|
|
|
// Click outside of any dropdown
|
|
$(document).bind(\'click\', function (e) {
|
|
var $clicked = $(e.target); // This is element we click on
|
|
if (!$clicked.parents().hasClass("dropdown")) {
|
|
//console.log("close dropdown dd ul - we click outside");
|
|
//$(".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();
|
|
}
|
|
}
|
|
});
|
|
});
|
|
';
|
|
}
|
|
|
|
// Wrapper to manage document_preview
|
|
if ($conf->browser->layout != 'phone') {
|
|
print "\n/* JS CODE TO ENABLE document_preview */\n"; // Function document_preview is into header
|
|
print ' jQuery(document).ready(function () {
|
|
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;
|
|
});
|
|
});'."\n";
|
|
}
|
|
|
|
// Code to manage reposition
|
|
print "\n/* JS CODE TO ENABLE reposition management (does not work if a redirect is done after action of submission) */\n";
|
|
print '
|
|
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);
|
|
$(\'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() {
|
|
var page_y = $(document).scrollTop();
|
|
|
|
if (page_y > 0)
|
|
{
|
|
if (this.href)
|
|
{
|
|
console.log("We click on tag with .reposition class. this.ref was "+this.href);
|
|
var hrefarray = this.href.split("#", 2);
|
|
hrefarray[0]=hrefarray[0].replace(/&page_y=(\d+)/, \'\'); /* remove page_y param if already present */
|
|
this.href=hrefarray[0]+\'&page_y=\'+page_y;
|
|
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";
|
|
|
|
// 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");
|
|
$(this).children(".clipboardCPButton, .clipboardCPText").show();
|
|
},
|
|
function() {
|
|
console.log("We hover out the value with a copy paste feature");
|
|
$(this).children(".clipboardCPButton, .clipboardCPText").hide();
|
|
}
|
|
);
|
|
|
|
jQuery(\'.clipboardCPValue, .clipboardCPButton, .clipboardCPValueToPrint\').click(function() {
|
|
console.log("We click on a clipboardCPButton or clipboardCPValueToPrint class and we want to copy content of clipboardCPValue class");
|
|
|
|
if (window.getSelection) {
|
|
jqobj=$(this).parent().children(".clipboardCPValue");
|
|
console.log(jqobj.html());
|
|
|
|
selection = window.getSelection(); /* get the object used for selection */
|
|
selection.removeAllRanges(); /* clear current selection */
|
|
|
|
/* 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);
|
|
selection.addRange(range); /* make the new selection with the value to copy */
|
|
|
|
/* 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 */
|
|
|
|
succeed = document.execCommand(\'copy\');
|
|
|
|
console.log("We set the style display back to inline-block");
|
|
jqobj.css("display", "inline-block");
|
|
} catch(e) {
|
|
succeed = false;
|
|
}
|
|
|
|
/* Remove the selection to avoid to see the hidden field to copy selected */
|
|
window.getSelection().removeAllRanges();
|
|
}
|
|
|
|
/* Show message */
|
|
/* TODO Show message into a top left corner or center of screen */
|
|
var lastchild = this.parentNode.lastChild; /* .parentNode is clipboardCP and last child is clipboardCPText */
|
|
var tmp = lastchild.innerHTML
|
|
if (succeed) {
|
|
lastchild.innerHTML = \'<div class="clipboardCPTextDivInside opacitymedium">'.dol_escape_js($langs->trans('CopiedToClipboard')).'</div>\';
|
|
} else {
|
|
lastchild.innerHTML = \'<div class="clipboardCPTextDivInside opacitymedium">'.dol_escape_js($langs->trans('Error')).'</div>\';
|
|
}
|
|
setTimeout(() => { lastchild.innerHTML = tmp; }, 1000);
|
|
});
|
|
});'."\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();
|
|
var currenttoken = jQuery("meta[name=anti-csrf-currenttoken]").attr("content");
|
|
console.log("We click on a cssforclicktodial class with href="+this.href);
|
|
$.ajax({
|
|
url: this.href,
|
|
type: \'GET\',
|
|
data: { token: currenttoken }
|
|
}).done(function(xhr, textStatus, errorThrown) {
|
|
/* do nothing */
|
|
}).fail(function(xhr, textStatus, errorThrown) {
|
|
alert("Error: "+textStatus);
|
|
});
|
|
return false;
|
|
});
|
|
});'."\n";
|
|
|
|
|
|
// Code to manage the confirm dialog box
|
|
print "\n/* JS CODE TO ENABLE DIALOG CONFIRM POPUP ON ACTION BUTTON */\n";
|
|
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 () {
|
|
window.location.replace(confirmUrl);
|
|
}
|
|
},
|
|
{
|
|
text: confirmCancelBtnLabel,
|
|
"class": \'ui-state-information\',
|
|
click: function () {
|
|
$(this).dialog("close");
|
|
}
|
|
}
|
|
],
|
|
close: function( event, ui ) {
|
|
$(\'#\'+confirmBox).remove();
|
|
},
|
|
open: function( event, ui ) {
|
|
$confirmBox.html(confirmContent);
|
|
}
|
|
});
|
|
});
|
|
});
|
|
'."\n";
|