LDAPAccountManager/lam/templates/lib/500_lam.js

1811 lines
52 KiB
JavaScript
Raw Normal View History

2010-01-01 17:20:49 +00:00
/**
This code is part of LDAP Account Manager (http://www.ldap-account-manager.org/)
2020-01-05 18:05:55 +00:00
Copyright (C) 2003 - 2020 Roland Gruber
2010-01-01 17:20:49 +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 2 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, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
2019-07-24 20:00:15 +00:00
window.lam = window.lam || {};
2011-04-09 10:04:56 +00:00
/**
* Called when user clicks on a table row. This toggles the checkbox in the row.
2016-12-07 20:18:06 +00:00
*
2011-04-09 10:04:56 +00:00
* @param box checkbox name
*/
function list_click(box) {
2011-05-07 12:03:55 +00:00
var cbox = document.getElementsByName(box)[0];
2019-10-15 14:06:46 +00:00
if (cbox.checked) {
2010-01-01 17:20:49 +00:00
cbox.checked = false;
}
else {
cbox.checked = true;
}
}
2010-02-14 18:10:53 +00:00
/**
* The user changed the value in the OU selection box. This will reload the list view with the new suffix.
2016-12-07 20:18:06 +00:00
*
2010-02-14 18:10:53 +00:00
* @param type account type
* @param element dropdown box
*/
function listOUchanged(type, element) {
location.href='list.php?type=' + type + '&suffix=' + element.options[element.selectedIndex].value;
2010-01-01 17:20:49 +00:00
}
/**
* The user pressed a key in the page number box. On enter this will reload the list view with the new page.
2016-12-07 20:18:06 +00:00
*
* @param url target URL
* @param e event
*/
function listPageNumberKeyPress(url, e) {
var pageNumber = jQuery('#listNavPage').val();
if (e.keyCode == 13) {
if (e.preventDefault) {
e.preventDefault();
}
location.href = url + '&page=' + pageNumber;
return false;
}
return true;
}
2011-04-09 10:04:56 +00:00
/**
* Shows the dialog to change the list settings.
2016-12-07 20:18:06 +00:00
*
2011-04-09 10:04:56 +00:00
* @param title dialog title
* @param okText text for Ok button
* @param cancelText text for Cancel button
*/
function listShowSettingsDialog(title, okText, cancelText) {
var buttonList = {};
buttonList[okText] = function() { document.forms["settingsDialogForm"].submit(); };
2013-02-22 19:30:43 +00:00
buttonList[cancelText] = function() { jQuery(this).dialog("close"); };
2011-04-09 10:04:56 +00:00
jQuery('#settingsDialog').dialog({
modal: true,
title: title,
dialogClass: 'defaultBackground',
buttons: buttonList,
width: 'auto'
});
}
2013-01-14 17:09:26 +00:00
/**
* Submits the form by clicking on the given button if enter was pressed.
2013-03-24 11:23:02 +00:00
* Example: SubmitForm('apply_filter', event);
2016-12-07 20:18:06 +00:00
*
2013-01-14 17:09:26 +00:00
* @param id button ID
* @param e event
* @returns Boolean result
*/
2010-01-01 17:20:49 +00:00
function SubmitForm(id, e) {
if (e.keyCode == 13) {
2012-03-10 15:37:21 +00:00
if (e.preventDefault) {
e.preventDefault();
}
if (e.returnValue) {
e.returnValue = false;
}
2013-01-12 11:34:08 +00:00
if (window.lastKeyCode) {
// no submit if last key code was arrow key (browser autocompletion)
if (window.lastKeyCode == 33 || window.lastKeyCode == 34 ||
window.lastKeyCode == 38 || window.lastKeyCode == 40) {
window.lastKeyCode = e.keyCode;
return true;
}
}
2010-01-01 17:20:49 +00:00
document.getElementsByName(id)[0].click();
return false;
}
2013-01-12 11:34:08 +00:00
window.lastKeyCode = e.keyCode;
2012-03-10 15:37:21 +00:00
return true;
2010-01-01 17:20:49 +00:00
}
2010-01-02 13:49:56 +00:00
function addResizeHandler(item, min, max) {
2013-07-21 11:31:20 +00:00
jQuery(item).click(
function() {
if (jQuery(item).hasClass('imgExpanded')) {
jQuery(item).animate({
height: min
});
}
else {
jQuery(item).animate({
height: max
});
}
jQuery(item).toggleClass('imgExpanded');
2010-01-02 13:49:56 +00:00
}
2016-12-07 20:18:06 +00:00
);
2010-01-02 13:49:56 +00:00
}
/**
* Selects/deselects all accounts on the page.
*/
function list_switchAccountSelection() {
// set checkbox selection
2013-03-16 14:32:27 +00:00
jQuery('input.accountBoxUnchecked').prop('checked', true);
jQuery('input.accountBoxChecked').prop('checked', false);
// switch CSS class
2018-12-23 09:41:33 +00:00
var nowChecked = jQuery('.accountBoxUnchecked');
var nowUnchecked = jQuery('.accountBoxChecked');
nowChecked.addClass('accountBoxChecked');
nowChecked.removeClass('accountBoxUnchecked');
nowUnchecked.addClass('accountBoxUnchecked');
nowUnchecked.removeClass('accountBoxChecked');
}
2010-07-29 20:37:56 +00:00
/**
* The user changed the value in the profile selection box. This will reload the login page with the new profile.
2016-12-07 20:18:06 +00:00
*
2010-07-29 20:37:56 +00:00
* @param element dropdown box
*/
function loginProfileChanged(element) {
location.href='login.php?useProfile=' + element.options[element.selectedIndex].value;
}
/**
* Shows the dialog to delete a profile.
2016-12-07 20:18:06 +00:00
*
* @param title dialog title
* @param okText text for Ok button
* @param cancelText text for Cancel button
* @param scope account type (e.g. user)
* @param selectFieldName name of select box with profile name
*/
function profileShowDeleteDialog(title, okText, cancelText, scope, selectFieldName) {
// get profile name
var profileName = jQuery('[name=' + selectFieldName + ']').val();
// update text
jQuery('#deleteText').text(profileName);
// update hidden input fields
jQuery('#profileDeleteType').val(scope);
jQuery('#profileDeleteName').val(profileName);
var buttonList = {};
buttonList[okText] = function() { document.forms["deleteProfileForm"].submit(); };
2013-02-22 19:30:43 +00:00
buttonList[cancelText] = function() { jQuery(this).dialog("close"); };
jQuery('#deleteProfileDialog').dialog({
modal: true,
title: title,
dialogClass: 'defaultBackground',
buttons: buttonList,
width: 'auto'
});
}
/**
2014-02-09 14:47:35 +00:00
* Shows a simple dialog.
2016-12-07 20:18:06 +00:00
*
* @param title dialog title
2015-06-16 18:59:56 +00:00
* @param okText text for Ok button (optional, submits form)
* @param cancelText text for Cancel button
2014-02-09 14:47:35 +00:00
* @param formID form ID
* @param dialogDivID ID of div that contains dialog content
*/
2014-02-09 14:47:35 +00:00
function showSimpleDialog(title, okText, cancelText, formID, dialogDivID) {
var buttonList = {};
2015-06-16 18:59:56 +00:00
if (okText) {
buttonList[okText] = function() { document.forms[formID].submit(); };
}
2013-02-22 19:30:43 +00:00
buttonList[cancelText] = function() { jQuery(this).dialog("close"); };
2014-02-09 14:47:35 +00:00
jQuery('#' + dialogDivID).dialog({
modal: true,
title: title,
dialogClass: 'defaultBackground',
buttons: buttonList,
width: 'auto'
});
}
2011-05-15 18:26:28 +00:00
/**
* Shows the dialog to change the password.
2016-12-07 20:18:06 +00:00
*
2011-05-15 18:26:28 +00:00
* @param title dialog title
* @param okText text for Ok button
* @param cancelText text for Cancel button
* @param randomText text for random password
* @param ajaxURL URL used for AJAX request
* @param tokenName name of CSRF token
* @param tokenValue value of CSRF token
2011-05-15 18:26:28 +00:00
*/
function passwordShowChangeDialog(title, okText, cancelText, randomText, ajaxURL, tokenName, tokenValue) {
2011-05-15 18:26:28 +00:00
var buttonList = {};
buttonList[okText] = function() { passwordHandleInput("false", ajaxURL, tokenName, tokenValue); };
buttonList[randomText] = function() { passwordHandleInput("true", ajaxURL, tokenName, tokenValue); };
2011-05-15 18:26:28 +00:00
buttonList[cancelText] = function() {
jQuery('#passwordDialogMessageArea').html("");
jQuery(this).dialog("close");
};
jQuery('#passwordDialog').dialog({
modal: true,
title: title,
dialogClass: 'defaultBackground',
buttons: buttonList,
width: 'auto'
});
// set focus on password field
var myElement = document.getElementsByName('newPassword1')[0];
myElement.focus();
}
/**
* Manages the password change when a button is pressed.
2016-12-07 20:18:06 +00:00
*
2011-05-15 18:26:28 +00:00
* @param random "true" if random password should be generated
* @param ajaxURL URL used for AJAX request
* @param tokenName name of CSRF token
* @param tokenValue value of CSRF token
2011-05-15 18:26:28 +00:00
*/
function passwordHandleInput(random, ajaxURL, tokenName, tokenValue) {
2011-05-15 18:26:28 +00:00
// get input values
var modules = new Array();
jQuery('#passwordDialog').find(':checked').each(function() {
2013-03-16 14:32:27 +00:00
modules.push(jQuery(this).prop('name'));
2011-05-15 18:26:28 +00:00
});
var pwd1 = jQuery('#passwordDialog').find('[name=newPassword1]').val();
var pwd2 = jQuery('#passwordDialog').find('[name=newPassword2]').val();
2013-03-16 14:32:27 +00:00
var forcePasswordChange = jQuery('input[name=lamForcePasswordChange]').prop('checked');
var sendMail = jQuery('input[name=lamPasswordChangeSendMail]').prop('checked');
2014-02-10 19:16:37 +00:00
var sendMailAlternateAddress = '';
if (jQuery('#passwordDialog').find('[name=lamPasswordChangeSendMailAddress]')) {
sendMailAlternateAddress = jQuery('#passwordDialog').find('[name=lamPasswordChangeSendMailAddress]').val();
}
2011-05-15 18:26:28 +00:00
var pwdJSON = {
"modules": modules,
"password1": pwd1,
"password2": pwd2,
"random": random,
"forcePasswordChange": forcePasswordChange,
"sendMail": sendMail,
"sendMailAlternateAddress": sendMailAlternateAddress
2011-05-15 18:26:28 +00:00
};
var data = {jsonInput: pwdJSON};
data[tokenName] = tokenValue;
2011-05-15 18:26:28 +00:00
// make AJAX call
2019-10-05 10:21:19 +00:00
jQuery.post(ajaxURL, data, function(dataReturned) {passwordHandleReply(dataReturned);}, 'json');
2011-05-15 18:26:28 +00:00
}
/**
* Manages the server reply to a password change request.
2016-12-07 20:18:06 +00:00
*
2011-05-15 18:26:28 +00:00
* @param data JSON reply
*/
function passwordHandleReply(data) {
if (data.errorsOccured == "false") {
jQuery('#passwordDialogMessageArea').html("");
jQuery('#passwordDialog').dialog("close");
jQuery('#passwordMessageArea').html(data.messages);
if (data.forcePasswordChange) {
jQuery('#forcePasswordChangeOption').attr('checked', 'checked');
}
2011-05-15 18:26:28 +00:00
}
else {
jQuery('#passwordDialogMessageArea').html(data.messages);
2016-12-07 20:18:06 +00:00
}
2011-05-15 18:26:28 +00:00
}
2011-06-06 18:06:51 +00:00
/**
* Shows a general confirmation dialog and submits a form if the user accepted.
2016-12-07 20:18:06 +00:00
*
2011-06-06 18:06:51 +00:00
* @param title dialog title
* @param okText text for Ok button
* @param cancelText text for Cancel button
* @param dialogDiv div that contains dialog content
* @param formName form to submit
2012-04-09 13:20:24 +00:00
* @param resultField (hidden) input field whose value is set to ok/cancel when button is pressed
2011-06-06 18:06:51 +00:00
*/
2012-04-09 13:20:24 +00:00
function showConfirmationDialog(title, okText, cancelText, dialogDiv, formName, resultField) {
2011-06-06 18:06:51 +00:00
var buttonList = {};
2012-04-09 13:20:24 +00:00
buttonList[okText] = function() {
2013-02-22 19:30:43 +00:00
jQuery('#' + dialogDiv).dialog('close');
2012-04-09 13:20:24 +00:00
if (resultField) {
jQuery('#' + resultField).val('ok');
2019-01-02 20:10:32 +00:00
}
2015-06-16 18:59:56 +00:00
appendDialogInputsToFormAndSubmit(dialogDiv, formName);
2012-04-09 13:20:24 +00:00
};
2013-02-22 19:30:43 +00:00
buttonList[cancelText] = function() {
if (resultField) {
jQuery('#' + resultField).val('cancel');
2019-01-02 20:10:32 +00:00
}
2013-02-22 19:30:43 +00:00
jQuery(this).dialog("close");
};
2011-06-06 18:06:51 +00:00
jQuery('#' + dialogDiv).dialog({
modal: true,
title: title,
dialogClass: 'defaultBackground',
buttons: buttonList,
width: 'auto'
});
}
2015-06-16 18:59:56 +00:00
/**
* Appends the input fields of a dialog back to the form and submits it.
2016-12-07 20:18:06 +00:00
*
2015-06-16 18:59:56 +00:00
* @param dialogDiv ID of dialog div
* @param formName name of form
*/
function appendDialogInputsToFormAndSubmit(dialogDiv, formName) {
var inputs = jQuery('#' + dialogDiv + ' :input');
inputs.each(function() {
jQuery(this).addClass('hidden');
jQuery(this).appendTo(document.forms[formName]);
});
document.forms[formName].submit();
}
/**
* Shows a simple confirmation dialog.
* If the user presses Cancel then the current action is stopped (event.preventDefault()).
2016-12-07 20:18:06 +00:00
*
* @param text dialog text
* @param e event
*/
function confirmOrStopProcessing(text, e) {
if (!confirm(text)) {
if (e.preventDefault) {
e.preventDefault();
}
if (e.returnValue) {
e.returnValue = false;
}
return false;
}
return true;
}
2012-10-28 14:37:54 +00:00
/**
* Alines the elements with the given IDs to the same width.
2016-12-07 20:18:06 +00:00
*
2012-10-28 14:37:54 +00:00
* @param elementIDs IDs
*/
function equalWidth(elementIDs) {
var maxWidth = 0;
for (var i = 0; i < elementIDs.length; ++i) {
if (jQuery(elementIDs[i]).width() > maxWidth) {
maxWidth = jQuery(elementIDs[i]).width();
2019-01-02 20:10:32 +00:00
}
2012-10-28 14:37:54 +00:00
}
2013-11-01 15:54:49 +00:00
if (maxWidth < 5) {
// no action if invalid width value (e.g. because of hidden tab)
return;
}
2019-10-15 14:06:46 +00:00
for (var elementId = 0; elementId < elementIDs.length; ++elementId) {
jQuery(elementIDs[elementId]).css({
'width': maxWidth - (jQuery(elementIDs[elementId]).outerWidth() - jQuery(elementIDs[elementId]).width())
});
2012-10-28 14:37:54 +00:00
}
}
2013-03-24 11:23:02 +00:00
/**
* Alines the elements with the given IDs to the same height.
2016-12-07 20:18:06 +00:00
*
2013-03-24 11:23:02 +00:00
* @param elementIDs IDs
*/
function equalHeight(elementIDs) {
var max = 0;
for (var i = 0; i < elementIDs.length; ++i) {
if (jQuery(elementIDs[i]).height() > max) {
max = jQuery(elementIDs[i]).height();
2019-01-02 20:10:32 +00:00
}
2013-03-24 11:23:02 +00:00
}
2019-10-15 14:06:46 +00:00
for (var elementId = 0; elementId < elementIDs.length; ++elementId) {
jQuery(elementIDs[elementId]).css({
'height': max - (jQuery(elementIDs[elementId]).outerHeight() - jQuery(elementIDs[elementId]).height())
});
2013-03-24 11:23:02 +00:00
}
}
2012-10-28 14:37:54 +00:00
/**
* Shows the dialog to change the list settings.
2016-12-07 20:18:06 +00:00
*
2012-10-28 14:37:54 +00:00
* @param title dialog title
* @param okText text for Ok button
* @param cancelText text for Cancel button
2017-01-03 19:02:29 +00:00
* @param typeId account type
2012-10-28 14:37:54 +00:00
* @param selectFieldName name of select box with profile name
*/
2017-01-03 19:02:29 +00:00
function showDistributionDialog(title, okText, cancelText, typeId, type, selectFieldName) {
2012-10-28 14:37:54 +00:00
// show dialog
var buttonList = {};
var dialogId = '';
2016-12-07 20:18:06 +00:00
2012-10-28 14:37:54 +00:00
if (type == 'export') {
2017-01-03 19:02:29 +00:00
jQuery('#name_' + typeId).val(jQuery('#' + selectFieldName).val());
dialogId = 'exportDialog_' + typeId;
buttonList[okText] = function() { document.forms["exportDialogForm_" + typeId].submit(); };
2012-10-28 14:37:54 +00:00
} else if (type == 'import') {
2017-01-03 19:02:29 +00:00
dialogId = 'importDialog_' + typeId;
buttonList[okText] = function() { document.forms["importDialogForm_" + typeId].submit(); };
2012-10-28 14:37:54 +00:00
}
2013-02-22 19:30:43 +00:00
buttonList[cancelText] = function() { jQuery(this).dialog("close"); };
2016-12-07 20:18:06 +00:00
2012-10-28 14:37:54 +00:00
jQuery('#' + dialogId).dialog({
modal: true,
title: title,
dialogClass: 'defaultBackground',
buttons: buttonList,
width: 'auto'
});
if (type == 'export') {
2017-01-03 19:02:29 +00:00
equalWidth(new Array('#passwd_' + typeId, '#destServerProfiles_' + typeId));
2012-10-28 14:37:54 +00:00
} else if (type == 'import') {
2017-01-03 19:02:29 +00:00
equalWidth(new Array('#passwd_' + typeId, '#importProfiles'));
2012-10-28 14:37:54 +00:00
}
}
2013-05-01 16:55:59 +00:00
/**
* Stores the current scroll position in the form.
2016-12-07 20:18:06 +00:00
*
2013-05-01 16:55:59 +00:00
* @param formName ID of form
*/
function saveScrollPosition(formName) {
var top = jQuery(window).scrollTop();
var left = jQuery(window).scrollLeft();
jQuery('<input>').attr({
type: 'hidden',
name: 'scrollPositionTop',
value: top
}).appendTo(jQuery('#' + formName));
jQuery('<input>').attr({
type: 'hidden',
name: 'scrollPositionLeft',
value: left
}).appendTo(jQuery('#' + formName));
2016-12-07 20:18:06 +00:00
}
2013-05-01 16:55:59 +00:00
2013-10-27 16:10:49 +00:00
/**
* Shows the dialog to create a DNS zone.
2016-12-07 20:18:06 +00:00
*
2013-10-27 16:10:49 +00:00
* @param title dialog title
* @param okText text for Ok button
* @param cancelText text for Cancel button
*/
function bindShowNewZoneDialog(title, okText, cancelText) {
var buttonList = {};
buttonList[okText] = function() { document.forms["newBindZoneDialogForm"].submit(); };
buttonList[cancelText] = function() { jQuery(this).dialog("close"); };
jQuery('#newBindZoneDialog').dialog({
modal: true,
title: title,
dialogClass: 'defaultBackground',
buttons: buttonList,
width: 'auto'
});
}
// creates the tooltips for help buttons
2013-10-20 18:07:56 +00:00
jQuery(document).ready(
function() {
jQuery(document).tooltip({
items: "[helpdata]",
content: function() {
var element = $(this);
var helpString = "<table><tr><th class=\"help\">";
helpString += element.attr("helptitle");
helpString += "</th></tr><td class=\"help\">";
helpString += element.attr("helpdata");
helpString += "</td></tr></table>";
return helpString;
}
})
}
);
/**
* Checks if the given field has the same value as the reference field.
* Field is marked red if different and green if equal.
2016-12-07 20:18:06 +00:00
*
* @param fieldID ID of field to check
* @param fieldIDReference ID of reference field
*/
function checkFieldsHaveSameValues(fieldID, fieldIDReference) {
var field = jQuery('#' + fieldID);
var fieldRef = jQuery('#' + fieldIDReference);
2016-12-07 20:18:06 +00:00
var check =
function() {
var value = field.val();
var valueRef = fieldRef.val();
if ((value == '') && (valueRef == '')) {
field.removeClass('markFail');
field.removeClass('markOk');
}
else {
if (value == valueRef) {
field.removeClass('markFail');
2016-12-07 20:18:06 +00:00
field.addClass('markOk');
}
else {
field.addClass('markFail');
field.removeClass('markOk');
}
}
}
jQuery(field).keyup(check);
jQuery(fieldRef).keyup(check);
}
/**
* Checks if the value of the given password field matches LAM's password policy.
* Field is marked red if fail and green if ok.
2016-12-07 20:18:06 +00:00
*
* @param fieldID ID of field to check
* @param tokenName name of CSRF token
* @param tokenValue value of CSRF token
*/
function checkPasswordStrength(fieldID, ajaxURL, tokenName, tokenValue) {
var field = jQuery('#' + fieldID);
2016-12-07 20:18:06 +00:00
var check =
function() {
var value = field.val();
var pwdJSON = {
"password": value
};
var data = {jsonInput: pwdJSON};
data[tokenName] = tokenValue;
// make AJAX call
2019-10-05 10:21:19 +00:00
jQuery.post(ajaxURL + "&function=passwordStrengthCheck", data, function(dataReturned) {checkPasswordStrengthHandleReply(dataReturned, fieldID);}, 'json');
};
jQuery(field).keyup(check);
}
/**
* Manages the server reply to a password strength check request.
2016-12-07 20:18:06 +00:00
*
* @param data JSON reply
* @param fieldID input field ID
*/
function checkPasswordStrengthHandleReply(data, fieldID) {
var field = jQuery('#' + fieldID);
2019-10-15 14:06:46 +00:00
if (data.result === true) {
field.removeClass('markFail');
field.addClass('markOk');
field.prop('title', '');
}
else if (field.val() == '') {
field.removeClass('markFail');
2016-12-07 20:18:06 +00:00
field.removeClass('markOk');
}
else {
field.addClass('markFail');
field.removeClass('markOk');
field.prop('title', data.result);
2016-12-07 20:18:06 +00:00
}
}
/**
* Updates the positions of a htmlSortable list in a hidden input field.
* The positions must be separated by comma (e.g. "0,1,2,3").
2016-12-07 20:18:06 +00:00
*
* @param id HTML ID of hidden input field
* @param oldPos old position
* @param newPos new position
*/
function updateModulePositions(id, oldPos, newPos) {
var positions = jQuery('#' + id).val().split(',');
if (newPos > oldPos) {
var save = positions[oldPos];
for (var i = oldPos; i < newPos; i++) {
positions[i] = positions[i + 1];
}
positions[newPos] = save;
}
if (newPos < oldPos) {
2019-10-15 14:06:46 +00:00
var oldPosition = positions[oldPos];
for (var position = oldPos; position > newPos; position--) {
positions[position] = positions[position - 1];
}
2019-10-15 14:06:46 +00:00
positions[newPos] = oldPosition;
}
jQuery('#' + id).val(positions.join(','));
}
2015-05-31 08:03:00 +00:00
2019-07-24 20:00:15 +00:00
window.lam.filterSelect = window.lam.filterSelect || {};
2015-05-31 08:03:00 +00:00
/**
* Filters a select box by the value of the filter input field.
2016-12-07 20:18:06 +00:00
*
2015-05-31 08:03:00 +00:00
* @param filterInput ID of input field for filter
* @param select ID of select box to filter
* @param event key event
*/
2019-07-24 20:00:15 +00:00
window.lam.filterSelect.activate = function (filterInput, select, event) {
var inputField = jQuery('#' + filterInput);
var selectField = jQuery('#' + select);
if (selectField.hasClass('lam-dynamicOptions')) {
window.lam.filterSelect.filterDynamic(inputField, selectField);
}
else {
window.lam.filterSelect.filterStandard(inputField, selectField);
}
}
/**
* Filters a normal select field.
*
* @param inputField input field with filter value
* @param selectField select field
*/
window.lam.filterSelect.filterStandard = function(inputField, selectField) {
2015-05-31 08:03:00 +00:00
// if values were not yet saved, save them
2019-07-24 20:00:15 +00:00
if (!selectField.data('options')) {
2015-05-31 08:03:00 +00:00
var options = [];
2019-07-24 20:00:15 +00:00
selectField.find('option').each(function() {
2015-05-31 08:03:00 +00:00
options.push({value: $(this).val(), text: $(this).text()});
});
2019-07-24 20:00:15 +00:00
selectField.data('options', options);
2015-05-31 08:03:00 +00:00
}
// get matching values
2019-07-24 20:00:15 +00:00
var list = selectField.empty().scrollTop(0).data('options');
var search = jQuery.trim(inputField.val());
2015-05-31 08:03:00 +00:00
var regex = new RegExp(search,'gi');
jQuery.each(list, function(i) {
var option = list[i];
if(option.text.match(regex) !== null) {
2019-07-24 20:00:15 +00:00
selectField.append(
2015-05-31 08:03:00 +00:00
jQuery('<option>').text(option.text).val(option.value)
);
}
});
}
2016-12-07 20:18:06 +00:00
2019-07-24 20:00:15 +00:00
/**
* Filters a select field with dynamic scrolling.
*
* @param inputField input field with filter value
* @param selectField select field
*/
window.lam.filterSelect.filterDynamic = function(inputField, selectField) {
var optionsOrig = selectField.data('dynamic-options-orig');
if (optionsOrig === undefined) {
selectField.data('dynamic-options-orig', selectField.data('dynamic-options'));
optionsOrig = selectField.data('dynamic-options-orig');
}
selectField.empty().scrollTop(0);
var newOptions = [];
// get matching values
var search = jQuery.trim(inputField.val());
var regex = new RegExp(search,'gi');
jQuery.each(optionsOrig, function(i) {
var option = optionsOrig[i];
if(option.label.match(regex) !== null) {
newOptions.push(option);
}
});
selectField.data('dynamic-options', newOptions);
window.lam.dynamicSelect.initSelect(selectField);
}
2016-12-07 20:18:06 +00:00
window.lam.upload = window.lam.upload || {};
/**
* Continues a CSV file upload.
*
* @param url URL where to get status JSON
* @param tokenName name of CSRF token
* @param tokenValue value of CSRF token
2016-12-07 20:18:06 +00:00
*/
window.lam.upload.continueUpload = function(url, tokenName, tokenValue) {
var data = {
jsonInput: ''
};
data[tokenName] = tokenValue;
2016-12-07 20:18:06 +00:00
jQuery.ajax({
url: url,
method: 'POST',
data: data
2016-12-07 20:18:06 +00:00
})
.done(function(jsonData){
if (!jsonData.accountsFinished) {
window.lam.upload.printBasicStatus(jsonData);
}
else if (!jsonData.postActionsFinished) {
window.lam.upload.printPostActionStatus(jsonData);
}
else if (!jsonData.pdfFinished) {
window.lam.upload.printPDFStatus(jsonData);
}
// next call if not finished
if (!jsonData.allDone) {
window.lam.upload.continueUpload(url, tokenName, tokenValue);
2016-12-07 20:18:06 +00:00
}
else {
window.lam.upload.uploadDone(jsonData);
}
});
};
/**
* Prints the upload status when accounts are still being created.
*
* @param jsonData status JSON
*/
window.lam.upload.printBasicStatus = function(jsonData) {
var htmlOut = '<div class="title">';
htmlOut += '<h2 class="titleText">' + jsonData.title + '</h2>';
htmlOut += '</div>';
htmlOut += '<div id="progressbarGeneral"></div>';
jQuery('#uploadContent').html(htmlOut);
jQuery('#progressbarGeneral').progressbar({
value: jsonData.accountsProgress
});
};
/**
* Prints the upload status when post actions run.
*
* @param jsonData status JSON
*/
window.lam.upload.printPostActionStatus = function(jsonData) {
var htmlOut = '<div class="title">';
htmlOut += '<h2 class="titleText">' + jsonData.title + '</h2>';
htmlOut += '</div>';
htmlOut += '<div id="progressbarGeneral"></div>';
if (jsonData.postActionsTitle) {
htmlOut += '<h2>' + jsonData.postActionsTitle + '</h2>';
htmlOut += '<div id="progressbarPostActions"></div>';
}
jQuery('#uploadContent').html(htmlOut);
jQuery('#progressbarGeneral').progressbar({
value: 100
});
if (jsonData.postActionsTitle) {
jQuery('#progressbarPostActions').progressbar({
value: jsonData.postActionsProgress
});
}
};
/**
* Prints the upload status when PDFs are generated.
*
* @param jsonData status JSON
*/
window.lam.upload.printPDFStatus = function(jsonData) {
var htmlOut = '<div class="title">';
htmlOut += '<h2 class="titleText">' + jsonData.title + '</h2>';
htmlOut += '</div>';
htmlOut += '<div id="progressbarGeneral"></div>';
htmlOut += '<h2>' + jsonData.titlePDF + '</h2>';
htmlOut += '<div id="progressbarPDF"></div>';
jQuery('#uploadContent').html(htmlOut);
jQuery('#progressbarGeneral').progressbar({
value: 100
});
jQuery('#progressbarPDF').progressbar({
value: jsonData.pdfProgress
});
};
/**
* Upload finished, check for errors.
*
* @param jsonData status JSON
*/
window.lam.upload.uploadDone = function(jsonData) {
if (jsonData.errorHtml) {
var htmlOut = '<div class="subTitle">';
htmlOut += '<h4 class="subTitleText">' + jsonData.titleErrors + '</h4>';
htmlOut += '</div>';
htmlOut += jsonData.errorHtml;
jQuery('#uploadContent').html(htmlOut);
}
else {
2017-01-07 17:23:04 +00:00
top.location.href = '../lists/list.php?type=' + jsonData.typeId + '&uploadAllOk';
2016-12-07 20:18:06 +00:00
}
2017-08-26 09:42:48 +00:00
};
2017-06-20 16:43:19 +00:00
2017-08-26 09:42:48 +00:00
window.lam.gui = window.lam.gui || {};
/**
* Resizes input fields etc. when they are marked as equally high.
*/
window.lam.gui.equalHeight = function() {
2019-02-23 17:42:21 +00:00
var maxHeight = 20;
2017-06-20 16:43:19 +00:00
jQuery('.lamEqualHeightTabContent').each(function() {
if (jQuery(this).height() > maxHeight) {
2019-02-23 17:42:21 +00:00
maxHeight = jQuery(this).height() + 20;
2019-01-02 20:10:32 +00:00
}
2017-06-20 16:43:19 +00:00
});
jQuery('.lamEqualHeightTabContent').each(function() {
jQuery(this).css({'height': maxHeight});
});
2017-08-26 09:42:48 +00:00
};
window.lam.form = window.lam.form || {};
/**
* Trims all marked input elements on form submission.
*/
window.lam.form.autoTrim = function() {
jQuery('form').submit(function(e) {
jQuery('.lam-autotrim').each(function() {
2019-02-01 18:35:31 +00:00
this.value = String(this.value).trim();
2017-08-26 09:42:48 +00:00
});
});
};
window.lam.dialog = window.lam.dialog || {};
2020-01-06 11:26:50 +00:00
/**
* Shows a dialog message.
*
* @param title dialog title
* @param okText ok button text
* @param divId DIV id with dialog content
* @param callbackFunction callback function (optional)
*/
2019-12-19 21:01:54 +00:00
window.lam.dialog.showMessage = function(title, okText, divId, callbackFunction) {
var buttonList = {};
2019-12-19 21:01:54 +00:00
buttonList[okText] = function() {
jQuery(this).dialog("close");
if (callbackFunction) {
callbackFunction();
}
};
jQuery('#' + divId).dialog({
modal: true,
title: title,
dialogClass: 'defaultBackground',
buttons: buttonList,
width: 'auto'
});
};
window.lam.account = window.lam.account || {};
/**
* Adds a listener on the link to set default profile.
*/
window.lam.account.addDefaultProfileListener = function() {
var defaultProfileLink = jQuery('#lam-make-default-profile');
if (defaultProfileLink) {
defaultProfileLink.click(function() {
var link = $(this);
var typeId = link.data('typeid');
var name = link.data('name');
var okText = link.data('ok');
var date = new Date();
date.setTime(date.getTime() + (365*24*60*60*1000));
document.cookie = 'defaultProfile_' + typeId + '=' + name + '; expires=' + date.toUTCString();
window.lam.dialog.showMessage(null, okText, 'lam-make-default-profile-dlg');
});
}
};
window.lam.tools = window.lam.tools || {};
/**
* Adds a listener on select lists to store the last value as default in local storage.
* Select lists need to be marked with class "lam-save-selection".
*/
window.lam.tools.addSavedSelectListener = function() {
if (!window.localStorage) {
return;
}
var selects = jQuery('.lam-save-selection');
if (selects) {
selects.each(function() {
var select = jQuery(this);
var name = select.attr('name');
var storageKey = 'lam_selectionStore_' + name;
// load value from local storage
var storageValue = window.localStorage.getItem(storageKey);
if (storageValue) {
var option = select.find('option[text="' + storageValue + '"]');
if (option) {
select.val(storageValue);
}
}
// add change listener
select.on('change', function() {
var selectedValue = this.value;
window.localStorage.setItem(storageKey, selectedValue);
});
});
}
};
2017-11-11 15:39:53 +00:00
/**
* Activates tabs.
*/
window.lam.tools.activateTab = function() {
2018-11-01 10:21:03 +00:00
jQuery('.lam-active-tab').addClass('ui-tabs-active ui-state-active');
2017-11-11 15:39:53 +00:00
};
2017-11-24 18:22:11 +00:00
/**
* Sets the focus on the initial field.
*/
window.lam.tools.setInitialFocus = function() {
jQuery('.lam-initial-focus').focus();
};
2018-01-12 16:57:32 +00:00
window.lam.tools.schema = window.lam.tools.schema || {};
/**
* Adds the onChange listener to schema selections.
*/
window.lam.tools.schema.select = function() {
var select = jQuery('#lam-schema-select');
var display = select.data('display');
select.change(function() {
var value = this.value;
document.location = 'schema.php?display=' + display + '&sel=' + value;
});
};
2018-09-23 18:12:27 +00:00
window.lam.importexport = window.lam.importexport || {};
2018-08-31 18:59:05 +00:00
/**
* Starts the import process.
*
* @param tokenName name of CSRF token
* @param tokenValue value of CSRF token
*/
2018-09-23 18:12:27 +00:00
window.lam.importexport.startImport = function(tokenName, tokenValue) {
2018-08-31 18:59:05 +00:00
jQuery(document).ready(function() {
2018-09-01 11:36:04 +00:00
jQuery('#progressbarImport').progressbar();
2018-08-31 18:59:05 +00:00
var output = jQuery('#importResults');
var data = {
jsonInput: ''
};
data[tokenName] = tokenValue;
jQuery.ajax({
url: '../misc/ajax.php?function=import',
method: 'POST',
data: data
})
.done(function(jsonData){
2018-09-01 11:36:04 +00:00
if (jsonData.data && (jsonData.data != '')) {
output.append(jsonData.data);
}
2018-08-31 18:59:05 +00:00
if (jsonData.status == 'done') {
jQuery('#progressbarImport').hide();
jQuery('#btn_submitImportCancel').hide();
jQuery('#statusImportInprogress').hide();
jQuery('#statusImportDone').show();
2018-09-01 11:36:04 +00:00
jQuery('.newimport').show();
}
else if (jsonData.status == 'failed') {
jQuery('#btn_submitImportCancel').hide();
jQuery('#statusImportInprogress').hide();
jQuery('#statusImportFailed').show();
jQuery('.newimport').show();
2018-08-31 18:59:05 +00:00
}
else {
jQuery('#progressbarImport').progressbar({
value: jsonData.progress
});
window.lam.import.startImport(tokenName, tokenValue);
}
});
});
};
2018-09-23 18:12:27 +00:00
/**
* Starts the export process.
*
* @param tokenName name of CSRF token
* @param tokenValue value of CSRF token
*/
window.lam.importexport.startExport = function(tokenName, tokenValue) {
jQuery(document).ready(function() {
jQuery('#progressbarExport').progressbar({value: 50});
var output = jQuery('#exportResults');
var data = {
jsonInput: ''
};
data[tokenName] = tokenValue;
data['baseDn'] = jQuery('#baseDn').val();
data['searchScope'] = jQuery('#searchScope').val();
data['filter'] = jQuery('#filter').val();
data['attributes'] = jQuery('#attributes').val();
data['format'] = jQuery('#format').val();
data['ending'] = jQuery('#ending').val();
data['includeSystem'] = jQuery('#includeSystem').val();
data['saveAsFile'] = jQuery('#saveAsFile').val();
jQuery.ajax({
url: '../misc/ajax.php?function=export',
method: 'POST',
data: data
})
.done(function(jsonData){
if (jsonData.data && (jsonData.data != '')) {
output.append(jsonData.data);
}
if (jsonData.status == 'done') {
jQuery('#progressbarExport').hide();
jQuery('#btn_submitExportCancel').hide();
jQuery('#statusExportInprogress').hide();
jQuery('#statusExportDone').show();
jQuery('.newexport').show();
2018-10-04 19:07:55 +00:00
if (jsonData.output) {
jQuery('#exportResults > pre').text(jsonData.output);
}
else if (jsonData.file) {
window.open(jsonData.file, '_blank');
}
2018-09-23 18:12:27 +00:00
}
else {
jQuery('#progressbarExport').hide();
jQuery('#btn_submitExportCancel').hide();
jQuery('#statusExportInprogress').hide();
jQuery('#statusExportFailed').show();
jQuery('.newexport').show();
}
2018-10-04 19:07:55 +00:00
})
.fail(function() {
jQuery('#progressbarExport').hide();
jQuery('#btn_submitExportCancel').hide();
jQuery('#statusExportInprogress').hide();
jQuery('#statusExportFailed').show();
jQuery('.newexport').show();
2018-09-23 18:12:27 +00:00
});
});
};
2018-10-06 17:47:33 +00:00
window.lam.html = window.lam.html || {};
/**
* Shows a DN selection for the given input field.
*
* @param fieldId id of input field
* @param title title of dialog
* @param okText ok button text
* @param cancelText cancel button text
* @param tokenName CSRF token name
* @param tokenValue CSRF token value
*/
window.lam.html.showDnSelection = function(fieldId, title, okText, cancelText, tokenName, tokenValue) {
var field = jQuery('#' + fieldId);
var fieldDiv = jQuery('#dlg_' + fieldId);
if (!fieldDiv.length > 0) {
jQuery('body').append(jQuery('<div class="hidden" id="dlg_' + fieldId + '"></div>'));
}
var dnValue = field.val();
var data = {
jsonInput: ''
};
data[tokenName] = tokenValue;
2018-10-11 14:52:38 +00:00
data['fieldId'] = fieldId;
2018-10-06 17:47:33 +00:00
data['dn'] = dnValue;
jQuery.ajax({
url: '../misc/ajax.php?function=dnselection',
method: 'POST',
data: data
})
2018-10-11 14:52:38 +00:00
.done(function(jsonData) {
jQuery('#dlg_' + fieldId).html(jsonData.dialogData);
2018-10-13 17:05:50 +00:00
var buttonList = {};
2018-10-14 07:16:55 +00:00
buttonList[cancelText] = function() { jQuery(this).dialog("destroy"); };
2018-10-13 17:05:50 +00:00
jQuery('#dlg_' + fieldId).dialog({
modal: true,
title: title,
dialogClass: 'defaultBackground',
buttons: buttonList,
2018-10-14 07:16:55 +00:00
width: 'auto',
maxHeight: 600,
position: {my: 'center', at: 'center', of: window}
2018-10-13 17:05:50 +00:00
});
2018-10-06 17:47:33 +00:00
});
};
2018-10-11 14:52:38 +00:00
/**
* Selects the DN from dialog.
2018-10-13 17:05:50 +00:00
*
2018-10-11 14:52:38 +00:00
* @param el ok button in dialog
* @param fieldId field id of input field
* @returns false
*/
window.lam.html.selectDn = function(el, fieldId) {
var field = jQuery('#' + fieldId);
var dn = jQuery(el).parents('.row').data('dn');
field.val(dn);
2018-10-14 07:16:55 +00:00
jQuery('#dlg_' + fieldId).dialog("destroy");
2018-10-11 14:52:38 +00:00
return false;
}
2018-10-13 17:05:50 +00:00
/**
* Updates the DN selection.
*
* @param el element
* @param fieldId field id of dialog
* @param tokenName CSRF token name
* @param tokenValue CSRF token value
*/
window.lam.html.updateDnSelection = function(el, fieldId, tokenName, tokenValue) {
var fieldDiv = jQuery('#dlg_' + fieldId);
var dn = jQuery(el).parents('.row').data('dn');
var data = {
jsonInput: ''
};
data[tokenName] = tokenValue;
data['fieldId'] = fieldId;
data['dn'] = dn;
jQuery.ajax({
url: '../misc/ajax.php?function=dnselection',
method: 'POST',
data: data
})
.done(function(jsonData) {
jQuery('#dlg_' + fieldId).html(jsonData.dialogData);
jQuery(fieldDiv).dialog({
position: {my: 'center', at: 'center', of: window}
});
})
.fail(function() {
jQuery(fieldDiv).dialog("close");
});
}
2018-10-28 15:10:29 +00:00
/**
* Activates the lightboxes on images.
*/
window.lam.html.activateLightboxes = function() {
jQuery('.lam-lightbox').magnificPopup({
type:'image',
zoom: {
enabled: true
}
});
};
2018-12-29 19:06:13 +00:00
/**
* Prevents enter key on input fields with class "lam-prevent-enter".
*/
window.lam.html.preventEnter = function() {
jQuery('.lam-prevent-enter').keypress(function (event) {
if (event.keyCode === 10 || event.keyCode === 13) {
event.preventDefault();
}
});
}
2019-07-24 19:29:26 +00:00
window.lam.dynamicSelect = window.lam.dynamicSelect || {};
/**
* Activates dynamic selection for all marked select fields.
*/
window.lam.dynamicSelect.activate = function() {
var dynamicSelects = jQuery('.lam-dynamicOptions');
dynamicSelects.each(function() {
var selectField = jQuery(this);
2019-07-24 19:32:25 +00:00
window.lam.dynamicSelect.initSelect(selectField);
2019-07-24 19:29:26 +00:00
});
}
2019-07-24 19:32:25 +00:00
/**
* Sets up a select field for dynamic scrolling.
*
* @param selectField select
*/
window.lam.dynamicSelect.initSelect = function(selectField) {
selectField.data('option-height', selectField.find("option").height());
selectField.data('select-height', selectField.height());
selectField.data('select-last-scroll-top', 0);
selectField.data('select-current-scroll', 0);
selectField.html('');
var options = selectField.data('dynamic-options');
var maxOptions = 3000;
var numOfOptionBeforeToLoadNextSet = 10;
var numberOfOptionsToLoad = 200;
for (var i = 0; i < maxOptions; i++) {
selectField.append(window.lam.dynamicSelect.createOption(options[i], i));
}
if (options.length > maxOptions) {
// activate scrolling logic only if enough options are set
selectField.scroll(function(event) {
window.lam.dynamicSelect.onScroll(selectField, event, maxOptions, numOfOptionBeforeToLoadNextSet, numberOfOptionsToLoad);
});
}
}
2019-07-24 19:29:26 +00:00
/**
* Creates an option field inside the select.
*
* @param data option data
* @param index index in list of all options
* @returns option
*/
window.lam.dynamicSelect.createOption = function(data, index) {
var newOption = jQuery(document.createElement("option"));
newOption.attr('value', data.value);
newOption.data('index', index);
newOption.text(data.label);
return newOption;
}
/**
* Onscroll event.
*
* @param selectField select field
* @param event event
* @param maxOptions maximum options to show
* @param numOfOptionBeforeToLoadNextSet number of options to reach before end of list
* @param numberOfOptionsToLoad number of options to add
*/
window.lam.dynamicSelect.onScroll = function(selectField, event, maxOptions, numOfOptionBeforeToLoadNextSet, numberOfOptionsToLoad) {
var scrollTop = selectField.scrollTop();
var totalHeight = selectField.find("option").length * selectField.data('option-height');
var lastScrollTop = selectField.data('select-last-scroll-top');
var selectBoxHeight = selectField.data('select-height');
var singleOptionHeight = selectField.data('option-height');
var currentScroll = scrollTop + selectBoxHeight;
selectField.data('select-current-scroll-top', scrollTop);
if ((scrollTop >= lastScrollTop)
&& ((currentScroll + (numOfOptionBeforeToLoadNextSet * singleOptionHeight)) >= totalHeight)) {
window.lam.dynamicSelect.loadNextOptions(selectField, maxOptions, numberOfOptionsToLoad);
}
else if ((scrollTop <= lastScrollTop)
&& ((scrollTop - (numOfOptionBeforeToLoadNextSet * singleOptionHeight)) <= 0)) {
window.lam.dynamicSelect.loadPreviousOptions(selectField, maxOptions, numberOfOptionsToLoad);
}
selectField.data('select-last-scroll-top', scrollTop);
}
/**
* Loads the next bunch of options at the end.
*
* @param selectField selct field
* @param maxOptions maximum options to show
* @param numberOfOptionsToLoad number of options to add
*/
window.lam.dynamicSelect.loadNextOptions = function(selectField, maxOptions, numberOfOptionsToLoad) {
var selectBoxHeight = selectField.data('select-height');
var singleOptionHeight = selectField.data('option-height');
var currentScrollPosition = selectField.data('select-current-scroll-top') + selectBoxHeight;
var options = selectField.data('dynamic-options');
var lastIndex = selectField.children().last().data('index');
for (var toAdd = 0; toAdd < numberOfOptionsToLoad; toAdd++) {
var addPos = lastIndex + 1 + toAdd;
if (options[addPos] === undefined) {
break;
}
selectField.append(window.lam.dynamicSelect.createOption(options[addPos], addPos));
}
var numberOfOptions = selectField.children().length;
var toRemove = numberOfOptions - maxOptions;
if (toRemove > 0) {
selectField.children().slice(0, toRemove).remove();
}
else {
toRemove = 0;
}
selectField.scrollTop(currentScrollPosition - selectBoxHeight - (toRemove * singleOptionHeight));
}
/**
* Loads the next bunch of options at the beginning.
*
* @param selectField selct field
* @param maxOptions maximum options to show
* @param numberOfOptionsToLoad number of options to add
*/
window.lam.dynamicSelect.loadPreviousOptions = function(selectField, maxOptions, numberOfOptionsToLoad) {
var singleOptionHeight = selectField.data('option-height');
var currentScrollPosition = selectField.data('select-current-scroll-top');
var options = selectField.data('dynamic-options');
var lastIndex = selectField.children().first().data('index');
var added = 0;
for (var toAdd = 0; toAdd < numberOfOptionsToLoad; toAdd++) {
var addPos = lastIndex - 1 - toAdd;
if (options[addPos] === undefined) {
break;
}
added++;
selectField.prepend(window.lam.dynamicSelect.createOption(options[addPos], addPos));
}
var numberOfOptions = selectField.children().length;
var toRemove = numberOfOptions - maxOptions;
if (toRemove > 0) {
selectField.children().slice(maxOptions).remove();
}
selectField.scrollTop(currentScrollPosition + (added * singleOptionHeight));
}
window.lam.selfservice = window.lam.selfservice || {};
/**
* Deletes a value of a multi-value field.
*
* @param fieldNamePrefix prefix of input field name
* @param delButton delete button that was clicked
*/
window.lam.selfservice.delMultiValue = function(fieldNamePrefix, delButton) {
var fields = jQuery("input[name^='" + fieldNamePrefix + "']");
var isOnlyOneField = (fields.length === 1);
if (!isOnlyOneField) {
// move add button if present
var addButton = jQuery(delButton).siblings('.add-link');
if (addButton.length === 1) {
var lastLastDelLink = jQuery(fields[fields.length - 2]).parent().parent().find('.del-link');
var lastLastDelLinkParent = jQuery(lastLastDelLink[0]).parent();
jQuery(addButton[0]).appendTo(lastLastDelLinkParent[0]);
}
// delete row
var row = jQuery(delButton).closest(".row").parent();
row.remove();
}
else {
fields[0].value = '';
}
};
/**
* Adds a value to a multi-value field.
*
* @param fieldNamePrefix prefix of input field name
* @param addButton add button that was clicked
*/
window.lam.selfservice.addMultiValue = function(fieldNamePrefix, addButton) {
var fields = jQuery("input[name^='" + fieldNamePrefix + "']");
// get next field number
var lastFieldName = fields[fields.length - 1].name;
var lastFieldNameIndex = lastFieldName.substring(fieldNamePrefix.length);
var newFieldNameIndex = parseInt(lastFieldNameIndex) + 1;
// copy row
var row = jQuery(addButton).closest(".row").parent();
var clone = row.clone();
clone = clone.appendTo(row.parent());
var cloneInput = clone.find("input[name^='" + fieldNamePrefix + "']");
cloneInput[0].name = fieldNamePrefix + newFieldNameIndex;
cloneInput[0].id = fieldNamePrefix + newFieldNameIndex;
cloneInput[0].value = '';
// delete add link from old row
jQuery(addButton).remove();
};
2019-11-21 18:34:01 +00:00
window.lam.webauthn = window.lam.webauthn || {};
2020-01-16 20:12:55 +00:00
/**
* Returns the first unicode character.
*
* @param c char
* @returns {number} character
*/
window.lam.webauthn.charAt = function (c) {
return c.charCodeAt(0);
}
2019-11-21 18:34:01 +00:00
/**
* Starts the webauthn process.
*
* @param prefix path prefix for Ajax endpoint
2020-01-08 19:38:26 +00:00
* @param isSelfService runs as part of self service
2019-11-21 18:34:01 +00:00
*/
2020-01-08 19:38:26 +00:00
window.lam.webauthn.start = function(prefix, isSelfService) {
2019-11-21 18:34:01 +00:00
jQuery(document).ready(
function() {
2020-01-08 19:38:26 +00:00
window.lam.webauthn.run(prefix, isSelfService);
2019-11-21 18:34:01 +00:00
}
);
}
/**
* Checks if the user is registered and starts login/registration.
*
* @param prefix path prefix for Ajax endpoint
2020-01-08 19:38:26 +00:00
* @param isSelfService runs as part of self service
2019-11-21 18:34:01 +00:00
*/
2020-01-08 19:38:26 +00:00
window.lam.webauthn.run = function(prefix, isSelfService) {
2019-12-09 20:35:37 +00:00
jQuery('#btn_skip_webauthn').click(function () {
2020-01-16 20:01:57 +00:00
var form = jQuery("#2faform");
2019-12-09 20:35:37 +00:00
form.append('<input type="hidden" name="sig_response" value="skip"/>');
form.submit();
return;
});
2020-01-06 11:26:50 +00:00
const token = jQuery('#sec_token').val();
2019-11-21 18:34:01 +00:00
// check for webauthn support
if (!navigator.credentials || (typeof(PublicKeyCredential) === "undefined")) {
jQuery('.webauthn-error').show();
return;
}
2020-01-06 11:26:50 +00:00
const data = {
2019-11-21 18:34:01 +00:00
action: 'status',
2019-11-21 21:03:42 +00:00
jsonInput: '',
2019-11-21 18:34:01 +00:00
sec_token: token
};
2020-01-08 19:38:26 +00:00
const extraParam = isSelfService ? '&selfservice=true' : '';
2019-11-21 18:34:01 +00:00
jQuery.ajax({
2020-01-08 19:38:26 +00:00
url: prefix + 'misc/ajax.php?function=webauthn' + extraParam,
2019-11-21 18:34:01 +00:00
method: 'POST',
data: data
})
.done(function(jsonData) {
2019-11-24 08:45:57 +00:00
if (jsonData.action === 'register') {
2020-01-06 11:26:50 +00:00
const successCallback = function (publicKeyCredential) {
const form = jQuery("#2faform");
const response = btoa(JSON.stringify(publicKeyCredential));
form.append('<input type="hidden" name="sig_response" value="' + response + '"/>');
form.submit();
};
const errorCallback = function(error) {
2020-01-16 20:01:57 +00:00
var errorDiv = jQuery('#generic-webauthn-error');
var buttonLabel = errorDiv.data('button');
var dialogTitle = errorDiv.data('title');
2020-01-06 11:26:50 +00:00
errorDiv.text(error.message);
window.lam.dialog.showMessage(dialogTitle,
buttonLabel,
'generic-webauthn-error',
function () {
jQuery('#btn_logout').click();
});
};
window.lam.webauthn.register(jsonData.registration, successCallback, errorCallback);
2019-11-24 08:45:57 +00:00
}
2019-12-31 16:01:51 +00:00
else if (jsonData.action === 'authenticate') {
window.lam.webauthn.authenticate(jsonData.authentication);
}
2019-11-21 18:34:01 +00:00
})
.fail(function() {
2020-06-03 15:51:21 +00:00
console.log('WebAuthn failed');
2019-11-21 18:34:01 +00:00
});
}
2019-11-24 08:45:57 +00:00
/**
* Performs a webauthn registration.
*
* @param publicKey registration object
2020-01-06 11:26:50 +00:00
* @param successCallback callback function in case of all went fine
* @param errorCallback callback function in case of an error
*/
window.lam.webauthn.register = function(publicKey, successCallback, errorCallback) {
if (!(publicKey.challenge instanceof Uint8Array)) {
2020-01-16 20:12:55 +00:00
publicKey.challenge = Uint8Array.from(window.atob(publicKey.challenge), window.lam.webauthn.charAt);
publicKey.user.id = Uint8Array.from(window.atob(publicKey.user.id), window.lam.webauthn.charAt);
2020-01-06 11:26:50 +00:00
publicKey.rp.icon = window.location.href.substring(0, window.location.href.lastIndexOf("/")) + publicKey.rp.icon;
if (publicKey.excludeCredentials) {
2020-01-16 20:01:57 +00:00
for (var i = 0; i < publicKey.excludeCredentials.length; i++) {
var idOrig = publicKey.excludeCredentials[i]['id'];
2020-01-06 11:26:50 +00:00
idOrig = idOrig.replace(/-/g, "+").replace(/_/g, "/");
2020-01-16 20:01:57 +00:00
var idOrigDecoded = atob(idOrig);
2020-01-16 20:12:55 +00:00
var idArray = Uint8Array.from(idOrigDecoded, window.lam.webauthn.charAt)
2020-01-06 11:26:50 +00:00
publicKey.excludeCredentials[i]['id'] = idArray;
}
}
}
2020-01-16 20:18:39 +00:00
navigator.credentials.create({publicKey: publicKey})
2019-11-24 08:45:57 +00:00
.then(function (data) {
2020-01-16 20:01:57 +00:00
var publicKeyCredential = {
2019-11-24 08:45:57 +00:00
id: data.id,
type: data.type,
2019-11-30 07:48:01 +00:00
rawId: window.lam.webauthn.arrayToBase64String(new Uint8Array(data.rawId)),
2019-11-24 08:45:57 +00:00
response: {
2019-11-25 20:07:23 +00:00
clientDataJSON: window.lam.webauthn.arrayToBase64String(new Uint8Array(data.response.clientDataJSON)),
attestationObject: window.lam.webauthn.arrayToBase64String(new Uint8Array(data.response.attestationObject))
2019-11-24 08:45:57 +00:00
}
};
2020-01-06 11:26:50 +00:00
successCallback(publicKeyCredential);
2019-11-24 08:45:57 +00:00
}, function (error) {
console.log(error.message);
2020-01-06 11:26:50 +00:00
errorCallback(error);
2019-12-31 16:01:51 +00:00
});
}
/**
* Performs a webauthn authentication.
*
* @param publicKey authentication object
*/
window.lam.webauthn.authenticate = function(publicKey) {
2020-01-16 20:12:55 +00:00
publicKey.challenge = Uint8Array.from(window.atob(publicKey.challenge), window.lam.webauthn.charAt);
2020-01-16 20:01:57 +00:00
for (var i = 0; i < publicKey.allowCredentials.length; i++) {
var idOrig = publicKey.allowCredentials[i]['id'];
2019-12-31 16:01:51 +00:00
idOrig = idOrig.replace(/-/g, "+").replace(/_/g, "/");
2020-01-16 20:01:57 +00:00
var idOrigDecoded = atob(idOrig);
2020-01-16 20:12:55 +00:00
var idArray = Uint8Array.from(idOrigDecoded, window.lam.webauthn.charAt)
2019-12-31 16:01:51 +00:00
publicKey.allowCredentials[i]['id'] = idArray;
}
2020-01-16 20:18:39 +00:00
navigator.credentials.get({publicKey: publicKey})
2020-01-16 20:12:55 +00:00
.then(function(data) {
2020-01-16 20:01:57 +00:00
var publicKeyCredential = {
2019-12-31 16:01:51 +00:00
id: data.id,
type: data.type,
rawId: window.lam.webauthn.arrayToBase64String(new Uint8Array(data.rawId)),
response: {
authenticatorData: window.lam.webauthn.arrayToBase64String(new Uint8Array(data.response.authenticatorData)),
clientDataJSON: window.lam.webauthn.arrayToBase64String(new Uint8Array(data.response.clientDataJSON)),
signature: window.lam.webauthn.arrayToBase64String(new Uint8Array(data.response.signature)),
userHandle: data.response.userHandle ? window.lam.webauthn.arrayToBase64String(new Uint8Array(data.response.userHandle)) : null
}
};
2020-01-16 20:01:57 +00:00
var form = jQuery("#2faform");
var response = btoa(JSON.stringify(publicKeyCredential));
2019-12-31 16:01:51 +00:00
form.append('<input type="hidden" name="sig_response" value="' + response + '"/>');
form.submit();
2020-01-16 20:12:55 +00:00
}, function(error) {
2019-12-31 16:01:51 +00:00
console.log(error.message);
2020-01-16 20:01:57 +00:00
var errorDiv = jQuery('#generic-webauthn-error');
var buttonLabel = errorDiv.data('button');
var dialogTitle = errorDiv.data('title');
2019-12-31 16:01:51 +00:00
errorDiv.text(error.message);
window.lam.dialog.showMessage(dialogTitle,
buttonLabel,
'generic-webauthn-error',
function () {
2019-12-19 21:01:54 +00:00
jQuery('#btn_logout').click();
});
2019-11-24 08:45:57 +00:00
});
}
2019-11-21 18:34:01 +00:00
2019-11-25 20:07:23 +00:00
/**
* Converts an array to a base64 string.
*
* @param input array
* @returns base64 string
*/
window.lam.webauthn.arrayToBase64String = function(input) {
2020-01-16 20:30:33 +00:00
return btoa(String.fromCharCode.apply(null, input));
2019-11-25 20:07:23 +00:00
}
2020-01-04 17:28:25 +00:00
/**
* Sets up the device management on the main configuration page.
*/
window.lam.webauthn.setupDeviceManagement = function() {
2020-01-16 20:01:57 +00:00
var searchButton = jQuery('#btn_webauthn_search');
2020-01-04 17:28:25 +00:00
if (searchButton) {
searchButton.click(window.lam.webauthn.searchDevices);
}
2020-01-16 20:01:57 +00:00
var searchInput = jQuery('#webauthn_searchTerm');
2020-01-13 19:14:40 +00:00
if (searchInput) {
searchInput.keydown(function (event) {
if (event.keyCode == 13) {
event.preventDefault();
searchButton.click();
return false;
}
});
}
2020-01-04 17:28:25 +00:00
}
/**
* Searches for devices via Ajax call.
*
* @param event button click event
* @returns {boolean} false
*/
window.lam.webauthn.searchDevices = function(event) {
if (event !== null) {
event.preventDefault();
}
2020-01-16 20:01:57 +00:00
var resultDiv = jQuery('#webauthn_results');
var tokenValue = resultDiv.data('sec_token_value');
var searchData = jQuery('#webauthn_searchTerm').val();
var data = {
2020-01-04 17:28:25 +00:00
action: 'search',
jsonInput: '',
sec_token: tokenValue,
searchTerm: searchData
};
jQuery.ajax({
url: '../misc/ajax.php?function=webauthnDevices',
method: 'POST',
data: data
})
.done(function(jsonData) {
resultDiv.html(jsonData.content);
window.lam.webauthn.addDeviceActionListeners();
})
.fail(function() {
2020-06-03 15:51:21 +00:00
console.log('WebAuthn search failed');
2020-01-04 17:28:25 +00:00
});
return false;
}
/**
* Adds listeners to the device action buttons.
*/
window.lam.webauthn.addDeviceActionListeners = function() {
2020-01-16 20:01:57 +00:00
var inputs = jQuery('.webauthn-delete');
2020-01-04 17:28:25 +00:00
inputs.each(function() {
jQuery(this).click(function(event) {
window.lam.webauthn.removeDevice(event);
});
});
}
/**
* Removes a webauthn device.
*
2020-01-05 18:05:55 +00:00
* @param event click event
2020-01-04 17:28:25 +00:00
*/
window.lam.webauthn.removeDevice = function(event) {
event.preventDefault();
2020-01-16 20:01:57 +00:00
var element = jQuery(event.target);
2020-01-05 18:05:55 +00:00
window.lam.webauthn.removeDeviceDialog(element, 'webauthnDevices');
return false;
}
/**
* Removes a user's own webauthn device.
*
* @param event click event
2020-01-10 19:06:24 +00:00
* @param isSelfService run in self service or admin context
2020-01-05 18:05:55 +00:00
*/
2020-01-10 19:06:24 +00:00
window.lam.webauthn.removeOwnDevice = function(event, isSelfService) {
2020-01-05 18:05:55 +00:00
event.preventDefault();
2020-01-16 20:01:57 +00:00
var element = jQuery(event.currentTarget);
var successCallback = null;
2020-01-11 16:29:05 +00:00
if (!isSelfService) {
successCallback = function () {
2020-01-16 20:01:57 +00:00
var form = jQuery("#webauthnform");
2020-01-11 16:29:05 +00:00
jQuery('<input>').attr({
type: 'hidden',
name: 'removed',
value: 'true'
}).appendTo(form);
form.submit();
};
}
2020-01-16 20:01:57 +00:00
var action = 'webauthnOwnDevices';
2020-01-10 19:06:24 +00:00
if (isSelfService) {
action = action + '&selfservice=true&module=webauthn&scope=user';
}
window.lam.webauthn.removeDeviceDialog(element, action, successCallback);
2020-01-05 18:05:55 +00:00
return false;
}
/**
* Opens the remove device diaog.
*
* @param element delete button
* @param action action for request (delete|deleteOwn)
2020-01-06 11:26:50 +00:00
* @param successCallback callback if all was fine (optional)
2020-01-05 18:05:55 +00:00
*/
2020-01-06 11:26:50 +00:00
window.lam.webauthn.removeDeviceDialog = function(element, action, successCallback) {
2020-01-16 20:01:57 +00:00
var dialogTitle = element.data('dialogtitle');
var okText = element.data('oktext');
var cancelText = element.data('canceltext');
var buttonList = {};
2020-01-05 16:53:12 +00:00
buttonList[okText] = function() {
jQuery('#webauthnDeleteConfirm').dialog('close');
2020-01-06 11:26:50 +00:00
window.lam.webauthn.sendRemoveDeviceRequest(element, action, successCallback);
2020-01-05 16:53:12 +00:00
};
buttonList[cancelText] = function() {
jQuery(this).dialog("close");
};
jQuery('#webauthnDeleteConfirm').dialog({
modal: true,
title: dialogTitle,
dialogClass: 'defaultBackground',
buttons: buttonList,
width: 'auto'
});
}
/**
* Sends the remove request to server.
*
* @param element button element
2020-01-05 18:05:55 +00:00
* @param action action (delete|deleteOwn)
2020-01-06 11:26:50 +00:00
* @param successCallback callback if all was fine (optional)
2020-01-05 16:53:12 +00:00
*/
2020-01-06 11:26:50 +00:00
window.lam.webauthn.sendRemoveDeviceRequest = function(element, action, successCallback) {
2020-01-16 20:01:57 +00:00
var dn = element.data('dn');
var credential = element.data('credential');
var resultDiv = jQuery('#webauthn_results');
var tokenValue = resultDiv.data('sec_token_value');
var data = {
2020-01-04 17:28:25 +00:00
action: 'delete',
jsonInput: '',
sec_token: tokenValue,
dn: dn,
credentialId: credential
};
jQuery.ajax({
2020-01-05 18:05:55 +00:00
url: '../misc/ajax.php?function=' + action,
2020-01-04 17:28:25 +00:00
method: 'POST',
data: data
})
2020-01-05 16:53:12 +00:00
.done(function(jsonData) {
2020-01-06 11:26:50 +00:00
if (successCallback) {
successCallback();
}
else {
resultDiv.html(jsonData.content);
}
2020-01-05 16:53:12 +00:00
})
.fail(function() {
2020-06-03 15:51:21 +00:00
console.log('WebAuthn device deletion failed');
2020-01-05 16:53:12 +00:00
});
2020-01-04 17:28:25 +00:00
}
2020-01-06 11:26:50 +00:00
/**
* Registers a user's own webauthn device.
*
* @param event click event
2020-01-11 16:29:05 +00:00
* @param isSelfService runs in self service context
2020-01-06 11:26:50 +00:00
*/
2020-01-11 16:29:05 +00:00
window.lam.webauthn.registerOwnDevice = function(event, isSelfService) {
2020-01-06 11:26:50 +00:00
event.preventDefault();
2020-01-16 20:01:57 +00:00
var element = jQuery(event.target);
var dn = element.data('dn');
var tokenValue = element.data('sec_token_value');
var publicKey = element.data('publickey');
var successCallback = function (publicKeyCredential) {
var form = jQuery("#webauthnform");
var response = btoa(JSON.stringify(publicKeyCredential));
var registrationData = jQuery('#registrationData');
2020-01-06 11:26:50 +00:00
registrationData.val(response);
form.submit();
};
2020-01-11 16:29:05 +00:00
if (isSelfService) {
successCallback = function (publicKeyCredential) {
2020-01-16 20:01:57 +00:00
var data = {
2020-01-11 16:29:05 +00:00
action: 'register',
jsonInput: '',
sec_token: tokenValue,
dn: dn,
credential: btoa(JSON.stringify(publicKeyCredential))
};
jQuery.ajax({
url: '../misc/ajax.php?selfservice=true&module=webauthn&scope=user',
method: 'POST',
data: data
})
.done(function(jsonData) {
2020-01-16 20:01:57 +00:00
var resultDiv = jQuery('#webauthn_results');
2020-01-11 16:29:05 +00:00
resultDiv.html(jsonData.content);
})
.fail(function() {
2020-06-03 15:51:21 +00:00
console.log('WebAuthn device registration failed');
2020-01-11 16:29:05 +00:00
});
};
}
2020-01-16 20:01:57 +00:00
var errorCallback = function (error) {
var errorDiv = jQuery('#generic-webauthn-error');
var buttonLabel = errorDiv.data('button');
var dialogTitle = errorDiv.data('title');
2020-01-06 11:26:50 +00:00
errorDiv.text(error.message);
window.lam.dialog.showMessage(dialogTitle,
buttonLabel,
'generic-webauthn-error'
);
};
window.lam.webauthn.register(publicKey, successCallback, errorCallback);
return false;
}
2017-08-26 09:42:48 +00:00
jQuery(document).ready(function() {
window.lam.gui.equalHeight();
window.lam.form.autoTrim();
window.lam.account.addDefaultProfileListener();
window.lam.tools.addSavedSelectListener();
2017-11-11 15:39:53 +00:00
window.lam.tools.activateTab();
2017-11-24 18:22:11 +00:00
window.lam.tools.setInitialFocus();
2018-01-12 16:57:32 +00:00
window.lam.tools.schema.select();
2018-10-28 15:10:29 +00:00
window.lam.html.activateLightboxes();
2018-12-29 19:06:13 +00:00
window.lam.html.preventEnter();
2019-07-24 19:29:26 +00:00
window.lam.dynamicSelect.activate();
2020-01-04 17:28:25 +00:00
window.lam.webauthn.setupDeviceManagement();
2017-06-20 16:43:19 +00:00
});
2019-05-20 14:30:12 +00:00
/**
2019-05-20 15:04:53 +00:00
* Setup service worker.
2019-05-20 14:30:12 +00:00
*/
if ("serviceWorker" in navigator) {
if (!navigator.serviceWorker.controller) {
var basePath = document.currentScript.src;
basePath = basePath.replace(/\/[^/]+\.js/gi, '');
var workerJS = basePath + '/../../pwa_worker.js';
navigator.serviceWorker.register(workerJS, {
scope : basePath + "../../"
});
}
}