/**
* ---------------------------------------------------------------------
* GLPI - Gestionnaire Libre de Parc Informatique
* Copyright (C) 2015-2020 Teclib' and contributors.
*
* http://glpi-project.org
*
* based on GLPI - Gestionnaire Libre de Parc Informatique
* Copyright (C) 2003-2014 by the INDEPNET Development Team.
*
* ---------------------------------------------------------------------
*
* LICENSE
*
* This file is part of GLPI.
*
* GLPI 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 2 of the License, or
* (at your option) any later version.
*
* GLPI 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 GLPI. If not, see .
* ---------------------------------------------------------------------
*/
/* global L */
var timeoutglobalvar;
if (typeof(String.prototype.normalize) !== 'function') {
$.ajax({
type: "GET",
url: CFG_GLPI.root_doc + "/public/lib/unorm.js",
dataType: "script",
cache: true
});
}
/**
* modifier la propriete display d'un element
*
* @param objet
* @param statut
**/
function setdisplay(objet, statut) {
var e = objet;
if (e.style.display != statut) {
e.style.display = statut;
}
return true;
}
/**
* @param id
**/
function cleandisplay(id) {
var e = document.getElementById(id);
if (e) {
setdisplay(e,'block');
}
}
/**
* @param id
**/
function cleanhide(id) {
var e = document.getElementById(id);
if (e) {
setdisplay(e,'none');
}
}
/**
* masquer le menu actif par timeout
*
* @param idMenu
**/
function afterView(idMenu) {
setdisplay(idMenu,'none');
}
/**
* @param id
* @param idMenu
**/
function menuAff(id, idMenu) {
var m = document.getElementById(idMenu);
var item = m.getElementsByTagName('li');
var ssmenu = null;
for (var i=0; i lastScrollTop && st > navbarHeight) {
// Scroll Down
$('#header').removeClass('nav-down').addClass('nav-up');
} else {
// Scroll Up
if (st + $(window).height() < $(document).height()) {
$('#header').removeClass('nav-up').addClass('nav-down');
}
}
lastScrollTop = st;
};
}
var langSwitch = function(elt) {
var _url = elt.attr('href').replace(/front\/preference.+/, 'ajax/switchlang.php');
$.ajax({
url: _url,
type: 'GET',
success: function(html) {
$('#language_link')
.html(html);
$('#debugajax').remove();
}
});
};
$(function() {
if ($('html').hasClass('loginpage')) {
return;
}
$('#menu.fullmenu li').on('mouseover', function() {
var _id = $(this).data('id');
menuAff('menu' + _id, 'menu');
});
$("body").delegate('td','mouseover mouseleave', function(e) {
var col = $(this).closest('tr').children().index($(this));
var tr = $(this).closest('tr');
if (!$(this).closest('tr').hasClass('noHover')) {
if (e.type == 'mouseover') {
tr.addClass("rowHover");
// If rowspan
if (tr.has('td[rowspan]').length === 0) {
tr.prevAll('tr:has(td[rowspan]):first').find('td[rowspan]').addClass("rowHover");
}
$(this).closest('table').find('tr:not(.noHover) th:nth-child('+(col+1)+')').addClass("headHover");
} else {
tr.removeClass("rowHover");
// remove rowspan
tr.removeClass("rowHover").prevAll('tr:has(td[rowspan]):first').find('td[rowspan]').removeClass("rowHover");
$(this).closest('table').find('tr:not(.noHover) th:nth-child('+(col+1)+')').removeClass("headHover");
}
}
});
// prevent jquery ui dialog to keep focus
$.ui.dialog.prototype._focusTabbable = function() {};
//quick lang switch
$('#language_link > a').on('click', function(event) {
event.preventDefault();
langSwitch($(this));
});
// ctrl+enter in form textareas (without tinymce)
$(document).on('keydown', '#page form textarea', function(event) {
if (event.ctrlKey
&& event.keyCode == 13) {
submitparentForm($(this));
}
});
// permits to have html in dialogs title
$.widget("ui.dialog", $.extend({}, $.ui.dialog.prototype, {
_title: function(title) {
if (!this.options.title ) {
title.html(" ");
} else {
title.html(this.options.title);
}
}
}));
});
/**
* Trigger submit event for a parent form of passed input dom element
*
* @param Object input the dom or jquery object of input
* @return bool
*/
var submitparentForm = function(input) {
// find parent form
var form = $(input).closest('form');
// find submit button(s)
var submit = form.find('[type=submit]').filter('[name=add], [name=update]');
// trigger if only one submit button
if (submit.length == 1) {
return (submit.trigger('click') !== false);
}
return false;
};
/**
* Determines if data from drop is an image.
*
* @param {Blob} file The file
* @return {boolean} True if image, False otherwise.
*/
var isImage = function(file) {
var validimagetypes = ["image/gif", "image/jpeg","image/jpg", "image/png"];
if ($.inArray(file.type, validimagetypes) < 0) {
return false;
} else {
return true;
}
};
/**
* Return a png url reprensenting an extension
*
* @param {String} ext the extension
* @return {string} an image html tag
*/
var getExtIcon = function(ext) {
var url = CFG_GLPI.root_doc+'/pics/icones/'+ext+'-dist.png';
if (!urlExists(url)) {
url = CFG_GLPI.root_doc+'/pics/icones/defaut-dist.png';
}
return '
';
};
/**
* Check for existence of an url
*
* @param {String} url
* @return {Bool}
*/
var urlExists = function(url) {
var exist = false;
$.ajax({
'type': 'HEAD',
'url': url,
'async': false,
'success': function() {
exist = true;
}
});
return exist;
};
/**
* Format a size to the last possible unit (o, Kio, Mio, etc)
*
* @param {integer} size
* @return {string} The formated size
*/
var getSize = function (size) {
var bytes = ['o', 'Kio', 'Mio', 'Gio', 'Tio'];
var lastval = '';
bytes.some(function(val) {
if (size > 1024) {
size = size / 1024;
} else {
lastval = val;
return true;
}
});
return Math.round(size * 100, 2) / 100 + lastval;
};
/**
* Convert a integer index into an excel like alpha index (A, B, ..., AA, AB, ...)
* @since 9.3
* @param integer index the numeric index
* @return string excel like string index
*/
var getBijectiveIndex = function(index) {
var bij_str = "";
while (parseInt(index) > 0) {
index--;
bij_str = String.fromCharCode("A".charCodeAt(0) + ( index % 26)) + bij_str;
index /= 26;
}
return bij_str;
};
/**
* Stop propagation and navigation default for the specified event
*/
var stopEvent = function(event) {
event.preventDefault();
event.stopPropagation();
};
/**
* Back to top implementation
*/
if ($('#backtotop').length) {
var scrollTrigger = 100, // px
backToTop = function () {
var scrollTop = $(window).scrollTop();
if (scrollTop > scrollTrigger) {
$('#backtotop').show('slow');
$('#see_debug').addClass('wbttop');
} else {
$('#backtotop').hide();
$('#see_debug').removeClass('wbttop');
}
};
backToTop();
$(window).on('scroll', function () {
backToTop();
});
$('#backtotop').on('click', function (e) {
e.preventDefault();
$('html,body').animate({
scrollTop: 0
}, 700);
});
}
/**
* Returns element height, including margins
*/
function _eltRealSize(_elt) {
var _s = 0;
_s += _elt.outerHeight();
_s += parseFloat(_elt.css('margin-top').replace('px', ''));
_s += parseFloat(_elt.css('margin-bottom').replace('px', ''));
_s += parseFloat(_elt.css('padding-top').replace('px', ''));
_s += parseFloat(_elt.css('padding-bottom').replace('px', ''));
return _s;
}
var initMap = function(parent_elt, map_id, height) {
// default parameters
map_id = (typeof map_id !== 'undefined') ? map_id : 'map';
height = (typeof height !== 'undefined') ? height : '200px';
if (height == 'full') {
//full height map
var wheight = $(window).height();
var _oSize = 0;
$('#header_top, #c_menu, #c_ssmenu2, #footer, .search_page').each(function(){
_oSize += _eltRealSize($(this));
});
_oSize += parseFloat($('#page').css('padding-top').replace('px', ''));
_oSize += parseFloat($('#page').css('padding-bottom').replace('px', ''));
_oSize += parseFloat($('#page').css('margin-top').replace('px', ''));
_oSize += parseFloat($('#page').css('margin-bottom').replace('px', ''));
var newHeight = Math.floor(wheight - _oSize);
var minHeight = 300;
if ( newHeight < minHeight ) {
newHeight = minHeight;
}
height = newHeight + 'px';
}
//add map, set a default arbitrary location
parent_elt.append($(''));
var map = L.map(map_id, {fullscreenControl: true}).setView([43.6112422, 3.8767337], 6);
//setup tiles and © messages
L.tileLayer('https://{s}.tile.osm.org/{z}/{x}/{y}.png', {
attribution: '© OpenStreetMap contributors'
}).addTo(map);
return map;
};
var showMapForLocation = function(elt) {
var _id = $(elt).data('fid');
var _items_id = $('#' + _id).val();
if (_items_id == 0) {
return;
}
var _dialog = $('');
_dialog.appendTo('body').dialog({
close: function() {
$(this).dialog('destroy').remove();
}
});
//add map, set a default arbitrary location
var map_elt = initMap($('#location_map_dialog'), 'location_map');
map_elt.spin(true);
$.ajax({
dataType: 'json',
method: 'POST',
url: CFG_GLPI.root_doc + '/ajax/getMapPoint.php',
data: {
itemtype: 'Location',
items_id: $('#' + _id).val()
}
}).done(function(data) {
if (data.success === false) {
_dialog.dialog('close');
$('' + data.message + '
').dialog({
close: function() {
$(this).dialog('destroy').remove();
}
});
} else {
var _markers = [];
var _marker = L.marker([data.lat, data.lng]);
_markers.push(_marker);
var _group = L.featureGroup(_markers).addTo(map_elt);
map_elt.fitBounds(
_group.getBounds(), {
padding: [50, 50],
maxZoom: 10
}
);
}
}).always(function() {
//hide spinner
map_elt.spin(false);
});
};
var query = {};
function markMatch (text, term) {
// Find where the match is
var match = text.toUpperCase().indexOf(term.toUpperCase());
var _result = $('');
// If there is no match, move on
if (match < 0) {
_result.append(escapeMarkupText(text));
return _result.html();
}
// Put in whatever text is before the match
_result.html(escapeMarkupText(text.substring(0, match)));
// Mark the match
var _match = $('');
_match.html(escapeMarkupText(text.substring(match, match + term.length)));
// Append the matching text
_result.append(_match);
// Put in whatever is after the match
_result.append(escapeMarkupText(text.substring(match + term.length)));
return _result.html();
}
/**
* Function that renders select2 results.
*/
var templateResult = function(result) {
var _elt = $('');
_elt.attr('title', result.title);
if (typeof query.term !== 'undefined' && typeof result.rendered_text !== 'undefined') {
_elt.html(result.rendered_text);
} else {
if (!result.text) {
return null;
}
var text = result.text;
if (!result.id) {
// If result has no id, then it is used as an optgroup and is not used for matches
_elt.html(escapeMarkupText(text));
return _elt;
}
var _term = query.term || '';
var markup = markMatch(text, _term);
if (result.level) {
var a='';
var i=result.level;
while (i>1) {
a = a+' ';
i=i-1;
}
_elt.html(a+'»'+markup);
} else {
_elt.html(markup);
}
}
return _elt;
};
// delay function who reinit timer on each call
var typewatch = (function(){
var timer = 0;
return function(callback, ms){
clearTimeout (timer);
timer = setTimeout(callback, ms);
};
})();
/**
* Function that renders select2 selections.
*/
var templateSelection = function (selection) {
if (!("element" in selection)) {
return selection.text;
}
// Data generated by ajax containing 'selection_text'
if (Object.prototype.hasOwnProperty.call(selection, 'selection_text')) {
return selection.selection_text;
}
// Data generated with optgroups
if (selection.element.parentElement.nodeName == 'OPTGROUP') {
return selection.element.parentElement.getAttribute('label') + ' - ' + selection.text;
}
// Default text
return selection.text;
};
/**
* Returns given text without is diacritical marks.
*
* @param {string} text
*
* @return {string}
*/
var getTextWithoutDiacriticalMarks = function (text) {
// Normalizing to NFD Unicode normal form decomposes combined graphemes
// into the combination of simple ones. The "è" becomes "e + ̀`".
text = text.normalize('NFD');
// The U+0300 -> U+036F range corresponds to diacritical chars.
// They are removed to keep only chars without their diacritical mark.
return text.replace(/[\u0300-\u036f]/g, '');
};
/**
* Escape markup in text to prevent XSS.
*
* @param {string} text
*
* @return {string}
*/
var escapeMarkupText = function (text) {
if (text.indexOf('>') !== -1 || text.indexOf('<') !== -1) {
// escape text, if it contains chevrons (can already be escaped prior to this point :/)
text = jQuery.fn.select2.defaults.defaults.escapeMarkup(text);
}
return text;
};
/**
* Updates an accessible progress bar title and foreground width.
* @since 9.5.0
* @param progressid ID of the progress bar
* @return void
*/
function updateProgress(progressid) {
var progress = $("progress#progress"+progressid).first();
$("div[data-progressid='"+progressid+"']").each(function(i, item) {
var j_item = $(item);
var fg = j_item.find(".progress-fg").first();
var calcWidth = (progress.attr('value') / progress.attr('max')) * 100;
fg.width(calcWidth+'%');
if (j_item.data('append-percent') === 1) {
var new_title = (j_item.prop('title').replace(new RegExp("\\d*%$"), progress.attr('value')+'%')).trim();
progress.prop('title', new_title);
j_item.prop('title', new_title);
}
});
}
/**
* Normalize altfield value of a MultiDatePicker instance.
*
* @param input_id id of the date input field
* @param date_format dateFormat option used in MultiDatePicker instance
* (i.e. 'dd-mm-yy', 'mm-dd-yy' or 'yy-mm-dd')
*
* @return void
*/
function normalizeMultiDateAltField(input_id, date_format) {
var dates = $(input_id).val().split(', ');
var alt_dates = [];
for (var i = 0; i < dates.length; i++) {
var date_obj = $.datepicker.parseDate(date_format, dates[i]);
alt_dates.push($.datepicker.formatDate('yy-mm-dd', date_obj));
}
$(input_id).val(alt_dates.join(', '));
}
/**
* Get RGB object from an hexadecimal color code
*
* @param {*} hex
* @returns {Object} {r, g, b}
*/
function hexToRgb(hex) {
var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
return result ? {
r: parseInt(result[1], 16),
g: parseInt(result[2], 16),
b: parseInt(result[3], 16)
} : null;
}
/**
* Get luminance for a color
* https://www.w3.org/TR/2008/REC-WCAG20-20081211/#relativeluminancedef
*
* @param {Array} rgb [r, g, b] array
* @returns {Number}
*/
function luminance(rgb) {
var a = rgb.map(function (v) {
v /= 255;
return v <= 0.03928
? v / 12.92
: Math.pow( (v + 0.055) / 1.055, 2.4 );
});
return a[0] * 0.2126 + a[1] * 0.7152 + a[2] * 0.0722;
}
/**
* Get contrast ratio between two colors
* https://www.w3.org/TR/2008/REC-WCAG20-20081211/#contrast-ratiodef
*
* @param {Array} rgb1 [r, g, b] array
* @param {Array} rgb2 [r, g, b] array
* @returns {Number}
*/
function contrast(rgb1, rgb2) {
return (luminance(rgb1) + 0.05) / (luminance(rgb2) + 0.05);
}
// fullscreen api
function GoInFullscreen(element) {
if (element.requestFullscreen) {
element.requestFullscreen();
} else if (element.mozRequestFullScreen) {
element.mozRequestFullScreen();
} else if (element.webkitRequestFullscreen) {
element.webkitRequestFullscreen();
} else if (element.msRequestFullscreen) {
element.msRequestFullscreen();
}
}
function GoOutFullscreen() {
if (document.exitFullscreen) {
document.exitFullscreen();
} else if (document.mozCancelFullScreen) {
document.mozCancelFullScreen();
} else if (document.webkitExitFullscreen) {
document.webkitExitFullscreen();
} else if (document.msExitFullscreen) {
document.msExitFullscreen();
}
}
function getUuidV4() {
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8);
return v.toString(16);
});
}
/** Track input changes and warn the user of unsaved changes if they try to navigate away */
window.glpiUnsavedFormChanges = false;
$(document).ready(function() {
// Forms must have the data-track-changes attribute set to true.
// Form fields may have their data-track-changes attribute set to empty (false) to override the tracking on that input.
$(document).on('input', 'form[data-track-changes="true"] input:not([data-track-changes=""]),' +
'form[data-track-changes="true"] textarea:not([data-track-changes="false"])', function() {
window.glpiUnsavedFormChanges = true;
});
$(document).on('change', 'form[data-track-changes="true"] select:not([data-track-changes=""])', function() {
window.glpiUnsavedFormChanges = true;
});
$(window).on('beforeunload', function(e) {
if (window.glpiUnsavedFormChanges) {
e.preventDefault();
// All supported browsers will show a localized message
return '';
}
});
$(document).on('submit', 'form', function() {
window.glpiUnsavedFormChanges = false;
});
});
function onTinyMCEChange(e) {
var editor = $(e.target)[0];
if ($(editor.targetElm).data('trackChanges') !== false) {
if ($(editor.formElement).data('trackChanges') === true) {
window.glpiUnsavedFormChanges = true;
}
}
}
function relativeDate(str) {
var s = ( +new Date() - Date.parse(str) ) / 1e3,
m = s / 60,
h = m / 60,
d = h / 24,
y = d / 365.242199,
tmp;
return (tmp = Math.round(s)) === 1 ? __('just now')
: m < 1.01 ? '%s seconds ago'.replace('%s', tmp)
: (tmp = Math.round(m)) === 1 ? __('a minute ago')
: h < 1.01 ? '%s minutes ago'.replace('%s', tmp)
: (tmp = Math.round(h)) === 1 ? __('an hour ago')
: d < 1.01 ? '%s hours ago'.replace('%s', tmp)
: (tmp = Math.round(d)) === 1 ? __('yesterday')
: y < 1.01 ? '%s days ago'.replace('%s', tmp)
: (tmp = Math.round(y)) === 1 ? __('a year ago')
: '%s years ago'.replace('%s', tmp);
}