<html><head><meta name="color-scheme" content="light dark"></head><body><pre style="word-wrap: break-word; white-space: pre-wrap;">const MONTHES_PER_YEAR = 12;

var element_id_counter = 1;

function Pred(value)
{
	return value - 1;
}

function Succ(value)
{
	return value + 1;
}

function AddLeadingChars(text, length, addingChar)
{
	addingChar = addingChar || "0";
	let result = '' + text;	
	while (result.length &lt; length)
		result = addingChar + result;			
	return result;
}


function DecodeDate(date) 
{	
	var result = {};
	result.year = date.getFullYear();
	result.day = AddLeadingChars(date.getDate(), 2);
	result.month = AddLeadingChars(date.getMonth() + 1, 2);		
	result.hours =  AddLeadingChars(date.getHours(), 2);
	result.minutes = AddLeadingChars(date.getMinutes(), 2); 
	result.seconds = AddLeadingChars(date.getSeconds(), 2);
	console.log(result);
	return result;
}

function openURLAnalyzePressedButtons(url)
{
	url = url || "";
	if (url != "")
	{
		var window_flag = "_self";
		if (event.ctrlKey) 
			window_flag = "_blank";	
		window.open(url, window_flag).focus();			
	}
}		

function FormatDate(date) 
{     
	const dateInfo = DecodeDate(date);
    return [dateInfo.day, dateInfo.month, dateInfo.year].join('.');
}

function FormatDateEn(date) 
{     
	const dateInfo = DecodeDate(date);
    return [dateInfo.year, dateInfo.month, dateInfo.day].join('-');
}

function FormatTime(date) 
{     
	const dateInfo = DecodeDate(date);
    return [dateInfo.hours, dateInfo.minutes, dateInfo.seconds].join(':');
}


function AddStackTrace()
{
	try {
        // Code throwing an exception
        throw new Error();
    } catch(e) {
        console.log(e.stack);
    }
}

function InRange(value, start, end)
{
	var result = (value &gt;= start);
	result = result &amp;&amp; (value &lt;= end);
	return result;
}

function ReadCurrentURLParam(param_name)
{
	return ReadURLParam(location.search, param_name);
}

function CompareInt(int1, int2)
{
	if (int1 != int2)
		return (int1 &gt; int2) ? 1 : -1;
	return 0;
}

function ReadURLParam(url, param_name)
{	
	/*var url = new URL(url_string);
	return url.searchParams.get(param_name);*/	
	var name = param_name;
	name = name.replace(/[\[]/, "\\[").replace(/[\]]/, "\\]");
	var regex = new RegExp("[\\?&amp;]" + name + "=([^&amp;#]*)");
    var results = regex.exec(url);	
	return results === null ? "" : decodeURIComponent(results[1].replace(/\+/g, " "));
}

function ChangeCurrentBrowserURL(url)
{
	if (url)
		window.history.replaceState("", "", url);				
}

function AddURLParameter(url, param, paramVal)
{
    var newAdditionalURL = "";
    var tempArray = url.split("?");
    var baseURL = tempArray[0];
    var additionalURL = tempArray[1];
    var temp = "";
    if (additionalURL) 
	{
        tempArray = additionalURL.split("&amp;");
        for (var i=0; i&lt;tempArray.length; i++){
            if(tempArray[i].split('=')[0] != param){
                newAdditionalURL += temp + tempArray[i];
                temp = "&amp;";
            }
        }
    }
    var rows_txt = temp + "" + param + "=" + paramVal;
    return baseURL + "?" + newAdditionalURL + rows_txt;
}

function RemoveURLParameter(url, param)
{
    let url_object = new URL(url);
	url_object.searchParams.delete(param);
	return url_object.href;
}

function ReplaceURLParameter(url, param, paramVal)
{
	var url_object = new URL(url);
	url_object.searchParams.set(param, paramVal);
	return url_object.href;
}

