2024-11-17 13:03:49 +03:00
|
|
|
function escapeHtml(text) {
|
|
|
|
var map = {
|
|
|
|
'&': '&',
|
|
|
|
'<': '<',
|
|
|
|
'>': '>',
|
|
|
|
'"': '"',
|
|
|
|
"'": '''
|
|
|
|
};
|
|
|
|
|
|
|
|
return text.replace(/[&<>"']/g, function(m) { return map[m]; });
|
|
|
|
}
|
|
|
|
|
|
|
|
function highlightText(searchText, container_selector, selectors = []) {
|
|
|
|
const container = u(container_selector)
|
|
|
|
const regexp = new RegExp(`(${searchText})`, 'gi')
|
|
|
|
|
|
|
|
function highlightNode(node) {
|
|
|
|
if(node.nodeType == 3) {
|
|
|
|
let newNode = escapeHtml(node.nodeValue)
|
|
|
|
newNode = newNode.replace(regexp, (match, ...args) => {
|
|
|
|
return `<span class='highlight'>${escapeHtml(match)}</span>`
|
|
|
|
})
|
|
|
|
|
|
|
|
const tempDiv = document.createElement('div')
|
|
|
|
tempDiv.innerHTML = newNode
|
|
|
|
|
|
|
|
while(tempDiv.firstChild) {
|
|
|
|
node.parentNode.insertBefore(tempDiv.firstChild, node)
|
|
|
|
}
|
|
|
|
node.parentNode.removeChild(node)
|
|
|
|
} else if(node.nodeType === 1 && node.tagName !== 'SCRIPT' && node.tagName !== 'BR' && node.tagName !== 'STYLE' && !node.classList.contains('highlight')) {
|
|
|
|
Array.from(node.childNodes).forEach(highlightNode);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
selectors.forEach(selector => {
|
|
|
|
elements = container.find(selector)
|
|
|
|
if(!elements || elements.length < 1) return;
|
|
|
|
|
|
|
|
elements.nodes.forEach(highlightNode)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
String.prototype.escapeHtml = function() {
|
|
|
|
try {
|
|
|
|
return escapeHtml(this)
|
|
|
|
} catch(e) {
|
|
|
|
return ''
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function fmtTime(time) {
|
|
|
|
const mins = String(Math.floor(time / 60)).padStart(2, '0');
|
|
|
|
const secs = String(Math.floor(time % 60)).padStart(2, '0');
|
|
|
|
return `${ mins}:${ secs}`;
|
|
|
|
}
|
|
|
|
|
|
|
|
function fastError(message) {
|
|
|
|
MessageBox(tr("error"), message, [tr("ok")], [Function.noop])
|
|
|
|
}
|
|
|
|
|
|
|
|
function humanFileSize(bytes, si) {
|
|
|
|
var thresh = si ? 1000 : 1024;
|
|
|
|
if(Math.abs(bytes) < thresh) {
|
|
|
|
return bytes + ' B';
|
|
|
|
}
|
|
|
|
var units = si
|
|
|
|
? ['kB','MB','GB','TB','PB','EB','ZB','YB']
|
|
|
|
: ['KiB','MiB','GiB','TiB','PiB','EiB','ZiB','YiB'];
|
|
|
|
var u = -1;
|
|
|
|
do {
|
|
|
|
bytes /= thresh;
|
|
|
|
++u;
|
|
|
|
} while(Math.abs(bytes) >= thresh && u < units.length - 1);
|
|
|
|
return bytes.toFixed(1)+' '+units[u];
|
|
|
|
}
|
|
|
|
|
|
|
|
function trim(string) {
|
|
|
|
var newStr = string.substring(0, 10);
|
|
|
|
if(newStr.length !== string.length)
|
|
|
|
newStr += "…";
|
|
|
|
|
|
|
|
return newStr;
|
|
|
|
}
|
|
|
|
|
|
|
|
function trimNum(string, num) {
|
|
|
|
return ovk_proc_strtr(string, num);
|
|
|
|
}
|
|
|
|
|
|
|
|
function ovk_proc_strtr(string, length = 0) {
|
|
|
|
const newString = string.substring(0, length);
|
|
|
|
return newString + (string !== newString ? "…" : "");
|
|
|
|
}
|
|
|
|
|
|
|
|
function chunkSubstr(string, size) {
|
|
|
|
const numChunks = Math.ceil(string.length / size);
|
|
|
|
const chunks = new Array(numChunks);
|
|
|
|
|
|
|
|
for (let i = 0, o = 0; i < numChunks; ++i, o += size) {
|
|
|
|
chunks[i] = string.substr(o, size);
|
|
|
|
}
|
|
|
|
|
|
|
|
return chunks;
|
|
|
|
}
|
|
|
|
|
|
|
|
function random_int(min, max) {
|
|
|
|
return Math.round(Math.random() * (max - min) + min)
|
|
|
|
}
|
|
|
|
|
|
|
|
function makeError(text, color = 'Red', timeout = 10000, uid = 0) {
|
|
|
|
const rand_id = uid != 0 ? uid : random_int(0, 10000)
|
|
|
|
|
|
|
|
if(uid != 0 && u(`.upLeftErrors .upLeftError[data-id='${uid}']`).length > 0) {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
u('.upLeftErrors').append(`
|
|
|
|
<div class='upLeftError upLeftError${color}' data-id='${rand_id}'>${escapeHtml(text)}</div>
|
|
|
|
`)
|
|
|
|
|
|
|
|
setTimeout(() => {
|
|
|
|
u(`.upLeftError[data-id='${rand_id}']`).remove()
|
|
|
|
}, timeout)
|
|
|
|
}
|
|
|
|
|
|
|
|
function array_splice(array, key)
|
|
|
|
{
|
|
|
|
let resultArray = [];
|
|
|
|
|
|
|
|
for(let i = 0; i < array.length; i++){
|
|
|
|
if(i != key){
|
|
|
|
resultArray.push(array[i]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return resultArray;
|
|
|
|
}
|
|
|
|
|
|
|
|
function strip_tags(text)
|
|
|
|
{
|
|
|
|
return text.replace(/(<([^>]+)>)/gi, "")
|
|
|
|
}
|
|
|
|
|
|
|
|
function find_author(id, profiles, groups)
|
|
|
|
{
|
|
|
|
if(id > 0) {
|
|
|
|
const profile = profiles.find(prof => prof.id == id)
|
|
|
|
if(profile) {
|
|
|
|
return profile
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
const group = groups.find(grou => grou.id == Math.abs(id))
|
|
|
|
if(group) {
|
|
|
|
return group
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return null
|
|
|
|
}
|
|
|
|
|
|
|
|
function collect_attachments(target) {
|
|
|
|
const horizontal_array = []
|
|
|
|
const horizontal_attachments = target.find(`.post-horizontal > a`)
|
|
|
|
horizontal_attachments.nodes.forEach(_node => {
|
|
|
|
horizontal_array.push(`${_node.dataset.type}${_node.dataset.id}`)
|
|
|
|
})
|
|
|
|
|
|
|
|
const vertical_array = []
|
|
|
|
const vertical_attachments = target.find(`.post-vertical > .vertical-attachment`)
|
|
|
|
vertical_attachments.nodes.forEach(_node => {
|
|
|
|
vertical_array.push(`${_node.dataset.type}${_node.dataset.id}`)
|
|
|
|
})
|
|
|
|
|
|
|
|
return horizontal_array.concat(vertical_array)
|
|
|
|
}
|
2024-11-27 23:27:15 +03:00
|
|
|
|
|
|
|
function getRemainingTime(fullTime, time) {
|
|
|
|
let timer = fullTime - time
|
|
|
|
|
|
|
|
if(timer < 0) return "-00:00"
|
|
|
|
|
|
|
|
return "-" + fmtTime(timer)
|
|
|
|
}
|
2024-11-28 17:43:40 +03:00
|
|
|
|
2024-12-01 18:12:50 +03:00
|
|
|
function serializeForm(form, submitter = null)
|
2024-11-28 17:43:40 +03:00
|
|
|
{
|
|
|
|
const u_ = u(form)
|
2024-12-01 21:53:15 +03:00
|
|
|
const inputs = u_.find('input, textarea, button, select')
|
2024-11-28 17:43:40 +03:00
|
|
|
let fd = new FormData()
|
|
|
|
inputs.nodes.forEach(inp => {
|
|
|
|
if(!inp || !inp.name) {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
if(inp.type == 'submit') {
|
2024-12-01 18:12:50 +03:00
|
|
|
if(inp !== submitter) {
|
|
|
|
return
|
|
|
|
}
|
2024-11-28 17:43:40 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
switch(inp.type) {
|
|
|
|
case 'hidden':
|
|
|
|
case 'text':
|
|
|
|
case 'textarea':
|
2024-11-28 23:15:50 +03:00
|
|
|
case 'select':
|
2024-12-01 21:53:15 +03:00
|
|
|
case 'select-one':
|
2024-12-01 18:12:50 +03:00
|
|
|
case 'submit':
|
2024-12-01 21:53:15 +03:00
|
|
|
case 'email':
|
|
|
|
case 'phone':
|
|
|
|
case 'search':
|
|
|
|
case 'password':
|
|
|
|
case 'date':
|
|
|
|
case 'datetime-local':
|
2024-11-28 17:43:40 +03:00
|
|
|
fd.append(inp.name, inp.value)
|
2024-11-28 23:15:50 +03:00
|
|
|
break
|
|
|
|
case 'checkbox':
|
|
|
|
if(inp.checked) {
|
|
|
|
fd.append(inp.name, inp.value)
|
|
|
|
}
|
|
|
|
|
2024-11-28 17:43:40 +03:00
|
|
|
break
|
|
|
|
case 'file':
|
2024-12-01 18:12:50 +03:00
|
|
|
if(!inp.multiple) {
|
|
|
|
if(inp.files[0]) {
|
|
|
|
fd.append(inp.name, inp.files[0])
|
|
|
|
} else {
|
|
|
|
const emptyFile = new Blob([], { type: 'application/octet-stream' })
|
|
|
|
fd.append(inp.name, emptyFile, '')
|
|
|
|
}
|
2024-11-28 17:43:40 +03:00
|
|
|
}
|
|
|
|
break
|
|
|
|
}
|
|
|
|
})
|
|
|
|
|
|
|
|
return fd
|
|
|
|
}
|
2024-11-30 15:35:43 +03:00
|
|
|
|
|
|
|
async function copyToClipboard(text) {
|
|
|
|
let fallback = () => {
|
|
|
|
prompt(text);
|
|
|
|
}
|
|
|
|
|
|
|
|
if(typeof navigator.clipboard == "undefined") {
|
|
|
|
fallback()
|
|
|
|
} else {
|
|
|
|
try {
|
|
|
|
await navigator.clipboard.writeText(text)
|
|
|
|
} catch(e) {
|
|
|
|
fallback()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2024-11-30 19:41:08 +03:00
|
|
|
|
|
|
|
function remove_file_format(text)
|
|
|
|
{
|
|
|
|
return text.replace(/\.[^.]*$/, '')
|
|
|
|
}
|
|
|
|
|
|
|
|
function sleep(time)
|
|
|
|
{
|
|
|
|
return new Promise((resolve) => setTimeout(resolve, time));
|
|
|
|
}
|