addEventListener("load", function() { movementMenu("basis3"); addEventListener("scroll", del); let view=document.getElementById("view"); // Ссылка на элементы окна просмотра let bas=document.getElementById("bas").style; let pict=document.getElementById("pict"); /* view.addEventListener("click", del); */ function del() // Функция закрытия окна просмотра { if (view) { view.style.visibility="hidden"; } bas.visibility="hidden"; pict.src="../../img/img/net.jpg"; } }); let editableElements; let editMode = -1; let editId = ['pluginDelete', 'titleEdit', 'pluginMove', 'elementEdit', 'editTableButtonAddLine', 'editTableButtonDeleteLine', 'editTableButtonAddColumn', 'editTableButtonDeleteColumn'] ; function basisVis() { editableElementsFun(); let basis3 = document.getElementById('basis3'); let sideFloatClass = basis3 ? basis3.querySelectorAll('[style*="visibility: visible;"]') : null; if (!basis3 || !sideFloatClass || !editableElements || editableElements.length === 0) return; elementsСhecked = [basis3, ...sideFloatClass, ...editableElements]; if (basis3.style.visibility === "hidden") { basis3.style.visibility = "visible"; sessionStorage.setItem('basis3_visibility', 'visible'); editableElements.forEach(function(element) { if (element) { element.setAttribute("contenteditable", true); } }); document.querySelector('#mainTitle').setAttribute('contenteditable', 'true'); basis3.style.left = '10px'; basis3.style.top = '20%'; basis3.style.transform = 'translate(0%, -20%)'; document.getElementById('bcbody').style.top = '30px'; document.querySelectorAll('.bfloat').forEach(e=>e.style.fontSize='1em') } else { basis3.style.visibility = "hidden"; sessionStorage.setItem('basis3_visibility', 'hidden'); editableElements.forEach(function(element) { if (element) { element.setAttribute("contenteditable", false); } }); document.querySelector('#mainTitle').setAttribute('contenteditable', 'false'); sideFloatClass.forEach(function(element) { element.style.visibility = "hidden"; }); for (let i = 0; i < editId.length; i++) { editMode = -1; if (document.getElementById(editId[i])) { document.getElementById(editId[i]).classList.remove('active'); } } document.getElementById('bcbody').style.top = '0px'; document.querySelectorAll('.bfloat').forEach(e=>e.style.fontSize='') } } addEventListener("DOMContentLoaded", function() { let te=document.getElementById("tex"); // Ссылка на текстовое поле let tex=document.getElementById("tex"); // Ссылка на стили текстового поля if (document.getElementById("content") == "") { te.value=document.getElementById("content").innerHTML; // Передача данных из области контента в текстовое поле } // Символы клавиш со знаками препинания или перевода строки let symb = ["Enter", "!", "?", ";", ":", ",", ".", " ", "-", "'", "\"", "(", ")", "{", "}", "[", "]", "_", "&", "/", "\\", "*"]; // Запись в память введенного текста при нажатии клавиши со знаком препинания или перевода строки if (document.getElementById("content")) { document.getElementById("content").addEventListener("keyup", function(ev) { for(let i=0; i { const list = dropdown.querySelector('.align-list'); dropdown.addEventListener('click', e => { if (e.target.closest('.align-list')) { const cmd = e.target.closest('li').dataset.cmd; handleImageAction(cmd); list.style.display = 'none'; return; } list.style.display = list.style.display === 'block' ? 'none' : 'block'; }); document.addEventListener('click', e => { if (!dropdown.contains(e.target)) { list.style.display = 'none'; } }); }); function handleImageAction(id) { var sel = window.getSelection(); if (sel.rangeCount) { var node = sel.anchorNode.nodeType === 1 ? sel.anchorNode : sel.anchorNode.parentElement; if (!node.closest('[contenteditable="true"]')) { return; } } switch (id) { case "imgLink": messageQueue.push("Enter image URL") ;(async () => { const url = await messageCreateInput() if (url) { const img = document.createElement("img") img.src = url img.style.cssText = "float: left; margin: 10px; width: 250px; border: 0; overflow: hidden;" insertNodeAtSelection(img) } })() break case "imgPc": var input = document.createElement("input"); input.type = "file"; input.accept = "image/*"; input.style.display = "none"; document.body.appendChild(input); input.addEventListener("change", function() { if (input.files.length > 0) { var formData = new FormData(); formData.append('userImg', input.files[0]); formData.append('handleRequestAction', 'uploadUserImage'); handleJsonRpcRequest('uploadUserImage', formData, 1) .then(result => { if (result.error) { messageFunction("{{img_upload_error}}"); } else { var img = document.createElement("img"); img.src = result; img.style.cssText = "float: left; margin: 10px; width: 250px; border: 0; overflow: hidden;"; insertNodeAtSelection(img); } }) .catch(() => { messageFunction("{{img_upload_error}}"); }); } document.body.removeChild(input); }); input.click(); break; case "imgManager": window.managerDataAction = "selectImgForm"; createAjaxRequest({ handleRequestAction: 'nameUser' }, function(response) { managerData("/img/users_img/" + response.user); managerDiv.style.visibility = "visible"; document.getElementById("settingsMain_d").style.visibility = "hidden"; }); break; } } function insertHR() { const hr = document.createElement("hr") hr.style.cssText = "height: 5px; width: 50%; background: rgb(0, 0, 0); border: 0;" insertNodeAtSelection(hr) } document.getElementById("hr").addEventListener("click", insertHR) function insertTable() { const table = document.createElement("table") table.style.cssText = "width: 50%; margin: 1px; float: left; border: 1px solid rgb(0, 0, 0); background-color: rgb(255, 255, 255); border-collapse: collapse;" for (let i = 0; i < 4; i++) { const tr = document.createElement("tr") for (let j = 0; j < 4; j++) { const td = document.createElement("td") td.style.cssText = "padding: 1px; border: 1px solid rgb(0, 0, 0);" tr.appendChild(td) } table.appendChild(tr) } insertNodeAtSelection(table) } document.getElementById("tabl").addEventListener("click", insertTable) function insertNodeAtSelection(node) { var sel = window.getSelection(); if (!sel.rangeCount) return; var range = sel.getRangeAt(0); range.deleteContents(); range.insertNode(node); } /*let t=document.querySelectorAll(".cldiv"); for(let i=0; i { option.style.backgroundColor = '#efefef'; }); if (activeOption) { pluginDropdownContentId.style.backgroundColor = '#d8d8d8'; } else { pluginDropdownContentId.style.backgroundColor = ''; } if (editMode == -1) { pluginDropdownContentId.style.backgroundColor = ''; } }); // действия блока элементов /* let elementDropdownContentId = document.getElementById("elementDropdownContent"); elementDropdownContentId.addEventListener('click', function () { let targetElement = document.getElementById(this.value); if (targetElement) { targetElement.click(); } else { console.log("{{action_not_defined}}2"); } }); */ // действия блока главных действий /* let mainActionsId = document.getElementById("mainActions"); mainActionsId.addEventListener('click', function () { switch (this.value) { case "save": saveChanges(); break; case "saveHow": saveChangesHow(); break; case "htm": showHtmlCode(); break; default: console.log("{{action_not_defined}}"); } }); */ document.getElementById("save").addEventListener("click", saveChanges); // Загрузка изменений как document.getElementById("saveHow").addEventListener("click", saveChangesHow); function saveChangesHow() { window.managerDataAction = "saveHow"; managerData("/content"); managerDiv.style.visibility = "visible"; document.getElementById("settingsMain_d").style.visibility="hidden"; } // Открытие страницы document.getElementById("openPage").addEventListener("click", openPageFun); function openPageFun() { window.managerDataAction = "openPage"; managerData("/content"); managerDiv.style.visibility = "visible"; document.getElementById("settingsMain_d").style.visibility="hidden"; } // Создание новой страницы document.getElementById("newPage").addEventListener("click", newPageFun); function newPageFun() { document.getElementById("right-float").innerHTML = ""; document.getElementById("left-float").innerHTML = ""; document.getElementById("content").innerHTML = ""; document.getElementById("mainTitle").innerHTML = "{{new_file}}!"; window.newPageFunValue = "newPage"; document.getElementById("settingsMain_d").style.visibility="hidden"; } // Сбор новых элементов function editableElementsFun() { let content = document.getElementById('content'); editableElements = document.querySelectorAll('.pluginEditable'); editableElements = Array.from(editableElements); editableElements.push(content); editableElements.forEach(function(element) { if (!element) { console.log("Element " + element + " not found."); return; } }); } window.editableElementsFun = editableElementsFun; // Сохранение выделение document.addEventListener('selectionchange', () => { const content = document.getElementById('content'); const sel = window.getSelection(); if (!sel.rangeCount) return; const range = sel.getRangeAt(0); const startNode = range.startContainer; if (content.contains(startNode)) { saveSelection(); } }); let savedSel = null; function saveSelection() { const content = document.getElementById('content'); const sel = window.getSelection(); if (!sel.rangeCount) return; const range = sel.getRangeAt(0); if (!content.contains(range.commonAncestorContainer)) return; const pre = range.cloneRange(); pre.selectNodeContents(content); pre.setEnd(range.startContainer, range.startOffset); const start = pre.toString().length; const end = start + range.toString().length; savedSel = { start, end }; } function restoreSelection() { if (!savedSel) return; const content = document.getElementById('content'); const { start, end } = savedSel; let charIndex = 0; const range = document.createRange(); range.setStart(content, 0); range.collapse(true); try { (function traverse(node) { if (node.nodeType === Node.TEXT_NODE) { const next = charIndex + node.length; if (charIndex <= start && next >= start) { range.setStart(node, start - charIndex); } if (charIndex <= end && next >= end) { range.setEnd(node, end - charIndex); throw 'done'; } charIndex = next; } else { node.childNodes.forEach(traverse); } })(content); } catch (e) {} const sel = window.getSelection(); sel.removeAllRanges(); sel.addRange(range); } // Взаимодействие с плагинами /* document.getElementById('pluginCreateLeft').onclick = function() { pluginFun('create', 'left'); }; document.getElementById('pluginCreateRight').onclick = function() { pluginFun('create', 'right'); }; */ document.getElementById('pluginAddLeft').onclick = function() { pluginFun('add', 'left'); }; document.getElementById('pluginAddRight').onclick = function() { pluginFun('add', 'right'); }; function pluginFun(action, side) { let data = `action=${encodeURIComponent(action)}&side=${encodeURIComponent(side)}&pluginName=`; if (action === 'add') { let xhr = createXHR(function () { let plugins = xhr.responseText.trim().split("\n"); let pluginAddSideName = document.getElementById('pluginAdd' + (side === 'left' ? 'Left' : 'Right') + 'Name'); pluginAddSideName.innerHTML = ''; plugins.forEach(plugin => { let option = document.createElement('option'); option.value = plugin; option.textContent = plugin; pluginAddSideName.appendChild(option); }); }); xhr.send(data+'&handleRequestAction=managerPlugin'); } } /* document.getElementById('pluginRulesButton1').onclick = function() { pluginRulesFun('pluginRulesBlock1'); }; document.getElementById('pluginRulesButton2').onclick = function() { pluginRulesFun('pluginRulesBlock2'); }; */ function pluginRulesFun(id) { let element = document.getElementById(id); if (element.classList.contains('show')) { element.classList.remove('show'); } else { element.classList.add('show'); let data = `action=${encodeURIComponent("add")}&side=$&pluginName=`; let xhr = createXHR(function () { let plugins = xhr.responseText.trim().split("\n"); element.innerHTML = `
{{plugin_name_guidelines}}

{{used_plugin_names}}
`; plugins.forEach(plugin => { let div = document.createElement('div'); div.innerHTML = plugin; element.appendChild(div); }); }); xhr.send(data+'&action=funcEditor'); } } document.getElementById('pluginCreateLeftFun_d').onclick = function() { pluginFun_d('pluginCreateLeftName', 'left-float', 'pluginCreateLeftTitle', ' {{plugin_created_left_suffix}}', 'create', 'pluginCreateLeft_d'); }; document.getElementById('pluginAddLeftFun_d').onclick = function() { pluginFun_d('pluginAddLeftName', 'left-float', 'pluginAddLeftTitle', ' {{plugin_added_left_suffix}}', 'add', 'pluginAddLeft_d'); }; document.getElementById('pluginCreateRightFun_d').onclick = function() { pluginFun_d('pluginCreateRightName', 'right-float', 'pluginCreateRightTitle', ' {{plugin_created_right_suffix}}', 'create', 'pluginCreateRight_d'); }; document.getElementById('pluginAddRightFun_d').onclick = function() { pluginFun_d('pluginAddRightName', 'right-float', 'pluginAddRightTitle', ' {{plugin_added_right_suffix}}', 'add', 'pluginAddRight_d'); }; function pluginFun_d(inputIdName, side_float, inputIdTitle, pluginText, action, pluginAddSide_d) { let pluginName = document.getElementById(inputIdName).value.trim(); let pluginTitle = document.getElementById(inputIdTitle).value.trim(); if (pluginName === "") { messageFunction(action === 'create' ? "{{plugin_name_empty_error}}" : "{{plugin_not_selected_error}}"); return; } let allowedCharacters = /^[a-zA-Z0-9 _]*$/; if (!allowedCharacters.test(pluginName)) { messageFunction("{{plugin_name_guidelines}}"); return; } /* if (pluginTitle === "") { messageFunction("{{plugin_title_empty_error}}"); return; } */ if (action === 'create') { let checkData = `action=check&pluginName=${encodeURIComponent(pluginName)}`; let checkXHR = createXHR(function () { if (checkXHR.responseText.trim() === "exists") { messageFunction(pluginName + "{{plugin_name_exists_suffix}}"); } else { sendRequest('create', side_float, pluginName, pluginTitle, pluginText); } }); checkXHR.send(checkData+'&handleRequestAction=managerPlugin'); } else { pluginHtml('add', pluginName, side_float, pluginTitle); inter(); } document.getElementById(pluginAddSide_d).style.visibility = "hidden"; } function sendRequest(action, side_float, pluginName, pluginTitle, pluginText) { let xhr = createXHR(function () { if (xhr.responseText.trim() === "Plugin created: " + pluginName) { pluginHtml('create', pluginName, side_float, pluginTitle); inter(); } }); let data = `action=${encodeURIComponent(action)}&side=${encodeURIComponent(side_float)}&pluginName=${encodeURIComponent(pluginName)}`; xhr.send(data+'&handleRequestAction=managerPlugin'); } function pluginHtml(action, pluginName, side_float, pluginTitle) { let sideFloat = document.getElementById(side_float); let sideFloatElement = sideFloat; let pluginUrl = document.createElement("div"); pluginUrl.classList.add('plugin-url'); pluginUrl.pluginUrl = '/plugin/' + pluginName + '/'; let br = document.createElement("br"); let tclass = null; if (pluginTitle != "") { tclass = document.createElement("div"); tclass.setAttribute("tclass", 'tclass'); tclass.setAttribute("plugin-title", 'pluginTitle'); tclass.className = 'btitle'; tclass.textContent = pluginTitle; } let bclass = document.createElement("div"); bclass.setAttribute("bclass", 'bclass'); bclass.className = 'bfloat'; let bcont = document.createElement("div"); bcont.className = 'bcont'; sideFloatElement.appendChild(pluginUrl); if (tclass) { pluginUrl.appendChild(tclass); } pluginUrl.appendChild(bclass); pluginUrl.appendChild(br); bclass.appendChild(bcont); if (action === 'add') { let xhr = createXHR(function () { let pluginContent = xhr.responseText; bcont.innerHTML = pluginContent; }); let data = `pluginName2=${encodeURIComponent(pluginName)}`; xhr.send(data+'&handleRequestAction=loadPlugin'); } else { let pluginEditable = document.createElement("div"); pluginEditable.className = 'pluginEditable'; pluginEditable.contentEditable = 'true'; bcont.appendChild(pluginEditable); } } for (let i = 0; i < editId.length; i++) { if (document.getElementById(editId[i])) { document.getElementById(editId[i]).onclick = function() { editFun(editId[i]); }; } } function editFun(whichEditId) { for (let i = 0; i < editId.length; i++) { if (whichEditId === editId[i]) { if (editMode != i) { editFun1_1(i); } else { editFun1_2(i); } } else { editFun3(i); } if (i == 3 && editMode != 3) { editFun4(i); } if (editMode != 0 && editMode != 2 && editMode != 3) { editFun5(i); } } } function editFun1_1(i) { editMode = i; document.getElementById(editId[i]).classList.add('active'); } function editFun1_2(i) { editMode = -1; document.getElementById(editId[i]).classList.remove('active'); } /* function editFun2_1(i) { let pluginElements = document.querySelectorAll('[plugin-url]'); for (let i = 0; i < pluginElements.length; i++) { let pluginTitleElement = pluginElements[i].querySelector('[plugin-title]'); if (pluginTitleElement) { let pluginUrl = pluginElements[i].getAttribute('plugin-url'); let newDiv = document.createElement('div'); newDiv.className = 'pluginTitleUrl'; newDiv.textContent = pluginUrl; pluginTitleElement.insertAdjacentElement('afterbegin', newDiv); } } } */ function editFun3(i) { /* document.getElementById(editId[i]).classList.remove('active'); */ } function editFun4(i) { } function editFun5(i) { pluginDropdownContentId.style.backgroundColor = ''; } let pluginTakeCheck = 0; let targetElement; document.onclick = function(event) { if (editMode === 0) { let target = event.target; let pluginElement = target.closest('.plugin-url'); if (pluginElement) { if (confirm("{{delete_plugin_confirm}}")) { pluginElement.remove(); /* let floatElements = [document.querySelector('.right-float'), document.querySelector('.left-float')]; floatElements.forEach(element => { if (element && element.children.length === 0 && element.textContent.trim() === "") { element.remove(); } }); */ inter(); } } } if (editMode === 1) { let target = event.target; let pluginTitle = target.closest('[plugin-title]'); let mainTitle = target.closest('#mainTitle'); let secondDiv = pluginTitle ? pluginTitle.closest('div').parentElement.closest('div') : null; let thirdDiv = secondDiv ? secondDiv.parentElement.closest('div') : null; let allDivsInParent = secondDiv ? Array.from(secondDiv.parentElement.children).filter(child => child.tagName === 'DIV') : []; let indexOfSecondDiv = secondDiv ? allDivsInParent.indexOf(secondDiv) : null; let classOfThirdDiv = thirdDiv ? thirdDiv.className.replace(/-float/g, '') : null; if (pluginTitle || mainTitle) { let editTitle = mainTitle ? mainTitle : pluginTitle; let whichTitle = mainTitle ? "mainTitle" : "pluginTitle"; console.log(whichTitle+" "+functionOpenPage); if (whichTitle === "mainTitle" && functionOpenPage === true) { messageFunction("{{open_page}}"); } else { let title = prompt("{{enter_new_title}}", editTitle.textContent.trim()); if (title !== null) { let newTitle = title.trim(); if (newTitle !== "") { let xhr = createXHR(function () { let responseText = xhr.responseText; console.log(responseText); editTitle.innerHTML = newTitle; messageFunction("{{title_saved}}"); inter(); }); let data = `newTitle=${encodeURIComponent(newTitle)}&whichTitle=${encodeURIComponent(whichTitle)} &side=${encodeURIComponent(classOfThirdDiv)}&pluginNumber=${encodeURIComponent(indexOfSecondDiv)}`; xhr.send(data+'&handleRequestAction=newTitle'); } else { messageFunction("{{plugin_title_empty_error}}"); } } } } } if (editMode === 2 && pluginTakeCheck == 0) { let pluginElement = event.target.closest('.plugin-url'); if (pluginElement) { pluginElement.style.border = '3px dashed #000000'; pluginElement.classList.add('pluginElementl'); let indicator = document.createElement("div"); indicator.style.width = '20px'; indicator.style.height = '20px'; indicator.style.position = 'absolute'; indicator.style.left = (event.clientX - 10) + 'px'; indicator.style.top = (event.clientY - 10) + 'px'; indicator.style.backgroundImage = "url(../../img/pict/b_iconslyb.svg)"; indicator.style.backgroundPosition = "0px -80px"; indicator.style.pointerEvents = "none"; document.body.appendChild(indicator); function pointerMove(event) { indicator.style.left = (event.clientX - 10) + 'px'; indicator.style.top = (event.clientY - 10) + 'px'; let dropTarget = document.elementFromPoint(event.clientX, event.clientY); let leftFloatElement = document.getElementById('left-float'); let rightFloatElement = document.getElementById('right-float'); let isLeftFloat = leftFloatElement ? leftFloatElement.contains(dropTarget) : false; let isRightFloat = rightFloatElement ? rightFloatElement.contains(dropTarget) : false; if (isLeftFloat || isRightFloat) { let targetCheck = document.elementFromPoint(event.clientX, event.clientY).closest('.plugin-url'); let floatElement = isLeftFloat ? leftFloatElement : rightFloatElement; if (pluginElement !== targetCheck) { pluginTakeCheck = 1; } pluginElement.classList.remove('pluginElementl'); if (targetCheck) { let side = getTargetSide(targetCheck, event.clientY); if (side === 0) { if (targetCheck.parentNode === floatElement) { floatElement.insertBefore(pluginElement, targetCheck.nextSibling); } else { floatElement.appendChild(pluginElement); } indicator.style.backgroundPosition = "-40px -80px"; } else if (side === 1) { if (targetCheck.parentNode === floatElement) { floatElement.insertBefore(pluginElement, targetCheck); } else { floatElement.appendChild(pluginElement); } indicator.style.backgroundPosition = "0px -80px"; } } else { floatElement.appendChild(pluginElement); } /* let floatElements = [document.querySelector('.right-float'), document.querySelector('.left-float')]; floatElements.forEach(element => { if (element && element.children.length === 0 && element.textContent.trim() === "") { element.remove(); } }); */ } } document.addEventListener('pointermove', pointerMove); document.addEventListener('pointerup', function pointerup() { document.removeEventListener('pointermove', pointerMove); document.removeEventListener('pointerup', pointerup); pluginElement.style.border = ''; pluginElement.style.padding = ''; indicator.remove(); inter(); }); } } pluginTakeCheck = 0; if (editMode === 3) { } let table = event.target.closest('table'); if (table) { let rowIndex, cellIndex; let targetRow = event.target.closest('tr'); let targetCell = event.target.closest('td'); if (targetRow) { rowIndex = Array.from(targetRow.parentNode.children).indexOf(targetRow); } if (targetCell) { cellIndex = Array.from(targetCell.parentNode.children).indexOf(targetCell); } if (editMode === 4 && targetRow) { let row = table.insertRow(rowIndex + 1); let cellCount = targetRow.cells.length; for (let i = 0; i < cellCount; i++) { let newCell = row.insertCell(i); if (targetRow.cells.length > 0) { let referenceCell = targetRow.cells[i]; newCell.style.cssText = referenceCell.style.cssText; } } } if (editMode === 5 && targetRow) { if (table.rows.length > 1) { table.deleteRow(rowIndex); } } if (editMode === 6 && targetCell) { for (let i = 0; i < table.rows.length; i++) { let row = table.rows[i]; let newCell = row.insertCell(cellIndex + 1); if (row.cells.length > cellIndex) { let referenceCell = row.cells[cellIndex]; newCell.style.cssText = referenceCell.style.cssText; } } } if (editMode === 7 && targetCell) { if (targetCell.parentNode.cells.length > 1) { for (let i = 0; i < table.rows.length; i++) { let row = table.rows[i]; if (row.cells.length > cellIndex) { row.deleteCell(cellIndex); } } } } inter(); } }; function getTargetSide(targetCheck, mouseY) { if (targetCheck) { let targetRect = targetCheck.getBoundingClientRect(); let targetY = targetRect.top + targetRect.height / 2; return mouseY < targetY ? 1 : 0; } else { return -1; } } /* выделение элементов */ let clipboard = ['', ''] let selectedElement = null let selectedElementOriginalOutline = '' let selectedElementCut = '' document.addEventListener('contextmenu',editingElements) function editingElements(event) { var editable = event.target.closest('[contenteditable="true"]') if (!editable) return event.preventDefault() var menu = document.getElementById('editingMenuItems') var copy = document.getElementById('editingMenuItemsCopy') var cut = document.getElementById('editingMenuItemsCut') var paste = document.getElementById('editingMenuItemsPaste') copy.style.display = 'none' cut.style.display = 'none' paste.style.display = 'none' var element = event.target.closest('hr, img, table') if (editable && element) { if (selectedElement && selectedElement !== element) { selectedElement.style.outline = selectedElementOriginalOutline } selectedElementOriginalOutline = element.style.outline || '' element.style.outline = '1px dashed black' selectedElement = element menu.style.visibility = 'visible' copy.style.display = '' cut.style.display = '' if (clipboard[0]) paste.style.display = '' } else if (editable && clipboard[0]) { if (selectedElement) { selectedElement.style.outline = selectedElementOriginalOutline selectedElement = null } menu.style.visibility = 'visible' paste.style.display = '' } else { if (selectedElement) { selectedElement.style.outline = selectedElementOriginalOutline selectedElement = null } menu.style.visibility = 'hidden' } targetElement = null if (element) { targetElement = element var sel = window.getSelection() var range = document.createRange() range.selectNode(targetElement) sel.removeAllRanges() sel.addRange(range) } document.querySelectorAll('.elementEditPanelElement').forEach(function(panel) { panel.style.display = 'none' document.getElementById('editingMenuItemsHr').style.display = 'none' }) if (targetElement !== null && event.target.closest('[contenteditable="true"]')) { editElement() } const pad=10 const menuRect=menu.getBoundingClientRect() let x=(event.clientX!==undefined?event.clientX:touchX) let y=(event.clientY!==undefined?event.clientY:touchY) let left=Math.min(x,window.innerWidth-menuRect.width-pad) let top=Math.min(y,window.innerHeight-menuRect.height-pad) if (!isPhone) { menu.style.left = `${Math.max(pad, left)}px` menu.style.top = `${Math.max(pad, top)}px` } else { menu.style.top = '30%' menu.style.left = '0' menu.style.right = '0' menu.style.marginLeft = 'auto' menu.style.marginRight = 'auto' menu.style.width = 'calc(100% - 20px)' menu.style.maxWidth = 'max-content' } } function editElement() { var panelMap = { 'HR': 'elementEditPanelHr', 'IMG': 'elementEditPanelImg', 'TABLE': 'elementEditPanelTable' } var panelId = panelMap[targetElement.tagName] if (panelId) { var panel = document.getElementById(panelId) if (panel) { panel.style.display = '' document.getElementById('editingMenuItemsHr').style.display = '' } } if (panelId === 'elementEditPanelHr') { document.getElementById('hr1Edit').value = parseInt(targetElement.style.height, 10) || 1 document.getElementById('hr2Edit').value = targetElement.style.width || '95%' document.getElementById('hr3cEdit').value = targetElement.style.backgroundColor ? rgbToHex(targetElement.style.backgroundColor) : '#000000' document.getElementById('hrMarginTopEdit').value = parseInt(targetElement.style.marginTop, 10) || 0 document.getElementById('hrMarginRightEdit').value = parseInt(targetElement.style.marginRight, 10) || 0 document.getElementById('hrMarginBottomEdit').value = parseInt(targetElement.style.marginBottom, 10) || 0 document.getElementById('hrMarginLeftEdit').value = parseInt(targetElement.style.marginLeft, 10) || 0 var m = targetElement.style.margin if (m === '0.5em auto 0.5em 0px') { document.getElementById('hr4Edit').value = 'left_clear' } else if (m === '0.5em 0px 0.5em auto') { document.getElementById('hr4Edit').value = 'right_clear' } else if (targetElement.style.display === 'inline-block' && targetElement.style.verticalAlign === 'middle') { document.getElementById('hr4Edit').value = 'left_text' } else { document.getElementById('hr4Edit').value = 'center_clear' } } if (panelId === 'elementEditPanelImg') { document.getElementById('ima1Edit').value = targetElement.src || '' document.getElementById('ima6Edit').value = parseInt(targetElement.style.width, 10) || 250 document.getElementById('ima6aEdit').value = parseInt(targetElement.style.height, 10) || '' document.getElementById('ima7Edit').value = parseInt(targetElement.style.borderWidth, 10) || 0 document.getElementById('ima8cEdit').value = targetElement.style.borderColor ? rgbToHex(targetElement.style.borderColor) : '#000000' document.getElementById('imaMarginTopEdit').value = parseInt(targetElement.style.marginTop, 10) || 0 document.getElementById('imaMarginRightEdit').value = parseInt(targetElement.style.marginRight, 10) || 0 document.getElementById('imaMarginBottomEdit').value = parseInt(targetElement.style.marginBottom, 10) || 0 document.getElementById('imaMarginLeftEdit').value = parseInt(targetElement.style.marginLeft, 10) || 0 document.getElementById('ima4Edit').value = targetElement.style.float ? (targetElement.style.float === 'left' ? 'left_clear' : 'right_clear') : 'center_clear' var link = targetElement.closest('a') document.getElementById('imaLinkEdit').value = link ? link.href : '' var captionEl = targetElement.nextElementSibling } if (panelId === 'elementEditPanelTable') { document.getElementById('tab1Edit').value = targetElement.style.width || '50%' document.getElementById('tabMarginTopEdit').value = parseInt(targetElement.style.marginTop, 10) || 0 document.getElementById('tabMarginRightEdit').value = parseInt(targetElement.style.marginRight, 10) || 0 document.getElementById('tabMarginBottomEdit').value = parseInt(targetElement.style.marginBottom, 10) || 0 document.getElementById('tabMarginLeftEdit').value = parseInt(targetElement.style.marginLeft, 10) || 0 document.getElementById('tab9Edit').value = parseInt(targetElement.style.borderWidth, 10) || 1 document.getElementById('tab11cEdit').value = targetElement.style.backgroundColor ? rgbToHex(targetElement.style.backgroundColor) : '#000000' var firstCell = targetElement.querySelector('td') document.getElementById('tab4Edit').value = firstCell ? parseInt(firstCell.style.padding, 10) || 1 : 1 document.getElementById('tab10cEdit').value = firstCell ? rgbToHex(firstCell.style.borderColor) : '#000000' document.getElementById('tab6Edit').value = targetElement.style.float ? (targetElement.style.float === 'left' ? 'left_clear' : 'right_clear') : 'center_clear' } } /* меню изменение элемнтов */ document.addEventListener('pointerdown', clearMenu) document.addEventListener('keydown', clearMenu) function clearMenu(event) { if (event.type === 'pointerdown' && event.button !== 0) { return; } if (event.target.closest('#editingMenuItems')) { return; } var menu = document.getElementById("editingMenuItems"); if (selectedElement) { selectedElement.style.outline = selectedElementOriginalOutline; selectedElement = null; } menu.style.visibility = "hidden"; } document.getElementById("editingMenuItemsCopy").addEventListener('click', function() { if (selectedElement) { clipboard = [selectedElement.cloneNode(true), 'copy']; } }); document.getElementById("editingMenuItemsCut").addEventListener('click', function() { if (selectedElement) { clipboard = [selectedElement.cloneNode(true), 'cut']; selectedElementCut = selectedElement; } }); document.getElementById("editingMenuItemsPaste").addEventListener('click', function() { if (clipboard && clipboard[0]) { var sel = window.getSelection(); if (!sel.rangeCount) return; var range = sel.getRangeAt(0); range.collapse(false); range.insertNode(clipboard[0]); if (clipboard[1] == 'cut' && selectedElementCut) { selectedElementCut.remove(); selectedElementCut = null; } clipboard[0] = clipboard[0].cloneNode(true); document.getElementById("editingMenuItems").style.visibility = "hidden"; } }); //редактирования меню страниц /* document.getElementById("contentPageCreateFun_d").addEventListener("click", function() { inter(); }); document.getElementById("contentPageMove").addEventListener("click", function() { inter(); }); document.getElementById("contentPageSettingsFun_d").addEventListener("click", function() { inter(); }); */ // панель редактирования для элементов document.getElementById("buthrEdit").addEventListener("click", function() { let hr1_v = document.getElementById("hr1Edit").value let hr2_v = document.getElementById("hr2Edit").value let hr3_v = document.getElementById("hr3cEdit").value let hr4_v = document.getElementById("hr4Edit").value let mt = document.getElementById("hrMarginTopEdit").value let mr = document.getElementById("hrMarginRightEdit").value let mb = document.getElementById("hrMarginBottomEdit").value let ml = document.getElementById("hrMarginLeftEdit").value let style = "" style += "height: " + (hr1_v || 1) + "px; " if (hr2_v) style += "width: " + hr2_v + "; " style += "background: " + hr3_v + "; " style += "margin: " + (mt||0) + "px " + (mr||0) + "px " + (mb||0) + "px " + (ml||0) + "px; " switch (hr4_v) { case "left_clear": style += "margin-left: 0; "; break case "right_clear": style += "margin-right: 0; "; break case "center_clear": style += "position: relative; left: 50%; transform: translateX(-50%); "; break case "left_text": style += "display: inline-block; vertical-align: middle; float: left; "; break case "right_text": style += "display: inline-block; vertical-align: middle; float: right; "; break case "text": style += "display: inline-block; vertical-align: middle; "; break } style += "border: 0;" change(targetElement, style, "") inter() }) document.getElementById("butimaEdit").addEventListener("click", function() { let url = document.getElementById("ima1Edit").value let pos = document.getElementById("ima4Edit").value let mt = document.getElementById("imaMarginTopEdit").value let mr = document.getElementById("imaMarginRightEdit").value let mb = document.getElementById("imaMarginBottomEdit").value let ml = document.getElementById("imaMarginLeftEdit").value let w = document.getElementById("ima6Edit").value let h = document.getElementById("ima6aEdit").value let bw = document.getElementById("ima7Edit").value let bc = document.getElementById("ima8cEdit").value let link = document.getElementById("imaLinkEdit").value if (!url) { messageFunction("{{insert_url}}") return } let style = "" if (pos === "left_clear") style += "float: left; " if (pos === "right_clear") style += "float: right; " if (pos === "center_clear") style += "position: relative; left: 50%; transform: translateX(-50%); margin-top: " + (mt||0) + "px; display: block; " if (pos === "left_text") style += "float: left; display: inline-block; vertical-align: middle; " if (pos === "right_text") style += "float: right; display: inline-block; vertical-align: middle; " if (pos === "text") style += "vertical-align: middle; display: inline-block; " if (pos !== "center_clear") style += "margin: " + (mt||0) + "px " + (mr||0) + "px " + (mb||0) + "px " + (ml||0) + "px; " if (w) style += "width: " + w + "px; " if (h) style += "height: " + h + "px; " if (bw) style += "border: " + bw + "px solid " + bc + "; " change(targetElement, style, url) if (link) { let a = document.createElement("a") a.href = link targetElement.parentNode.insertBefore(a, targetElement) a.appendChild(targetElement) } inter() }) document.getElementById("butabEdit").addEventListener("click", function() { let width_v = document.getElementById("tab1Edit").value let mt = document.getElementById("tabMarginTopEdit").value let mr = document.getElementById("tabMarginRightEdit").value let mb = document.getElementById("tabMarginBottomEdit").value let ml = document.getElementById("tabMarginLeftEdit").value let pad_i_v = document.getElementById("tab4Edit").value let float_v = document.getElementById("tab6Edit").value let border_v = document.getElementById("tab9Edit").value let bc_v = document.getElementById("tab10cEdit").value let bg_v = document.getElementById("tab11cEdit").value let style = "" if (width_v) style += "width: " + width_v + "; " if (float_v === "left_clear") style += "float: left; " if (float_v === "right_clear") style += "float: right; " if (float_v === "center_clear") style += "position: relative; left: 50%; transform: translateX(-50%); " if (float_v === "left_text") style += "float: left; display: inline-table; vertical-align: middle; " if (float_v === "right_text") style += "float: right; display: inline-table; vertical-align: middle; " if (float_v === "text") style += "display: inline-table; vertical-align: middle; " if (float_v !== "center_clear") style += "margin: " + (mt||0) + "px " + (mr||0) + "px " + (mb||0) + "px " + (ml||0) + "px; " if (border_v) style += "border: " + border_v + "px solid " + bc_v + "; " if (bg_v) style += "background-color: " + bg_v + "; " style += "border-collapse: collapse;" change(targetElement, style, "") let cells = targetElement.querySelectorAll("td") cells.forEach(function(cell) { let cellStyle = "" if (pad_i_v) cellStyle += "padding: " + pad_i_v + "px; " if (border_v) cellStyle += "border: " + border_v + "px solid " + bc_v + "; " cell.style.cssText = cellStyle }) inter() }) function change(element, style, src) { if (element) { if (style) element.style.cssText = style if (src) element.src = src } } function rgbToHex(rgb) { let rgbArray = rgb.match(/\d+/g); return "#" + rgbArray.map(x => { let hex = parseInt(x).toString(16); return hex.length === 1 ? "0" + hex : hex; }).join(''); } const visibility = sessionStorage.getItem('basis3_visibility'); if (visibility === "visible" && document.getElementById("siteSettingsButton")) { basisVis(); } }); //addEventListener("load", function()' addEventListener("load", function() { document.querySelectorAll('.swit').forEach(btn => { btn.addEventListener('click', () => { const target = document.getElementById(btn.id + '_d'); if (!target) return; target.style.display = (getComputedStyle(target).display === 'none') ? '' : 'none'; }); }); const container = document.querySelector('.toolbar-container'); const panel = document.getElementById('panel'); const arrowLeft = document.getElementById('arrow-left'); const arrowRight = document.getElementById('arrow-right'); let interval; let offset = 0; function getBounds() { const containerWidth = container.scrollWidth; const panelWidth = panel.clientWidth; const arrowWidth = arrowLeft.clientWidth; const extra = arrowWidth; const maxOffset = 24; const minOffset = panelWidth - containerWidth - extra; return { containerWidth, panelWidth, maxOffset, minOffset }; } function updateArrowsVisibility() { const { containerWidth, panelWidth, minOffset, maxOffset } = getBounds(); if (containerWidth <= panelWidth) { arrowLeft.style.display = 'none'; arrowRight.style.display = 'none'; panel.style.overflowX = 'visible'; offset = 0; container.style.transform = 'translateX(0px)'; } else { arrowLeft.style.display = 'inline-flex'; arrowRight.style.display = 'inline-flex'; panel.style.overflowX = 'clip'; if (offset > maxOffset) offset = maxOffset; if (offset < minOffset) offset = minOffset; } } const events = ['resize', 'scroll', 'pointerdown', 'pointerup', 'pointermove', 'keydown', 'touchstart']; events.forEach(evt => { window.addEventListener(evt, updateArrowsVisibility, { passive: true }); document.addEventListener(evt, updateArrowsVisibility, { passive: true }); }); if (window.visualViewport) { window.visualViewport.addEventListener('resize', updateArrowsVisibility); } updateArrowsVisibility(); function startScroll(direction) { const { maxOffset, minOffset } = getBounds(); interval = setInterval(() => { if (direction === 'left') { offset += 10; } else { offset -= 10; } if (offset > maxOffset) offset = maxOffset; if (offset < minOffset) offset = minOffset; container.style.transform = `translateX(${offset}px)`; }, 16); } function stopScroll() { clearInterval(interval); } arrowLeft.addEventListener('pointerdown', e => { if (e.pointerType === 'touch') e.preventDefault(); startScroll('left'); }); arrowLeft.addEventListener('pointerup', stopScroll); arrowLeft.addEventListener('pointerleave', stopScroll); arrowLeft.addEventListener('pointercancel', stopScroll); arrowLeft.addEventListener('contextmenu', e => { if (e.pointerType === 'touch') e.preventDefault(); }); arrowRight.addEventListener('pointerdown', e => { if (e.pointerType === 'touch') e.preventDefault(); startScroll('right'); }); arrowRight.addEventListener('pointerup', stopScroll); arrowRight.addEventListener('pointerleave', stopScroll); arrowRight.addEventListener('pointercancel', stopScroll); arrowRight.addEventListener('contextmenu', e => { if (e.pointerType === 'touch') e.preventDefault(); }); }); /* добовление функций */ const simpleFormats = [ { id: 'bol', style: { fontWeight: 'bold' }, prop: 'font-weight', test: v => (parseInt(v) >= 700 || v === 'bold') }, { id: 'ital', style: { fontStyle: 'italic' }, prop: 'font-style', test: v => v === 'italic' }, { id: 'under', style: { textDecorationLine: 'underline' },prop: 'text-decoration-line', test: v => v.split(' ').includes('underline') }, { id: 'strik', style: { textDecorationLine: 'line-through' },prop: 'text-decoration-line', test: v => v.split(' ').includes('line-through') }, { id: 'sup', style: { verticalAlign: 'super' }, prop: 'vertical-align', test: v => v === 'super' }, { id: 'sub', style: { verticalAlign: 'sub' }, prop: 'vertical-align', test: v => v === 'sub' } ]; const divFormats = [ { id: 'equal', style: { textAlign: 'left' } }, { id: 'equac', style: { textAlign: 'center' } }, { id: 'equar', style: { textAlign: 'right' } }, { id: 'equaj', style: { textAlign: 'justify'} } ]; const listFormats = [ { id: 'listNone', style: { listStyleType: 'none' } }, { id: 'listDots', style: { listStyleType: 'disc' } }, { id: 'listNumbers', style: { listStyleType: 'decimal' } }, { id: 'listLetters', style: { listStyleType: 'lower-alpha'} } ]; const singleFormats = [ { id: 'ff', prop: 'font-family'}, { id: 'fs', prop: 'font-size'} ]; const specialFormats = ['butlink', 'linkdel', 'forma', 'col', 'backgr']; addEventListener("load", function() { const content = document.getElementById('content'); simpleFormats.forEach(f => { document.getElementById(f.id).addEventListener('click', () => { const sel = window.getSelection(); if (!sel.rangeCount) return; const range = sel.getRangeAt(0); if (!content.contains(range.commonAncestorContainer)) return; let all = true; const it = document.createNodeIterator( range.commonAncestorContainer, NodeFilter.SHOW_ALL, { acceptNode: n => range.intersectsNode(n) ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_REJECT } ); let n; while (n = it.nextNode()) { if (n.nodeType === Node.TEXT_NODE && n.textContent.trim()) { let cur = n.parentElement, ok = false; while (cur) { const v = getComputedStyle(cur)[f.prop] || ''; if (f.test(v)) { ok = true; break; } cur = cur.parentElement; } if (!ok) { all = false; break; } } } all ? simpleUnformat(range, f) : simpleApplyformat(range, f); sel.removeAllRanges(); sel.addRange(range); inter(); }); }); divFormats.forEach(f => { document.getElementById(f.id).addEventListener('click', () => { const sel = window.getSelection(); if (!sel.rangeCount) return; const range = sel.getRangeAt(0); if (!content.contains(range.commonAncestorContainer)) return; divApplyformat(range, f); inter(); }); }); listFormats.forEach(f => { document.getElementById(f.id).addEventListener('click', () => { const sel = window.getSelection(); if (!sel.rangeCount) return; const range = sel.getRangeAt(0); if (!content.contains(range.commonAncestorContainer)) return; listApplyformat(range, f); inter(); }); }); singleFormats.forEach(f => { const el = document.getElementById(f.id) el.addEventListener('click', e => { const list = el.querySelector('.align-list') if (!list || getComputedStyle(list).display === 'none') return const cmdEl = e.target.closest('[data-cmd]') if (!cmdEl) return f.value = cmdEl.dataset.cmd const sel = window.getSelection() if (!sel.rangeCount) return const range = sel.getRangeAt(0) if (!content.contains(range.commonAncestorContainer)) return singleApplyformat(range, f) inter() }) }) specialFormats.forEach(f => { document.getElementById(f).addEventListener('click', () => { const sel = window.getSelection(); if (!sel.rangeCount) return; const range = sel.getRangeAt(0); if (!content.contains(range.commonAncestorContainer)) return; window[f + 'Fun'](range); inter(); }); }); const events = ['pointerup','keyup','input','focus','blur','click']; events.forEach(evt => { if (!content) return; content.addEventListener(evt, () => { updateToolbarStyles(); updateSingleSelectors(); }); }); }); /////////////////// Начало блока, выполняющего навигацию по внесенным изменениям ==================== let arr = [] let currentIndex = 0 function inter() { const editable = document.getElementById("content") if (editable) { let currentContent = editable.innerHTML if (currentContent !== arr[currentIndex]) { currentIndex++ arr = arr.slice(0, currentIndex) arr.push(currentContent) } } } if (document.getElementById("content")) { arr[0] = document.getElementById("content").innerHTML } document.getElementById("forw").addEventListener("click", function() { if (currentIndex < arr.length - 1) { currentIndex++ const editable = document.getElementById("content") editable.innerHTML = arr[currentIndex] editable.setAttribute("contenteditable", "true") } }) document.getElementById("bac").addEventListener("click", function() { if (currentIndex > 0) { currentIndex-- const editable = document.getElementById("content") editable.innerHTML = arr[currentIndex] editable.setAttribute("contenteditable", "true") } }) /////////////////// Конец блока, выполняющего навигацию по внесенным изменениям ==================== /* общие функции */ function applyformat(range, createElement) { const arr = [], it = document.createNodeIterator( range.commonAncestorContainer, NodeFilter.SHOW_TEXT, n => range.intersectsNode(n) ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_REJECT ); let n; while (n = it.nextNode()) arr.push(n); let firstEl, lastEl; arr.forEach((tn, i) => { const p = tn.parentNode; const start = tn === range.startContainer ? range.startOffset : 0; const end = tn === range.endContainer ? range.endOffset : tn.textContent.length; let newEl; if (tn === range.startContainer && tn === range.endContainer) { const b = tn.splitText(start), m = b.splitText(end - start); newEl = createElement(); newEl.textContent = b.textContent; p.replaceChild(newEl, b); p.insertBefore(m, newEl.nextSibling); } else if (tn === range.startContainer) { const aNode = tn.splitText(start); newEl = createElement(); newEl.textContent = aNode.textContent; p.replaceChild(newEl, aNode); } else if (tn === range.endContainer) { const b = tn.splitText(end); newEl = createElement(); newEl.textContent = tn.textContent; p.replaceChild(newEl, tn); p.insertBefore(b, newEl.nextSibling); } else { newEl = createElement(); newEl.textContent = tn.textContent; p.replaceChild(newEl, tn); } if (i === 0) firstEl = newEl; if (i === arr.length - 1) lastEl = newEl; }); if (firstEl && lastEl) { range.setStartBefore(firstEl); range.setEndAfter(lastEl); } mergeTextNodes(range.commonAncestorContainer); } /* simpleFormats */ function simpleApplyformat(range, format) { const span = document.createElement('span'); Object.assign(span.style, format.style); applyformat(range, () => span.cloneNode()); } function simpleUnformat(range, format) { const { prop, test } = format; const spans = new Set(); const it = document.createNodeIterator( range.commonAncestorContainer, NodeFilter.SHOW_TEXT, n => { if (!range.intersectsNode(n)) return NodeFilter.FILTER_REJECT; let node = n.parentNode; while (node && node !== range.commonAncestorContainer) { if (node.tagName === 'SPAN' && test(node.style.getPropertyValue(prop) || '')) { return NodeFilter.FILTER_ACCEPT; } node = node.parentNode; } return NodeFilter.FILTER_REJECT; } ); let tn; while (tn = it.nextNode()) { let node = tn.parentNode; while (node && node !== range.commonAncestorContainer) { if (node.tagName === 'SPAN' && test(node.style.getPropertyValue(prop) || '')) { if (range.intersectsNode(node)) { spans.add(node); } } node = node.parentNode; } } spans.forEach(span => { const full = span.textContent; let total = 0, startAbs = 0, endAbs = full.length; const walker = document.createTreeWalker(span, NodeFilter.SHOW_TEXT, null); let t; while (walker.nextNode()) { t = walker.currentNode; if (t === range.startContainer) startAbs = total + range.startOffset; if (t === range.endContainer) endAbs = total + range.endOffset; total += t.textContent.length; } if (startAbs >= endAbs) return; const bef = full.slice(0, startAbs); const sel = full.slice(startAbs, endAbs); const aft = full.slice(endAbs); const p = span.parentNode; if (!p) return; function cloneWithText(node, text) { const clone = node.cloneNode(false); for (let child of node.childNodes) { if (text.length === 0) break; if (child.nodeType === Node.TEXT_NODE) { const len = child.textContent.length; const take = text.slice(0, len); clone.appendChild(document.createTextNode(take)); text = text.slice(len); } else { const sub = child.textContent; const taken = text.slice(0, sub.length); clone.appendChild(cloneWithText(child, taken)); text = text.slice(sub.length); } } return clone; } if (bef) p.insertBefore(cloneWithText(span, bef), span); if (sel) { const unwrapped = document.createDocumentFragment(); const mid = cloneWithText(span, sel); while (mid.firstChild) unwrapped.appendChild(mid.firstChild); p.insertBefore(unwrapped, span); } if (aft) p.insertBefore(cloneWithText(span, aft), span); span.remove(); }); } function mergeTextNodes(node) { let c = node.firstChild; while (c) { let nx = c.nextSibling; if (c.nodeType === Node.TEXT_NODE) { while (nx && nx.nodeType === Node.TEXT_NODE) { c.textContent += nx.textContent; const next = nx.nextSibling; if (nx.parentNode) nx.parentNode.removeChild(nx); nx = next; } } else if (c.nodeType === Node.ELEMENT_NODE) { mergeTextNodes(c); } c = nx; } } /* divFormats */ function divApplyformat(range, format) { const style = format.style; if (!style || !style.textAlign) return; const externals = new Set(); const intersects = element => { const er = document.createRange(); er.selectNodeContents(element); return range.compareBoundaryPoints(Range.END_TO_START, er) < 0 && range.compareBoundaryPoints(Range.START_TO_END, er) > 0; }; Array.from(content.children).forEach(child => { if (intersects(child)) externals.add(child); }); externals.forEach(div => { div.style.textAlign = style.textAlign; }); } /* listApplyformat */ function listApplyformat(range, format) { const intersects = el => { const er = document.createRange(); er.selectNodeContents(el); return range.compareBoundaryPoints(Range.END_TO_START, er) < 0 && range.compareBoundaryPoints(Range.START_TO_END, er) > 0; }; const type = format.id; if (type === 'listNone') { const lists = new Set(); Array.from(content.querySelectorAll('li')).forEach(li => { if (intersects(li)) lists.add(li.parentNode); }); lists.forEach(list => { const parent = list.parentNode; const lis = Array.from(list.children); const selected = lis.filter(li => intersects(li)); if (!selected.length) return; const firstIdx = lis.indexOf(selected[0]); const lastIdx = lis.indexOf(selected[selected.length - 1]); const before = lis.slice(0, firstIdx); const after = lis.slice(lastIdx + 1); if (before.length) { const ul1 = list.cloneNode(false); before.forEach(li => ul1.appendChild(li)); parent.insertBefore(ul1, list); } selected.forEach(li => { const wrapper = li.firstElementChild && li.firstElementChild.cloneNode(true) || document.createElement('div'); if (!li.firstElementChild) { while (li.firstChild) wrapper.appendChild(li.firstChild); } parent.insertBefore(wrapper, list); }); if (after.length) { const ul2 = list.cloneNode(false); after.forEach(li => ul2.appendChild(li)); parent.insertBefore(ul2, list); } parent.removeChild(list); }); } else { const items = Array.from(content.children).filter(child => intersects(child)); if (!items.length) return; let listEl; if (type === 'listNumbers' || type === 'listLetters') { listEl = document.createElement('ol'); listEl.style.listStyleType = format.style.listStyleType; } else { listEl = document.createElement('ul'); listEl.style.listStyleType = format.style.listStyleType; } content.insertBefore(listEl, items[0]); items.forEach(node => { if (node.tagName === 'UL' || node.tagName === 'OL') { Array.from(node.children).forEach(li => { listEl.appendChild(li); }); content.removeChild(node); } else { const li = document.createElement('li'); content.removeChild(node); li.appendChild(node); listEl.appendChild(li); } }); } } /* singleFormats */ function singleApplyformat(range, f) { const val = f.value; if (!val) return; applyformat(range, () => { const span = document.createElement('span'); span.style[f.prop] = val; return span; }); } /* specialFormats */ function butlinkFun(range) { const url = document.getElementById('link2').value; const targetBlank = document.getElementById('link3').value === 'yes'; const underline = document.getElementById('link5').value === 'yes'; const color = document.getElementById('link6c').value; applyformat(range, () => { const a = document.createElement('a'); a.href = url; if (targetBlank) a.target = '_blank'; if (underline) a.style.textDecoration = 'underline'; if (color) a.style.color = color; return a; }); inter(); } function linkdelFun(range) { const frag = range.extractContents(); const cleaned = unwrapAllLinks(frag); range.insertNode(cleaned); function unwrapAllLinks(node) { const frag = document.createDocumentFragment(); Array.from(node.childNodes).forEach(ch => { if (ch.nodeType === Node.ELEMENT_NODE && ch.tagName === 'A') { frag.appendChild(unwrapAllLinks(ch)); } else if (ch.nodeType === Node.ELEMENT_NODE) { const copy = ch.cloneNode(false); copy.appendChild(unwrapAllLinks(ch)); frag.appendChild(copy); } else { frag.appendChild(ch.cloneNode(true)); } }); return frag; } } function formaFun(range) { const frag = range.extractContents(); const cleaned = unwrapAllSpansAndLinks(frag); range.insertNode(cleaned); const externals = new Set(); const intersects = element => { const er = document.createRange(); er.selectNodeContents(element); return range.compareBoundaryPoints(Range.END_TO_START, er) < 0 && range.compareBoundaryPoints(Range.START_TO_END, er) > 0; }; Array.from(content.children).forEach(child => { if (intersects(child)) externals.add(child); }); externals.forEach(el => { el.style.textAlign = ''; }); const itList = document.createNodeIterator( content, NodeFilter.SHOW_ELEMENT, { acceptNode: n => (n.tagName === 'UL' || n.tagName === 'OL') && range.intersectsNode(n) ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_REJECT } ); let listEl; while (listEl = itList.nextNode()) { const parent = listEl.parentNode; Array.from(listEl.children).forEach(li => { while (li.firstChild) parent.insertBefore(li.firstChild, listEl); }); parent.removeChild(listEl); } function unwrapAllSpansAndLinks(node) { const frag = document.createDocumentFragment(); Array.from(node.childNodes).forEach(ch => { if ( ch.nodeType === Node.ELEMENT_NODE && (ch.tagName === 'SPAN' || ch.tagName === 'A') ) { frag.appendChild(unwrapAllSpansAndLinks(ch)); } else if (ch.nodeType === Node.ELEMENT_NODE) { const copy = ch.cloneNode(false); copy.appendChild(unwrapAllSpansAndLinks(ch)); frag.appendChild(copy); } else { frag.appendChild(ch.cloneNode(true)); } }); return frag; } } let currentFormat = null; let currentRange = null; function colFun(range) { currentFormat = { prop: 'color', test: v => !!v }; currentRange = range; const app = document.querySelector('.pcr-app'); app.style.marginLeft = '-61px'; app.style.left = ''; app.classList.remove('hide'); } function backgrFun(range) { currentFormat = { prop: 'background-color', test: v => !!v }; currentRange = range; const app = document.querySelector('.pcr-app'); app.style.marginLeft = '-29px'; app.style.left = ''; 1, app.classList.remove('hide'); } function setColorFun() { const input = document.querySelector('.pcr-result'); const val = input.value; if (!currentRange || !currentFormat) return; if (!val) { simpleUnformat(currentRange, currentFormat); } else { applyformat(currentRange, () => { const span = document.createElement('span'); span.style[currentFormat.prop] = val; return span; }); } const app = document.querySelector('.pcr-app'); app.classList.add('hide'); } document.addEventListener('DOMContentLoaded', () => { document.addEventListener('pointerdown', e => { if (!e.target.closest('.pcr-app') && !e.target.closest('#col') && !e.target.closest('#backgr')) { setColorFun(); } }); }); /* определение стилей */ const toolbarButtons = ['bol','ital','under','strik','sup','sub']; const bgColors = { none: 'rgb(255 255 255)', partial: 'rgb(231 231 231)', full: 'rgb(203 203 203)' }; function detectFormatState(format) { const sel = window.getSelection(); if (!sel.rangeCount) return 'none'; const range = sel.getRangeAt(0); if (!content.contains(range.commonAncestorContainer)) return 'none'; const it = document.createNodeIterator( range.commonAncestorContainer, NodeFilter.SHOW_TEXT, { acceptNode: n => range.intersectsNode(n) ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_REJECT } ); let node, total = 0, styled = 0; while (node = it.nextNode()) { const text = node.textContent.trim(); if (!text) continue; total++; let cur = node.parentElement, ok = false; while (cur && cur !== content) { const fmt = simpleFormats.find(f => f.id === format); const v = fmt ? getComputedStyle(cur)[fmt.prop] || '' : ''; if (fmt && fmt.test(v)) { ok = true; break; } cur = cur.parentElement; } if (ok) styled++; } if (total === 0) return 'none'; if (styled === 0) return 'none'; if (styled === total) return 'full'; return 'partial'; } function updateToolbarStyles() { toolbarButtons.forEach(id => { const btn = document.getElementById(id); const state = detectFormatState(id); btn.style.backgroundColor = bgColors[state]; }); } const singleSelectors = ['ff','fs']; function detectSingleState(format) { const sel = window.getSelection(); if (!sel.rangeCount) return ''; const range = sel.getRangeAt(0); if (!content.contains(range.commonAncestorContainer)) return ''; const it = document.createNodeIterator( range.commonAncestorContainer, NodeFilter.SHOW_TEXT, { acceptNode: n => range.intersectsNode(n) ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_REJECT } ); let node, values = [], uniform = true; while (node = it.nextNode()) { const text = node.textContent.trim(); if (!text) continue; const cur = node.parentElement; const fmt = singleFormats.find(f => f.id === format); const v = getComputedStyle(cur)[fmt.prop] || ''; values.push(v); } if (values.length === 0) return ''; const first = values[0]; for (let i = 1; i < values.length; i++) { if (values[i] !== first) { uniform = false; break; } } return uniform ? values[0] : ''; } function updateSingleSelectors() { singleSelectors.forEach(id => { const dropdown = document.getElementById(id); const current = dropdown.querySelector('.current'); const list = dropdown.querySelectorAll('li'); let value = detectSingleState(id); if (!value) return; let cmd = id === 'ff' ? value.replace(/["']/g, '') : value; if (id === 'fs') { const num = parseFloat(cmd); const unit = (cmd.match(/[a-z%]+$/) || [''])[0]; cmd = num.toFixed(1) + unit; } let found = Array.from(list).some(li => li.dataset.cmd === cmd); if (!found && id === 'ff') { const li = document.createElement('li'); li.dataset.cmd = cmd; const div = document.createElement('div'); div.textContent = cmd.split(',')[0].trim(); li.appendChild(div); dropdown.querySelector('.align-list').appendChild(li); } current.textContent = id === 'ff' ? cmd.split(',')[0].trim() : cmd; current.dataset.cmd = cmd; }); } addEventListener("load", function() { document.querySelectorAll("#panel .toolbar-group").forEach(g => { const btn = g.querySelector(".toolbar-group-button"); const content = g.querySelector(".toolbar-group-content"); if (btn && content) { btn.addEventListener("click", () => { const isHidden = content.style.display === "none"; content.style.display = isHidden ? "" : "none"; if (btn && content) { const isHidden = content.style.display === "none"; g.classList.toggle("open", !isHidden); } }); if (btn && content) { const isHidden = content.style.display === "none"; g.classList.toggle("open", !isHidden); } } }); document.querySelectorAll('.swit').forEach(btn => { btn.addEventListener('click', () => { const target = document.getElementById(btn.id + '_d'); if (!target) return; target.style.display = (getComputedStyle(target).display === 'none') ? '' : 'none'; }); }); document.querySelectorAll('.align-dropdown').forEach(dropdown => { const current = dropdown.querySelector('.current'); const list = dropdown.querySelector('.align-list'); current.addEventListener('click', () => { list.style.display = list.style.display === 'block' ? 'none' : 'block'; if (list.style.display === 'none' && current.dataset.cmd) { const cmd = current.dataset.cmd; const iconEl = document.getElementById(cmd); if (iconEl) iconEl.click(); } }); document.addEventListener('click', e => { if (!dropdown.contains(e.target)) list.style.display = 'none'; }); list.querySelectorAll('li').forEach(li => { li.addEventListener('click', () => { const icon = li.firstElementChild; const cmd = icon.id; current.dataset.cmd = cmd; current.removeAttribute('style'); current.className = 'current editi editib pers'; current.classList.add(cmd); list.style.display = 'none'; }); }); }); document.querySelectorAll('.align-dropdown-text').forEach(dropdown => { const current = dropdown.querySelector('.current') const list = dropdown.querySelector('.align-list') dropdown.addEventListener('click', e => { if (e.target.closest('.align-list')) return list.style.display = list.style.display === 'block' ? 'none' : 'block' }) document.addEventListener('click', e => { if (!dropdown.contains(e.target)) list.style.display = 'none' }) list.querySelectorAll('li').forEach(li => { li.addEventListener('click', () => { const cmd = li.dataset.cmd current.innerHTML = li.querySelector('img')?.outerHTML || li.textContent current.dataset.cmd = cmd list.style.display = 'none' const f = singleFormats.find(ff => ff.id === dropdown.id) f.value = cmd const sel = window.getSelection() if (sel.rangeCount) { const range = sel.getRangeAt(0) if (content.contains(range.commonAncestorContainer)) { singleApplyformat(range, f) inter() } } }) }) }) });