function GetBaseURL()
{
	return (location.protocol + '//' + location.host + location.pathname);
}

function Assigned(variable)
{
	var result = (variable != undefined);
	result = result &amp;&amp; (variable != "");
	return result;
}

function isDefined(variable)
{	
	return (!isUndefined(variable));
}

function isUndefined(variable)
{	
	return (typeof variable === "undefined");
}

function DecodeURIComponentFull(component)
{
	return decodeURIComponent(component.replace(/\+/g, '%20'));
}

function SubmitSerializedDataToServer(url, method, form_data)
{
	var form = document.createElement("form");
    form.setAttribute("method", method);
    form.setAttribute("action", url);
	var params_array = form_data.split("&amp;");
	for (var i = 0; i &lt; params_array.length; i++)
	{
		
		var param = params_array[i].split("=");
		var param_name = DecodeURIComponentFull(param[0]);		
		var param_value = "";
		if (param.length &gt; 1)
			param_value = DecodeURIComponentFull(param[1]);
		// console.log(param_name + ": " + param_value);		
		var hiddenField = document.createElement("input");
        hiddenField.setAttribute("type", "hidden");
		hiddenField.setAttribute("name", param_name);
        hiddenField.setAttribute("value", param_value);
        form.appendChild(hiddenField);
	}	
	document.body.appendChild(form);
	form.submit();
	document.body.removeChild(form);	
}

function GetAgePostfix(age)
{	
	if ((age &lt;= 4) || 
		(age &gt;= 20)) 
	{
		var age_leftover = age % 10;			
		switch (age_leftover)
		{			
			case 1: return "&lt;&lt;LANG_STR_34&gt;&gt;";
			case 2: 
			case 3: 
			case 4: return "&lt;&lt;LANG_STR_35&gt;&gt;";				
		}
	}
	return "&lt;&lt;LANG_STR_104&gt;&gt;";	
}

function AgeToString(age)
{	
	if (age &gt; 0)
		return age + " " + GetAgePostfix(age);
	return "";
}

function VarAsInt(variable) 
{
	var result = parseInt(variable, 10);
	if (isNaN(result))
		result = 0;
	return result;
}

function GetSelectBoxValue(select_box)
{
	if (select_box)
	{
		var selected_item = $(select_box).children("option:selected");
		if (selected_item) 						
			return selected_item.val();	
	}
	return ""; 		
}

function GetSelectBoxText(select_box)
{
	if (select_box)
	{
		var selected_item = $(select_box).children("option:selected");
		if (selected_item) 						
			return selected_item.text();																	
	}
	return ""; 		
}

function GetFileExtension(file_name)
{
	if ((file_name) &amp;&amp;
		(file_name.indexOf('.') &gt;= 0))
	{
		return file_name.split('.').pop();
	}
	return "";
}

function SetSelectBoxValue(select_box, value)
{
	if (select_box)
	{
		$(select_box).children("option").each(function (index, child) 
		{				
			// alert(child.value);
			if (child.value == value)			
				$(child).attr('selected', 'selected');						
			else
				$(child).removeAttr('selected');			
		});
	}	
}

function GetSelectBoxValueInt(select_box)
{
	var value = GetSelectBoxValue(select_box);
	if (value != "")
		return VarAsInt(value);
	return -1;		
}

function IsSelectBoxFilled(select_box)
{
	var value = GetSelectBoxValue(select_box);	
	return ((value != null)  &amp;&amp;
			(value != ""));	
}

function IsTextBoxFilled(text_box)
{		
	var value = $(text_box).val();		
	return ((value != null)  &amp;&amp;
			(value != ""));	
}	

function GetInputBoxValue(element) 
{
	return GetTextBoxValue(element);
}

function GetTextBoxValue(element) 
{
	if (element) {
		return $(element).val();				
	}
	return "";	

}

function GetElementTagName(element)
{
	if (element)
	{
		var jquery_element = $(element);
		if (jquery_element[0]) 		
			return jquery_element[0].tagName.toLowerCase();
	}
	return "";
}

function IsInputBox(element)
{	
	return (GetElementTagName(element) == "input");
}

function IsSelectBox(element)
{	
	return (GetElementTagName(element) == "select");
}

function IsTextArea(element)
{	
	return (GetElementTagName(element) == "textarea");
}

function IsCheckBox(element)
{	
	var result = IsInputBox(element);
	if (result)
		result = ($(element).attr('type').toLowerCase() == "checkbox");
	return result;
}

function GetElementValue(element)
{
	if (IsSelectBox(element))
		return GetSelectBoxValue(element);
	return GetInputBoxValue(element);
}

function IsAnchor(element)
{	
	return (GetElementTagName(element) == "a");
}

function IsImage(element)
{	
	return (GetElementTagName(element) == "img");
}

function IsRadioBox(element)
{
	var result = IsInputBox(element);
	if (result === true)
		result &amp;= (element.type.toLowerCase() == "radio");
	return result;
}

function IsInputFilled(element)
{
	if (element)
	{
		if (IsRadioBox(element))
			return IsRadioBoxFilled(element);
		else
		{
			var value = $(element).val();
			return IsTextBoxFilled(element);			
		}
	}
	return false;
}

function IsRadioBoxFilled(radio_box)
{	
	var result = false;
	var parent = $(radio_box).parent();	
	if (parent)
	{					
		$(parent).children().each(function (index, child) 
		{								
			if ((IsRadioBox(child)) &amp;&amp;
				(IsTextBoxFilled(child)) &amp;&amp;
				(child.checked === true))
			{								
				result = true;				
				return;
			}
		});
	}
	return result;
}

function SetRadioBoxCheckedByNameValue(name, value)
{	
	var selector = "input[name='" + name + "']";
	$(selector).each(function()
	{		
		if (this.value == value)
		{
			$(this).attr('checked', 'checked');
			return;
		}
	});
}

function GetUniqueElementID(element)
{
	if (element)
	{				
		if (!$(element).attr('id'))
		{
			$(element).attr('id', "id_" + element_id_counter);			
			element_id_counter++;
		}			
		return ($(element).attr('id'));		
	}
	return null;
}

function CreateUniqueString(max_length, alphabet)
{
	var result = "";
	alphabet = alphabet || "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";	
	if (!max_length)
		max_length = 32;
	for (var i = 0; i &lt; max_length; i++)
		result += alphabet.charAt(Math.floor(Math.random() * alphabet.length));
	return result;
}

function CreateUniqueFileName(ext, uniqueStringLength)
{	
	ext = ext || "";
	if (!uniqueStringLength)
		uniqueStringLength = 8;
	let currentDate = new Date();
	let dateInfo = DecodeDate(currentDate);    
	let result = [dateInfo.year, dateInfo.month, dateInfo.day].join('-') + " " + FormatTime(currentDate);		
	result = result.replace(/:/ig, "");
	result = result.replace(/ /ig, "-");
	result += "-" + CreateUniqueString(uniqueStringLength, "abcdef0123456789");
	if (ext != "")
		result += "." + ext;
	return result;
}

function isObject(val) 
{
    return (typeof val === 'object');
}

function isNumber(str) 
{
	var result = (str != null);	
	result = result &amp;&amp; (str.length != 0);
	result = result &amp;&amp; (str.match(/^\d+$/));
	return result;
}


function IsValidPhone(phone)
{
	if (phone) {
		var phone_regex = /^[\+]?[(]?[0-9]{3}[)]?[-\s\.]?[0-9]{3}[-\s\.]?[0-9]{4,6}$/im;
		if (phone_regex.test(phone)) {
			return true;		
		}
	}
	return false;	
}

function ValidateEmail(email) 
{
    const email_reg_ex = /^(([^&lt;&gt;()[\]\\.,;:\s@"]+(\.[^&lt;&gt;()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
    return email_reg_ex.test(String(email).toLowerCase());
}

function AnalyzeEmailControl(email_control, show_alert) 
{
	if ((email_control) &amp;&amp;
		(email_control != ""))
	{
		var user_email = GetInputBoxValue(email_control);
		var result  = ValidateEmail(user_email);
		if (!result)
		{	
			$(email_control).parent()[0].scrollIntoView({ behavior: 'smooth'});
			if (show_alert)
			{
				var message_str = "Ð£ÐºÐ°Ð·Ð°Ð½ Ð½ÐµÐ¿Ñ€Ð°Ð²Ð¸Ð»ÑŒÐ½Ñ‹Ð¹ Ñ„Ð¾Ñ€Ð¼Ð°Ñ‚ ÑÐ»ÐµÐºÑ‚Ñ€Ð¾Ð½Ð½Ð¾Ð¹ Ð¿Ð¾Ñ‡Ñ‚Ñ‹\n\n";
				message_str += "Ð£ÐºÐ°Ð¶Ð¸Ñ‚Ðµ Ð¿Ñ€Ð°Ð²Ð¸Ð»ÑŒÐ½ÑƒÑŽ ÑÐ»ÐµÐºÑ‚Ñ€Ð¾Ð½Ð½ÑƒÑŽ Ð¿Ð¾Ñ‡Ñ‚Ñƒ Ð¸ Ð¿Ð¾Ð²Ñ‚Ð¾Ñ€Ð¸Ñ‚Ðµ Ð¿Ð¾Ð¿Ñ‹Ñ‚ÐºÑƒ";			
				alert(message_str);		
			}
		}
		return result;
	}
	return false;
}

function AnalyzeBooleanCondition(condition, description, errorMessageObject)
{
	var result = condition;
	if ((!result) &amp;&amp;
		(errorMessageObject) &amp;&amp;
		(!errorMessageObject.error))
	{
		errorMessageObject.error = description;
	}
	return result;		
}

function IsJson(str) 
{
    try {
        JSON.parse(str);
    } catch (e) {
        return false;
    }
    return true;
}

// JQuery  additional functions

function JQueryGetOuterHTML(s) {	
	return (s) ? this.before(s).remove() : jQuery("&lt;p&gt;").append(this.eq(0).clone()).html();
} 	

function JQueryChangeVisibility(visible) {	
	if (visible == true)		
		this.show();
	else
		this.hide();
} 

function JQueryInsertAtIndex(element, index) 
{	
	var lastIndex = this.children().size();
	if (index &lt; 0) {
		index = Math.max(0, lastIndex + 1 + index);
	}
	this.append(element);
	if (index &lt; lastIndex) {
		this.children().eq(index).before(this.children().last());
	}
	return this;
} 

function JQueryRemoveAttributes(except_array) 
{
	return this.each(function() 
	{
		var attributes = $.map(this.attributes, function(item) 
		{
		  return item.name;
		});
		var element = $(this);
		$.each(attributes, function(i, item) 
		{
			var should_delete = true;
			if (except_array)
			{
				console.log(except_array);
				should_delete = should_delete &amp;&amp; (except_array.indexOf(item) &lt; 0);
				console.log(item + ": " + except_array.indexOf(item));
			}
			if (should_delete)
				element.removeAttr(item);
		});
	});
}

function UpdateJQueryAdditionalFunctions()
{
	jQuery.fn.outerHTML = JQueryGetOuterHTML;
	jQuery.fn.changeVisibility = JQueryChangeVisibility;
	jQuery.fn.insertAt = JQueryInsertAtIndex;
	jQuery.fn.removeAttributes = JQueryRemoveAttributes;
}

function Assigned(variable)
{
	let result = (variable != null);
	result = result &amp;&amp; (typeof variable !== 'undefined');
	if (result)
	{
		if ((typeof variable === 'string') || 
			(variable instanceof String))
		{
			result = result &amp;&amp; (variable != "");
		}
	}
	return result;
}

function SetCookie(cookie_name, cookie_value, expire_days) 
{
	if (Assigned(cookie_name))
	{
		var expires = "";
		if (expire_days &gt; 0)
		{
			var date_expire = new Date();
			date_expire.setTime(date_expire.getTime() + (expire_days * 24 * 60 * 60 * 1000));
			var expires = "; expires=" + date_expire.toGMTString();
		}
		document.cookie = cookie_name + "=" + cookie_value + expires + "; path=/";		   
	}
}

function ClearCookie(cookie_name) 
{		
	SetCookie(cookie_name, "");
}

function GetCookie(cookie_name) 
{		
	var match = document.cookie.match(new RegExp('(^| )' + cookie_name + '=([^;]+)'));	
	if (match) 				
		return match[2];
	return "";
}


function ExecuteHTTPRequest(url, data, on_request_successed, on_request_finish, isNotAsync)
{
	isNotAsync = isNotAsync || false;
	return $.ajax(
	{
		url: url,
		type: 'POST',		
		data: data,
		async: (!isNotAsync),
		success: function(response)	  
		{		
			if (on_request_successed)
				on_request_successed(response);			
		},
		complete: function(response)
		{
			if (on_request_finish)
				on_request_finish(response);			
		}
	});	
}

function ProcessJsonRequest(server_answer, on_request_successed, on_request_error)
{
	if (server_answer.status == "ok") 					
	{				
		if (on_request_successed)
			on_request_successed(server_answer);
		return true;
	}
	else if (server_answer.status == "error") 
	{
		if (on_request_error)
			on_request_error(server_answer);
		else
			alert(server_answer.error_desc);
		return true;
	}
	return false;
}

function ExecuteAjaxRequest(url, data, on_request_successed, on_request_error, on_request_finish, isNotAsync)
{
	
	return ExecuteHTTPRequest(url, data, function(response) 
	{		
		var server_answer = JSON.parse(response);						
		ProcessJsonRequest(server_answer, on_request_successed, on_request_error);				
	}, on_request_finish, isNotAsync);
}

function ExecuteMixedRequest(url, data, on_request_successed, on_request_error, on_request_finish, isNotAsync)
{
	return ExecuteHTTPRequest(url, data, function(response) 
	{				
		if (IsJson(response))
		{
			var server_answer = JSON.parse(response);				
			if (server_answer) 
			{
				if ((!ProcessJsonRequest(server_answer, on_request_successed, on_request_error)) &amp;&amp;
					(on_request_successed))
				{
					on_request_successed(server_answer, true);		
				}
			}
		}
		else if (on_request_successed) 
			on_request_successed(response, false);		
	}, on_request_finish, isNotAsync);
}

function CreateURLFromFile(file)
{
	if (file)
		return URL.createObjectURL(file);
	return "";
}

function GetFirstDayOfYear(year, day_number)
{
	var result = new Date(year + "-01-01");
	while (result.getDay() != 1)
		result = IncrementDays(result, 1);
	return result;
}

function IncrementDays(date, days)
{
	var result = new Date(date.valueOf());
	result.setDate(result.getDate() + days);
	return result;
}

async function getImageSize(url)
{
	return new Promise(resolve =&gt; 
	{
		var image = new Image();		
		image.onload = function() 
		{			
			resolve({ 
				width: image.width,
				height: image.height
			});
		};
		image.onerror = function() 
		{						
			resolve({width: 0, height: 0});
		};
		image.src = url;	
	});	
}

/**
 Returns the dimensions of a video asynchrounsly.
 @param {String} url Url of the video to get dimensions from.
 @return {Promise} Promise which returns the dimensions of the video in 'width' and 'height' properties.
 */
async function getVideoMetadataOf(url)
{
	var image_size = await getImageSize(url);				
		
    return new Promise(resolve =&gt; 
	{
		if ((image_size.height &gt; 0) &amp;&amp; 
			(image_size.width &gt; 0))
		{
			resolve({ 
				width: image_size.width,
				height: image_size.height,
				duration: 0
			});
		}
	
        // create the video element
        const video = document.createElement('video');

        // place a listener on it
        video.addEventListener( "loadedmetadata", function () {
            // retrieve dimensions
            var height = this.videoHeight;
            var width = this.videoWidth;			
			if ((height == 0) || (width ==0))
			{
				var image_size = getImageSize(url);				
				width = image_size.width;
				height = image_size.height;
				
			}
			const duration = this.duration;
            // send back result
            resolve({ 
				width: width,
				height: height,
				duration: duration
			});
        }, false );

        // start download meta-datas
        video.src = url;
    });
}

function GetFileSizeInStringFormat(file_size)
{	
	let BYTES_COUNT = 1024;
	if (file_size &gt; BYTES_COUNT) 
	{
		// Receive Free bytes in KB
		let calc_size = (file_size / BYTES_COUNT);
		let prefix = "ÐšÐ‘";
		// If free space in KB &gt; 1024 - receive free spaces in MB
		if (calc_size &gt; BYTES_COUNT) 
		{
		  calc_size = (calc_size / BYTES_COUNT);
		  prefix = 'ÐœÐ‘';
		}
		// If free space in MB &gt; 1024 - receive free spaces in GB
		if (calc_size &gt; BYTES_COUNT) 
		{
		  calc_size = (calc_size / BYTES_COUNT);
		  prefix = 'Ð“Ð‘';
		}
		// If free space in GB &gt; 1024 - receive free spaces in TB
		if (calc_size &gt; BYTES_COUNT) 
		{
		  calc_size = (calc_size / BYTES_COUNT);
		  prefix = 'Ð¢Ð‘';
		}
		return calc_size.toFixed(2) + ' ' + prefix;
	}
	return file_size + ' Ð±Ð°Ð¹Ñ‚';
}

function base64ToDataUri(base64) 
{
    return 'data:image/png;base64,' + base64;
}

function base64ToDataUri(base64) 
{
    return 'data:image/png;base64,' + base64;
}

async function resizeImage(img, width, height) 
{
	return new Promise(resolve =&gt; 
	{
		// create an off-screen canvas
		var canvas = document.createElement('canvas');
		var ctx = canvas.getContext('2d');

		// set its dimension to target size
		canvas.width = width;
		canvas.height = height;

		// draw source image into the off-screen canvas:
		ctx.drawImage(img, 0, 0, width, height);

		// encode image to data-uri with base64 version of compressed image
		resolve(canvas.toDataURL());
	});
}

async function resizeImageSrc(image_src, width, height) 
{	
	return new Promise(resolve =&gt; 
	{
		var image = new Image();		
		image.onload = function() 
		{			
			resolve(resizeImage(this, width, height));
		};
		image.onerror = function() 
		{						
			resolve(null);
		};
		image.src = image_src;	
	});	
}

function getScaledImageSize(original_width, original_height, wanted_width, wanted_height)
{	

	if ((original_width &gt; 0) &amp;&amp;
		(original_height &gt; 0) &amp;&amp;
		((wanted_width &gt; 0) || 
		 (wanted_height &gt; 0)))
	{
		var side_ratio = (original_width / original_height);
		var new_width = wanted_width;
		var new_height = wanted_height;		
		
		// Receive New size of the picture
		if ((side_ratio &lt;= 1) &amp;&amp;
			(wanted_height &gt; 0))
		{
			new_width = Math.trunc(wanted_height * side_ratio);			
			if ((wanted_width &gt; 0) &amp;&amp;
				(new_width &gt; wanted_width)) 
			{
				new_height = new_height - Math.trunc((new_width - wanted_width) / side_ratio);
				new_width = wanted_width;				
			}
		}
		else 
		{
			new_height = Math.trunc(wanted_width / side_ratio);						
			if ((wanted_height &gt; 0) &amp;&amp;
				(new_height &gt; wanted_height)) 
			{				
				new_width =  new_width - Math.trunc((new_height - wanted_height) * side_ratio);
				new_height = wanted_height;        				
			}		  
		}		
		return {'width': new_width, 'height': new_height};
	}
	return {'width': original_width, 'height': original_height};
}

function FormatInteger(integer, digits)
{
	return (integer).toLocaleString('en-US', {minimumIntegerDigits: digits, useGrouping:false})
}

function DecodeEntities(text)
{
	return $('&lt;textarea /&gt;').html(text).text();
}

function RemoveStartEndBrackets(text, startBracket, endBracket)
{		
	if ((text.substr(0, 1) == startBracket) &amp;&amp;
		(text.substr(text.length - 1, 1) == endBracket))
	{
		return text.substr(1, text.length - 2);
	}
	return text;
}

SearchParentElementByNestingElement = function(element, parent_class)
{
	while (Assigned(element))
	{
		if ($(element).hasClass(parent_class))
			return element;
		element = ($(element).parent().length &gt; 0) ? $(element).parent() : null;		
	}
	return null;
}

function DaysBetween(date1, date2)
{
	return Math.round((date2 - date1) / (1000 * 60 * 60 * 24));
}

function WeeksBetween(date1, date2)
{
	return Math.round((date2 - date1) / (1000 * 60 * 60 * 24 * 7));
}

function CheckEnglishOnlyText(text)
{  
	return /^[a-zA-Z0-9\s\.\,\-\\\/]+$/.test(text);
}

function CopyToClipboard(text) 
{
	if (window.clipboardData &amp;&amp; window.clipboardData.setData) {
		// Internet Explorer-specific code path to prevent textarea being shown while dialog is visible.
		return window.clipboardData.setData("Text", text);

	}
	else if (document.queryCommandSupported &amp;&amp; document.queryCommandSupported("copy")) {
		var textarea = document.createElement("textarea");
		textarea.textContent = text;
		textarea.style.position = "fixed";  // Prevent scrolling to bottom of page in Microsoft Edge.
		document.body.appendChild(textarea);
		textarea.select();
		try {
			return document.execCommand("copy");  // Security exception may be thrown by some browsers.
		}
		catch (ex) {
			console.warn("Copy to clipboard failed.", ex);
			return prompt("Copy to clipboard: Ctrl+C, Enter", text);
		}
		finally {
			document.body.removeChild(textarea);
		}
	}
}

function CombineObjectParameters(source, dest)
{
	for (var propertyName in source) 
		dest[propertyName] = source[propertyName];
}

function CloneObject(source)
{
	var result = {};
	for (var propertyName in source) 
	{
		if (typeof(source[propertyName]) === "object")
			result[propertyName] = CloneObject(source[propertyName]);
		else
			result[propertyName] = source[propertyName];
	}
	return result;
}

function SaveFileContentToDrive(fileName, content, contentType, addUTF8Marker)
{	
	addUTF8Marker = (isDefined(addUTF8Marker)) ? addUTF8Marker : true;	
	var markerLength = (addUTF8Marker) ? 3 : 0;	
	byteArray = new Uint8Array(content.length + markerLength);
	for (var i = 0; i &lt; content.length; i++) 
		byteArray[markerLength + i] = content.charCodeAt(i);    
	if (addUTF8Marker)
		byteArray[0] = 0xEF, byteArray[1] = 0xBB, byteArray[2] = 0xBF
	var blobFile = new Blob([byteArray], { type: contentType });
	if (window.navigator &amp;&amp; window.navigator.msSaveOrOpenBlob)
		window.navigator.msSaveOrOpenBlob(blobFile, fileName);
	else 
		DownloadFileByURL(URL.createObjectURL(blobFile));
}

function DownloadFileByURL(url, fileName)
{
	fileName = fileName || "";
	var anchorElement = document.createElement("a");		
	anchorElement.href = url;
	anchorElement.setAttribute("download", fileName),
	document.body.appendChild(anchorElement),
	anchorElement.click(),
	anchorElement.parentNode.removeChild(anchorElement)	
}

function b64DecodeUnicode(str)
 {
    return decodeURIComponent(Array.prototype.map.call(atob(str), function (c) 
	{
        return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2);
    }).join(''));
}

function SelectAndLoadFileContentFromDriveInBase64(callback, allowedExts)
{
	if (callback)
	{
		var fileElement = document.createElement("input");		
		fileElement.type = "file";
		if (allowedExts)
			fileElement.accept = allowedExts;
		document.body.appendChild(fileElement),	
		fileElement.addEventListener('change', (event) =&gt; 
		{
			const fileList = event.target.files;			
			if (fileList.length &gt; 0)
			{
				var fr = new FileReader();	
				fr.addEventListener('load', (event) =&gt; 
				{					
					eventdata = event.target;
					const result_base_64 = event.target.result;									
					const result_decoded = result_base_64.split(',')[1];
					callback(result_decoded);					
				});				
				fr.readAsDataURL(fileList[0]);
			}		
		});
		fileElement.click();
		fileElement.parentNode.removeChild(fileElement)		
	}
}

function GenerateDatedFileName(prefix, suffix)
{
	var result = new Date().toJSON().slice(0, 10)
	result = (prefix) ? prefix + result : result;
	result += (suffix) ? suffix : "";
	return result;	
}

function GenerateDateTimedFileName(prefix, suffix)
{
	var suffixTime = new Date().toJSON();
	suffixTime = suffixTime.slice(11, 19);
	suffixTime = suffixTime.replaceAll(":", "-");
	suffix = suffix || "";
	suffix = " " + suffixTime + suffix;
	return GenerateDatedFileName(prefix, suffix);	
}

function TableToArray(tableID, copyURLToAdditionalColumn, rowSelector, cellSelector) 
{

    // Variable to store the final csv data
    let data = [];
	rowSelector = rowSelector || "tr";
	cellSelector = cellSelector || 'td,th';
    // Get each row data
    let rows = document.getElementById(tableID).querySelectorAll(rowSelector);
    for (let i = 0; i &lt; rows.length; i++) 
	{

        // Get each column data
        let cols = rows[i].querySelectorAll(cellSelector);

        // Stores each csv row data
        let csvrow = [];
        for (let j = 0; j &lt; cols.length; j++) 
		{

            // Get the text data of each cell of
            // a row and push it to csvrow						
			let text = "&lt;div&gt;" + cols[j].innerHTML + "&lt;/div&gt;";			
            csvrow.push($(text).text());
			if (copyURLToAdditionalColumn)
			{
				if (text.indexOf('href="') !== false)
				{
					let url = text.substr(text.indexOf('href="'));
					url = 
					csvrow.push(url);
				}
			}
        }

        // Combine each column value with comma
        data.push(csvrow);
    }
    // Combine each row data with new line character
   return data;
}

function TableToString(tableID, copyURLToAdditionalColumn, rowSelector, cellSelector) 
{	
	let result = ""; 
	let dataArray = TableToArray(tableID, copyURLToAdditionalColumn, rowSelector, cellSelector);
	for (let i = 0; i &lt; dataArray.length; i++) {
		result += dataArray[i].join("\t") + "\n";
	}
	return result;
}

String.prototype.format = function() 
{
  a = this;
  for (k in arguments) {
    a = a.replace("{" + k + "}", arguments[k])
  }
  return a;
}

$(document).ready(function() 
{
	UpdateJQueryAdditionalFunctions();
});

UpdateJQueryAdditionalFunctions();</pre></body></html>