UNPKG

aditorx

Version:

Aditor is a fast, flexible, and fully customizable rich text editor for modern web applications. It provides a smooth writing experience with built-in formatting tools, keyboard shortcuts, and an intuitive UI. Perfect for developers who need a lightweight

1,420 lines (1,236 loc) 53.8 kB
import "./aditorx.css"; export function initializeAditorX(inputSection, defaultValue) { if (defaultValue == "") { inputSection.innerHTML = ` <div class="aditor"> <div class="line"> <div class="Head"> <label class="textLabel"></label> <div class="content"> <ul class="inputContent" contenteditable="true"></ul> </div> <div class="actionsOff"> <button class="expand"> <i class="fa-solid fa-caret-down"></i> </button> </div> </div> <div class="sub-line-off"> <div class="sub-Head"> <label class="pointLabel"> <input type="checkbox"><span class="points"><i class="fa-solid fa-square"></i></span></label> <div class="sub-content"> <ul class="inputSubContent" contenteditable="true"></ul> </div> </div> </div></div> </div> <div class="dropdownMenu" > <div class="icon headingBtn" tabindex="0"> <span><i class="fa-solid fa-heading"></i></span> </div> <div class="icon textBtn active" tabindex="0"> <span><i class="fa-solid fa-paragraph"></i></span> </div> <div class="icon pointBtn" tabindex="0"> <span><i class="fa-solid fa-list"></i></span> </div> <div class="icon checkboxBtn" tabindex="0"> <span><i class="fa-solid fa-square-check"></i></span> </div> <div class="icon indentBtn" tabindex="0"> <span><i class="fa-solid fa-indent"></i></span> </div> </div>`; } else { inputSection.innerHTML = defaultValue; } const aditor = inputSection.querySelector(".aditor"); const headingBtn = inputSection.querySelector(".headingBtn"); const textBtn = inputSection.querySelector(".textBtn"); const pointBtn = inputSection.querySelector(".pointBtn"); const checkboxBtn = inputSection.querySelector(".checkboxBtn"); const indentBtn = inputSection.querySelector(".indentBtn"); let current_Label = "textLabel"; let current_EditableText = ""; let subLineActive = false; let subAditorActive = false; let current_Editable = null; let current_subEditable = null; if (current_Editable == null) { current_Editable = inputSection.querySelector(".inputContent"); } let current_Line = null; let next_Line = null; let previous_Line = null; let current_subLine = null; let previous_subLine = null; let current_subHead = null; let next_subHead = null; let previous_subHead = null; function updateElement() { current_Line = current_Editable.closest(".line"); next_Line = current_Line.nextElementSibling; previous_Line = current_Line.previousElementSibling; while (next_Line && next_Line.classList.contains("collapsed")) { next_Line = next_Line.nextElementSibling; } while (previous_Line && previous_Line.classList.contains("collapsed")) { previous_Line = previous_Line.previousElementSibling; } current_subLine = current_Line.querySelector(".sub-line"); if (current_subEditable != null) { current_subHead = current_subEditable.closest(".sub-Head"); next_subHead = current_subHead.nextElementSibling; previous_subHead = current_subHead.previousElementSibling; } if (previous_Line != null) { previous_subLine = previous_Line.querySelector(".sub-line"); } } let selection = false; function emptyAditor() { current_Label = "textLabel"; subLineActive = false; subAditorActive = false; activeOption(); aditor.innerHTML = ` <div class="line"> <div class="Head"> <label class="textLabel"></label> <div class="content"> <ul class="inputContent" contenteditable="true"></ul> </div> <div class="actionsOff"> <button class="expand"> <i class="fa-solid fa-caret-down"></i> </button> </div> </div> <div class="sub-line-off"> <div class="sub-Head"> <label class="pointLabel"> <input type="checkbox"><span class="points"><i class="fa-solid fa-square"></i></span></label> <div class="sub-content"> <ul class="inputSubContent" contenteditable="true"></ul> </div> </div> </div> </div> </div>`; activeOption(); selection = false; subAditorActive = false; current_Editable = aditor.querySelector(".inputContent"); current_Editable.focus(); window.getSelection().selectAllChildren(current_Editable); window.getSelection().collapseToEnd(); updateElement(); } let text = ""; function updateSelectedText() { const selection = window.getSelection(); if (selection.rangeCount > 0) { const selectedText = selection.toString(); text = selectedText; } } aditor.addEventListener("keydown", (e) => { // if (e.key == "/") { // e.preventDefault(); // // options.classList.toggle("inactive"); // dropdownMenu.classList.toggle("active"); // currentFocus = currentLabelActive(); // } if (e.key === "/") { e.preventDefault(); const selection = window.getSelection(); const range = selection.rangeCount > 0 ? selection.getRangeAt(0) : null; let parentRect = null; if (range) { if (!subLineActive) { parentRect = current_Editable.getBoundingClientRect(); } else { parentRect = current_subEditable.getBoundingClientRect(); } // Position dropdown UNDER `current_Editable` dropdownMenu.style.top = `${window.scrollY + parentRect.bottom + 10}px`; // dropdownMenu.style.left = `${window.scrollX + parentRect.left}px`; // dropdownMenu.style.width = `${parentRect.width}px`; // Show dropdown currentFocus = currentLabelActive(); preFocus = currentFocus; dropdownMenu.classList.toggle("active"); } } if (e.key == " ") { if (!subLineActive) { if (current_Editable.textContent.startsWith("#")) { e.preventDefault(); current_Editable.innerHTML = current_Editable.innerHTML.substring(1); current_Label = "headingLabel"; headingFunc(current_Label); } else if (current_Editable.textContent.startsWith(">")) { e.preventDefault(); current_Editable.innerHTML = current_Editable.innerHTML.substring(4); current_Label = "textLabel"; elementFunc(current_Label); } else if (current_Editable.textContent.startsWith("-")) { e.preventDefault(); current_Editable.innerHTML = current_Editable.innerHTML.substring(1); current_Label = "pointLabel"; elementFunc(current_Label); } else if (current_Editable.textContent.startsWith("*")) { e.preventDefault(); current_Editable.innerHTML = current_Editable.innerHTML.substring(1); current_Label = "checkboxLabel"; elementFunc(current_Label); } } else { if (current_subEditable.textContent.startsWith(">")) { e.preventDefault(); current_subEditable.innerHTML = current_subEditable.innerHTML.substring(4); current_Label = "textLabel"; elementFunc(current_Label); } else if (current_subEditable.textContent.startsWith("-")) { e.preventDefault(); current_subEditable.innerHTML = current_subEditable.innerHTML.substring(1); current_Label = "pointLabel"; elementFunc(current_Label); } else if (current_subEditable.textContent.startsWith("*")) { e.preventDefault(); current_subEditable.innerHTML = current_subEditable.innerHTML.substring(1); current_Label = "checkboxLabel"; elementFunc(current_Label); } } } if (e.ctrlKey && e.key == "z") { e.preventDefault(); } if (e.shiftKey && (e.key === "ArrowLeft" || e.key === "ArrowRight")) { // Using a timeout to ensure the selection update after the key press event is fully processed setTimeout(updateSelectedText, 0); } if (e.ctrlKey && e.key == "x") { e.preventDefault(); if (!subLineActive) { current_Editable.innerHTML = current_Editable.textContent.replace( text, "" ); current_Editable.focus(); window.getSelection().selectAllChildren(current_Editable); window.getSelection().collapseToEnd(); } else { current_subEditable.innerHTML = current_subEditable.textContent.replace( text, "" ); current_subEditable.focus(); window.getSelection().selectAllChildren(current_subEditable); window.getSelection().collapseToEnd(); } } if (e.ctrlKey && e.key == "c") { e.preventDefault(); if (!subLineActive) { current_Editable.focus(); window.getSelection().selectAllChildren(current_Editable); window.getSelection().collapseToEnd(); } else { current_subEditable.focus(); window.getSelection().selectAllChildren(current_subEditable); window.getSelection().collapseToEnd(); } } if (e.ctrlKey && e.key == "v") { e.preventDefault(); if (!subLineActive) { current_Editable.innerHTML += text; current_Editable.focus(); window.getSelection().selectAllChildren(current_Editable); window.getSelection().collapseToEnd(); } else { current_subEditable.innerHTML += text; current_subEditable.focus(); window.getSelection().selectAllChildren(current_subEditable); window.getSelection().collapseToEnd(); } } if (e.ctrlKey && e.key == "a") { e.preventDefault(); selection = true; let range = document.createRange(); range.selectNodeContents(aditor); window.getSelection().removeAllRanges(); window.getSelection().addRange(range); } if (e.key == "Tab") { if (e.shiftKey) { e.preventDefault(); // if (current_Label == "headingLabel") { headingCollapse_All(); // } } else { e.preventDefault(); if (current_Label == "headingLabel") { const line = current_Editable.closest(".line"); headingActionBtn(line, "switch"); headingCollapse(line); } else { indentFunc(); } } } if (e.key == "Enter") { e.preventDefault(); updateElement(); dropdownMenu.classList.remove("active"); if (!subLineActive && current_Editable.textContent.trim() == "") { current_Label = "textLabel"; updateLine(current_Label, "", current_Line); current_Editable = current_Line.querySelector(".inputContent"); current_Editable.focus(); } else if (!subLineActive && current_Editable.textContent.trim() != "") { if ( current_Label == "headingLabel" && current_Line.querySelector(".actionsOff") ) { current_Label = "textLabel"; addDiv(); headingScan(); } else { addDiv(); } } else if ( subLineActive && current_subEditable.textContent.trim() == "" ) { indentFunc(); } else if ( subLineActive && current_subEditable.textContent.trim() != "" ) { addDiv(); } } if (e.key == "Backspace") { // Check if the ul is empty if (selection) { emptyAditor(); } if (!subLineActive) { if (current_Editable.textContent.trim() == "") { updateElement(); if (previous_Line) { // Delete the current sub current_Line.remove(); // Focus on the ul of the previous sub current_Editable = previous_Line.querySelector(".inputContent"); const label = current_Editable .closest(".line") .querySelector("label"); current_Label = label.className; if (current_Label == "headingLabel") { // headingActionBtn(previous_Line, "off"); headingScan(); } activeOption(); if (current_Editable) { e.preventDefault(); current_Editable.focus(); window.getSelection().selectAllChildren(current_Editable); window.getSelection().collapseToEnd(); } } else if (next_Line) { // Delete the current sub current_Line.remove(); // Focus on the ul of the previous sub current_Editable = next_Line.querySelector(".inputContent"); const label = current_Editable .closest(".line") .querySelector("label"); current_Label = label.className; if (current_Label == "headingLabel") { // headingActionBtn(previous_Line, "off"); } activeOption(); if (current_Editable) { e.preventDefault(); current_Editable.focus(); window.getSelection().selectAllChildren(current_Editable); window.getSelection().collapseToEnd(); } } else { emptyAditor(); } } } else { if (current_subEditable.textContent.trim() == "") { updateElement(); current_subHead = current_subEditable.closest(".sub-Head"); next_subHead = current_subHead.nextElementSibling; previous_subHead = current_subHead.previousElementSibling; if (previous_subHead) { // Delete the current sub current_subHead.remove(); // Focus on the ul of the previous sub current_subEditable = previous_subHead.querySelector(".inputSubContent"); const label = previous_subHead.querySelector("label"); current_Label = label.className; if (current_Label == "checkboxLabel") { const parent = previous_subHead.closest(".line"); updateParentCheckbox(parent); //check it later how did i change the parent when new subhead added in previos aditor } activeOption(); if (current_subEditable) { e.preventDefault(); current_subEditable.focus(); window.getSelection().selectAllChildren(current_subEditable); window.getSelection().collapseToEnd(); } } else if (next_subHead) { // Delete the current sub current_subHead.remove(); // Focus on the ul of the next sub current_subEditable = next_subHead.querySelector(".inputSubContent"); const label = next_subHead.querySelector("label"); current_Label = label.className; if (current_Label == "checkboxLabel") { const parent = next_subHead.closest(".line"); updateParentCheckbox(parent); //check it later how did i change the parent when new subhead added in previos aditor } activeOption(); if (current_subEditable) { e.preventDefault(); current_subEditable.focus(); window.getSelection().selectAllChildren(current_subEditable); window.getSelection().collapseToEnd(); } } else { e.preventDefault(); subLineActive = false; const actionBtn = current_Line.querySelector(".actions"); actionBtn.classList.replace("actions", "actionsOff"); current_subLine.classList.replace("sub-line", "sub-line-off"); current_Editable = current_subEditable .closest(".line") .querySelector(".inputContent"); const label = current_Editable .closest(".line") .querySelector("label"); current_Label = label.className; activeOption(); current_Editable.focus(); window.getSelection().selectAllChildren(current_Editable); window.getSelection().collapseToEnd(); } } } } if ( (e.key == "ArrowUp" || e.key == "ArrowDown") && !dropdownMenu.classList.contains("active") ) { e.preventDefault(); updateElement(); navigator(e.key); } if (e.key == "ArrowLeft" && !dropdownMenu.classList.contains("active")) { const range = window.getSelection().getRangeAt(0); const tempRange = document.createRange(); if (!subLineActive) { tempRange.selectNodeContents(current_Editable); tempRange.setEnd(range.startContainer, range.startOffset); const cursorPosition = tempRange.toString().length; if (cursorPosition == 0) { e.preventDefault(); updateElement(); navigator(e.key); } } else { tempRange.selectNodeContents(current_subEditable); tempRange.setEnd(range.startContainer, range.startOffset); const cursorPosition = tempRange.toString().length; if (cursorPosition == 0) { e.preventDefault(); updateElement(); navigator(e.key); } } } if (e.key == "ArrowRight" && !dropdownMenu.classList.contains("active")) { const range = window.getSelection().getRangeAt(0); const tempRange = document.createRange(); if (!subLineActive) { tempRange.selectNodeContents(current_Editable); tempRange.setEnd(range.startContainer, range.startOffset); const cursorPosition = tempRange.toString().length; const currentEditableLength = current_Editable.textContent.length; if (cursorPosition == currentEditableLength) { e.preventDefault(); updateElement(); navigator(e.key); } } else { tempRange.selectNodeContents(current_subEditable); tempRange.setEnd(range.startContainer, range.startOffset); const cursorPosition = tempRange.toString().length; const currentEditableLength = current_subEditable.textContent.length; if (cursorPosition == currentEditableLength) { e.preventDefault(); updateElement(); navigator(e.key); } } } }); let oneTime = true; if (defaultValue == "") { current_Editable.textContent = "Write something ....."; oneTime = false; } aditor.addEventListener("click", (e) => { if ( e.target.parentElement.className == "expand" || e.target.parentElement.className == "collapse" ) { const label = e.target.parentElement .closest(".line") .querySelector("label").className; if (label == "headingLabel") { const line = e.target.parentElement.closest(".line"); headingActionBtn(line, "switch"); headingCollapse(line); } else { let expandBtn = e.target.parentElement; let expand = e.target.parentElement .closest(".line") .querySelector(".sub-line"); if (expand != null) { expand.classList.replace("sub-line", "sub-line-off"); expandBtn.classList.replace("expand", "collapse"); expandBtn.innerHTML = `<i class="fa-solid fa-caret-right"></i>`; } else { expand = expandBtn.closest(".line").querySelector(".sub-line-off"); expand.classList.replace("sub-line-off", "sub-line"); expandBtn.classList.replace("collapse", "expand"); expandBtn.innerHTML = ` <i class="fa-solid fa-caret-down"></i>`; } } } else if (e.target.parentElement.className == "actions") { const label = e.target.closest(".line").querySelector("label").className; if (label == "headingLabel") { const line = e.target.closest(".line"); headingActionBtn(line, "switch"); headingCollapse(line); } else { let expandBtn = e.target; let expand = e.target.closest(".line").querySelector(".sub-line"); if (expand != null) { expand.classList.replace("sub-line", "sub-line-off"); expandBtn.classList.replace("expand", "collapse"); expandBtn.innerHTML = `<i class="fa-solid fa-caret-right"></i>`; } else { expand = expandBtn.closest(".line").querySelector(".sub-line-off"); expand.classList.replace("sub-line-off", "sub-line"); expandBtn.classList.replace("collapse", "expand"); expandBtn.innerHTML = ` <i class="fa-solid fa-caret-down"></i>`; } } } else if (e.target.classList == "inputContent") { if (!oneTime) { current_Editable = e.target; updateElement(); current_Editable.textContent = ""; oneTime = true; } subLineActive = false; current_Editable = e.target; updateElement(); const label = current_Line.querySelector("label"); current_Label = label.className; activeOption(); } else if (e.target.classList == "inputSubContent") { subLineActive = true; current_subEditable = e.target; current_Editable = current_subEditable .closest(".sub-Head") .closest(".line") .querySelector(".inputContent"); updateElement(); const label = current_subHead.querySelector("label"); current_Label = label.className; activeOption(); } else if ( e.target.type == "checkbox" || e.target.classList == "checked" || e.target.classList == "unchecked" ) { let checkbox = e.target.nextElementSibling; // checkbox.classList.toggle("done"); checkbox.classList == "unchecked" ? checkbox.classList.replace("unchecked", "checked") : checkbox.classList.replace("checked", "unchecked"); const parent = e.target.closest(".line"); if (!checkbox.closest(".Head")) { updateParentCheckbox(parent); } else { updateNestedCheckbox(parent); } } else { if (e.target.className == "sub-line") { current_subLine = e.target.closest(".sub-line"); current_subHead = e.target.closest(".sub-Head"); updateElement(); const label = current_subHead.querySelector("label"); current_Label = label.className; current_subEditable = current_subHead.querySelector(".inputSubContent"); current_subEditable.focus(); window.getSelection().selectAllChildren(current_subEditable); window.getSelection().collapseToEnd(); } else { current_Line = e.target.closest(".line"); if (!oneTime) { updateElement(); current_Editable.textContent = ""; oneTime = true; } updateElement(); const label = current_Line.querySelector("label"); current_Label = label.className; current_Editable = current_Line.querySelector(".inputContent"); current_Editable.focus(); window.getSelection().selectAllChildren(current_Editable); window.getSelection().collapseToEnd(); } } }); function backward() { if (!subLineActive) { if (previous_Line != null && previous_subLine == null) { const label = previous_Line.querySelector("label"); current_Label = label.className; current_Editable = previous_Line.querySelector(".inputContent"); current_Editable.focus(); window.getSelection().selectAllChildren(current_Editable); } else if (previous_Line != null && previous_subLine != null) { subLineActive = true; const current_subLine_lastHead = previous_subLine.lastElementChild; const label = current_subLine_lastHead.querySelector("label"); current_Label = label.className; current_subEditable = current_subLine_lastHead.querySelector(".inputSubContent"); current_subEditable.focus(); window.getSelection().selectAllChildren(current_subEditable); } } else { current_subHead = current_subEditable.closest(".sub-Head"); previous_subHead = current_subHead.previousElementSibling; if (previous_subHead != null) { const label = previous_subHead.querySelector("label"); current_Label = label.className; current_subEditable = previous_subHead.querySelector(".inputSubContent"); current_subEditable.focus(); window.getSelection().selectAllChildren(current_subEditable); } else if (previous_subHead == null) { subLineActive = false; const label = current_subHead.closest(".line").querySelector("label"); current_Label = label.className; current_Editable = current_subHead .closest(".line") .querySelector(".inputContent"); current_Editable.focus(); window.getSelection().selectAllChildren(current_Editable); } } window.getSelection().collapseToEnd(); } function forward(key) { if (!subLineActive) { if (next_Line != null && current_subLine == null) { const label = next_Line.querySelector("label"); current_Label = label.className; current_Editable = next_Line.querySelector(".inputContent"); current_Editable.focus(); window.getSelection().selectAllChildren(current_Editable); } else if (current_subLine != null) { subLineActive = true; const current_subLine_firstHead = current_subLine.firstElementChild; const label = current_subLine_firstHead.querySelector("label"); current_Label = label.className; current_subEditable = current_subLine_firstHead.querySelector(".inputSubContent"); current_subEditable.focus(); window.getSelection().selectAllChildren(current_subEditable); } } else { current_Line = current_subEditable.closest(".line"); next_Line = current_Line.nextElementSibling; current_subHead = current_subEditable.closest(".sub-Head"); next_subHead = current_subHead.nextElementSibling; if (next_subHead != null) { const label = next_subHead.querySelector("label"); current_Label = label.className; current_subEditable = next_subHead.querySelector(".inputSubContent"); current_subEditable.focus(); window.getSelection().selectAllChildren(current_subEditable); } else if (next_subHead == null && next_Line != null) { subLineActive = false; const label = next_Line.closest(".line").querySelector("label"); current_Label = label.className; current_Editable = next_Line .closest(".line") .querySelector(".inputContent"); current_Editable.focus(); window.getSelection().selectAllChildren(current_Editable); } } if (key == "ArrowRight") { window.getSelection().collapseToStart(); } else { window.getSelection().collapseToEnd(); } } function navigator(key) { updateElement(); if (key == "ArrowUp") { backward(); } else if (key == "ArrowDown") { forward(); } else if (key == "ArrowLeft") { backward(); } else if (key == "ArrowRight") { forward("ArrowRight"); } updateElement(); activeOption(); } function updateLabel(label, current_EditableText) { if (label == "headingLabel") { return `<label class="headingLabel"></label> <div class="content"> <h3><ul class="inputContent" contenteditable="true">${current_EditableText}</ul></h3> </div>`; } else if (label == "textLabel") { return `<label class="textLabel"></label> <div class="content"> <ul class="inputContent" contenteditable="true">${current_EditableText}</ul> </div>`; } else if (label == "pointLabel") { return `<label class="pointLabel"> <input type="checkbox" /><span class="points"><i class="fa-solid fa-circle"></i></span ></label> <div class="content"> <ul class="inputContent" contenteditable="true">${current_EditableText}</ul> </div>`; } else if (label == "checkboxLabel") { return `<label class="checkboxLabel"> <input type="checkbox"/><span class="unchecked"></span ></label> <div class="content"> <ul class="inputContent" contenteditable="true">${current_EditableText}</ul> </div>`; } } function updateLine(label, current_EditableText, Div) { let newLabel = updateLabel(label, current_EditableText); if (label == "headingLabel") { Div.innerHTML = `<div class="Head"> ${newLabel} <div class="actionsOff"> <button class="expand"> <i class="fa-solid fa-caret-down"></i> </button> </div> </div> `; } else if (label == "checkboxLabel") { Div.innerHTML = `<div class="Head"> ${newLabel} <div class="actionsOff"> <button class="expand"> <i class="fa-solid fa-caret-down"></i> </button> </div> </div> <div class="sub-line-off"> <div class="sub-Head"> <label class="checkboxLabel"> <input type="checkbox"/><span class="unchecked"></span ></label> <div class="sub-content"> <ul class="inputSubContent" contenteditable="true"></ul> </div> </div> </div>`; } else { Div.innerHTML = `<div class="Head"> ${newLabel} <div class="actionsOff"> <button class="expand"> <i class="fa-solid fa-caret-down"></i> </button> </div> </div> <div class="sub-line-off"> <div class="sub-Head"> <label class="pointLabel"> <input type="checkbox" /><span class="points"><i class="fa-solid fa-square"></i></span ></label> <div class="sub-content"> <ul class="inputSubContent" contenteditable="true"></ul> </div> </div> </div>`; } } function updateHead(label, current_EditableText, current_subContent, Div) { let newLabel = updateLabel(label, current_EditableText); Div.innerHTML = `<div class="Head"> ${newLabel} <div class="actions"> <button class="expand"> <i class="fa-solid fa-caret-down"></i> </button> </div> </div> ${current_subContent}`; } function updateSubLine(label, current_EditableText, Div) { if (label == "textLabel") { Div.innerHTML = ` <label class="textLabel"></label> <div class="sub-content"> <ul class="inputSubContent" contenteditable="true">${current_EditableText}</ul> </div>`; } else if (label == "pointLabel") { Div.innerHTML = ` <label class="pointLabel"> <input type="checkbox" /><span class="points"><i class="fa-solid fa-square"></i></i></span ></label> <div class="sub-content"> <ul class="inputSubContent" contenteditable="true">${current_EditableText}</ul> </div>`; } else if (label == "checkboxLabel") { Div.innerHTML = ` <label class="checkboxLabel"> <input type="checkbox"/><span class="unchecked"></span ></label> <div class="sub-content"> <ul class="inputSubContent" contenteditable="true">${current_EditableText}</ul> </div>`; } } function addDiv() { updateElement(); activeOption(); if (!subLineActive) { const range = window.getSelection().getRangeAt(0); const tempRange = document.createRange(); tempRange.selectNodeContents(current_Editable); tempRange.setEnd(range.startContainer, range.startOffset); const cursorPosition = tempRange.toString().length; // Create new line when sub line is off const Div = document.createElement("div"); Div.classList.add("line"); updateLine(current_Label, "", Div); if (current_Label == "headingLabel") { let initial = null; let final = null; const childDivs = aditor.children; Array.from(childDivs).forEach((child) => { if (initial == null) { if (current_Line == child) { initial = child; } } else if ( final == null && child.querySelector("Label").className == "headingLabel" ) { final = child; } }); if (cursorPosition == "0") { aditor.insertBefore(Div, current_Line); current_Editable = Div.querySelector(".inputContent"); current_Editable.focus(); window.getSelection().selectAllChildren(current_Editable); window.getSelection().collapseToEnd(); } else if (final != null) { aditor.insertBefore(Div, final); current_Editable = Div.querySelector(".inputContent"); current_Editable.focus(); window.getSelection().selectAllChildren(current_Editable); window.getSelection().collapseToEnd(); } else { aditor.appendChild(Div); current_Editable = Div.querySelector(".inputContent"); current_Editable.focus(); window.getSelection().selectAllChildren(current_Editable); window.getSelection().collapseToEnd(); } } else { if (cursorPosition == "0") { aditor.insertBefore(Div, current_Line); current_Editable = Div.querySelector(".inputContent"); current_Editable.focus(); window.getSelection().selectAllChildren(current_Editable); window.getSelection().collapseToEnd(); } else if (next_Line != null) { aditor.insertBefore(Div, next_Line); current_Editable = Div.querySelector(".inputContent"); current_Editable.focus(); window.getSelection().selectAllChildren(current_Editable); window.getSelection().collapseToEnd(); } else { aditor.appendChild(Div); current_Editable = Div.querySelector(".inputContent"); current_Editable.focus(); window.getSelection().selectAllChildren(current_Editable); window.getSelection().collapseToEnd(); } } } else { // updateElement(); if (current_subEditable.textContent.trim() != "") { const range = window.getSelection().getRangeAt(0); const tempRange = document.createRange(); tempRange.selectNodeContents(current_subEditable); tempRange.setEnd(range.startContainer, range.startOffset); const cursorPosition = tempRange.toString().length; // create new sub head in the sub line const Div = document.createElement("div"); Div.classList.add("sub-Head"); current_subHead = current_subEditable.closest(".sub-Head"); current_subLine = current_subHead.closest(".sub-line"); updateSubLine(current_Label, "", Div); if (cursorPosition == "0") { current_subLine.insertBefore(Div, current_subHead); current_subEditable = Div.querySelector(".inputSubContent"); current_subEditable.focus(); window.getSelection().selectAllChildren(current_subEditable); window.getSelection().collapseToEnd(); } else if (next_subHead != null) { current_subLine = next_subHead.closest(".sub-line"); current_subLine.insertBefore(Div, next_subHead); current_subEditable = Div.querySelector(".inputSubContent"); current_subEditable.focus(); window.getSelection().selectAllChildren(current_subEditable); window.getSelection().collapseToEnd(); } else { current_subLine = current_subHead.closest(".sub-line"); current_subLine.appendChild(Div); current_subEditable = Div.querySelector(".inputSubContent"); current_subEditable.focus(); window.getSelection().selectAllChildren(current_subEditable); window.getSelection().collapseToEnd(); } } // else if (current_subEditable.textContent.trim() != "") { // // change the sub line // updateSubLine(current_Label, current_EditableText, current_subHead); // subAditorActive = false; // current_subEditable = current_subHead.querySelector(".inputSubContent"); // current_subEditable.focus(); // window.getSelection().selectAllChildren(current_subEditable); // window.getSelection().collapseToEnd(); // } if (current_Line.querySelector("label").className == "checkboxLabel") { const parent = current_subHead.closest(".line"); updateParentCheckbox(parent); //check it later how did i change the parent when new subhead added in previos aditor } } } function headingActionBtn(line, action) { if (action == "switch") { if (line.querySelector(".collapse")) { const expandBtn = line.querySelector(".collapse"); expandBtn.classList.replace("collapse", "expand"); expandBtn.innerHTML = ` <i class="fa-solid fa-caret-down"></i>`; } else if (line.querySelector(".expand")) { const expandBtn = line.querySelector(".expand"); expandBtn.classList.replace("expand", "collapse"); expandBtn.innerHTML = `<i class="fa-solid fa-caret-right"></i>`; } } else if (action == "on" && line.querySelector(".actionsOff") != null) { const actionBtn = line.querySelector(".actionsOff"); actionBtn.classList.replace("actionsOff", "actions"); } else if (action == "off" && line.querySelector(".actions") != null) { const actionBtn = line.querySelector(".actions"); actionBtn.classList.replace("actions", "actionsOff"); } else if (action == "switchOff") { if (line.querySelector(".expand")) { const expandBtn = line.querySelector(".expand"); expandBtn.classList.replace("expand", "collapse"); expandBtn.innerHTML = `<i class="fa-solid fa-caret-right"></i>`; } } else if (action == "switchOn") { if (line.querySelector(".collapse")) { const expandBtn = line.querySelector(".collapse"); expandBtn.classList.replace("collapse", "expand"); expandBtn.innerHTML = ` <i class="fa-solid fa-caret-down"></i>`; } } } function headingScan() { let initial = null; let mid_line = 0; const childDivs = Array.from(aditor.children); childDivs.forEach((child, index) => { const isHeading = child.querySelector("Label")?.className === "headingLabel"; if (isHeading) { initial = index; } else if (initial !== null) { mid_line++; } if (initial != null && mid_line > 0) { headingActionBtn(childDivs[initial], "on"); initial = null; mid_line = 0; } else if (initial != null && mid_line == 0) { headingActionBtn(childDivs[initial], "off"); } }); } function headingCollapse(line) { let initial = null; let final = null; const childDivs = aditor.children; Array.from(childDivs).forEach((child, index) => { if (initial == null) { if (line == child) { initial = index; } } else if ( final == null && child.querySelector("Label").className == "headingLabel" ) { final = index; } }); if (final != null) { for (let i = initial + 1; i < final; i++) { childDivs[i].classList.toggle("collapsed"); } } else { for (let i = initial + 1; i < childDivs.length; i++) { childDivs[i].classList.toggle("collapsed"); } } } let allExpand = false; function headingCollapse_All() { let foundHeading = false; const childDivs = aditor.children; Array.from(childDivs).forEach((child, index) => { if (child.querySelector("Label").className == "headingLabel") { foundHeading = true; if (allExpand) { headingActionBtn(child, "switchOn"); } else { headingActionBtn(child, "switchOff"); } } else if (foundHeading) { if (!allExpand && childDivs[index].className == "line") { childDivs[index].classList.add("collapsed"); } else if ( allExpand && childDivs[index].className == "line collapsed" ) { childDivs[index].classList.remove("collapsed"); } } }); allExpand = !allExpand; current_Editable = inputSection.querySelector(".inputContent"); current_Line = current_Editable.closest(".line"); current_Label = current_Line.querySelector("Label").className; current_Editable.focus(); window.getSelection().selectAllChildren(current_Editable); window.getSelection().collapseToEnd(); updateElement(); } function updateNestedCheckbox(parent) { if (parent.querySelector(".Head").querySelector(".checked")) { const subUnchecked = parent .querySelector(".sub-line") .querySelectorAll(".unchecked"); subUnchecked.forEach((item) => { item.classList.replace("unchecked", "checked"); }); } else { const subChecked = parent .querySelector(".sub-line") .querySelectorAll(".checked"); subChecked.forEach((item) => { item.classList.replace("checked", "unchecked"); }); } } function updateParentCheckbox(parent) { const subUnchecked = parent .querySelector(".sub-line") .querySelectorAll(".unchecked").length; const subChecked = parent .querySelector(".sub-line") .querySelectorAll(".checked").length; if (subUnchecked == 0 && subChecked > 0) { const parentCheckbox = parent .querySelector(".Head") .querySelector(".unchecked"); if (parentCheckbox != null) { parentCheckbox.classList.replace("unchecked", "checked"); } } else if (subUnchecked > 0) { const parentCheckbox = parent .querySelector(".Head") .querySelector(".checked"); if (parentCheckbox != null) { parentCheckbox.classList.replace("checked", "unchecked"); } } } function headingFunc(current_Label) { updateElement(); if ( !subLineActive && current_Label != "hradingLabel" && current_Line.querySelector(".actionsOff") ) { current_Label = "headingLabel"; activeOption(); current_EditableText = current_Editable.textContent; updateElement(); let current_subContent = current_Editable .closest(".line") .querySelector(".sub-line"); if (current_subContent == null) { updateLine(current_Label, current_EditableText, current_Line); } else { current_subContent = current_subContent.outerHTML; updateHead( current_Label, current_EditableText, current_subContent, current_Line ); } headingScan(); current_Editable = current_Line.querySelector(".inputContent"); current_Editable.focus(); window.getSelection().selectAllChildren(current_Editable); window.getSelection().collapseToEnd(); } // else // { // current_Editable = current_Line.querySelector(".inputContent"); // current_Editable.focus(); // window.getSelection().selectAllChildren(current_Editable); // window.getSelection().collapseToEnd(); // } } function elementFunc(current_Label) { activeOption(); updateElement(); if (!subLineActive) { current_EditableText = current_Editable.textContent; let current_subContent = current_Editable .closest(".line") .querySelector(".sub-line"); if (current_subContent == null) { updateLine(current_Label, current_EditableText, current_Line); } else { current_subContent = current_subContent.outerHTML; updateHead( current_Label, current_EditableText, current_subContent, current_Line ); } current_Editable = current_Line.querySelector(".inputContent"); current_Editable.focus(); window.getSelection().selectAllChildren(current_Editable); window.getSelection().collapseToEnd(); } else { subAditorActive = true; current_EditableText = current_subEditable.textContent; updateSubLine(current_Label, current_EditableText, current_subHead); current_subEditable = current_subHead.querySelector(".inputSubContent"); current_subEditable.focus(); window.getSelection().selectAllChildren(current_subEditable); window.getSelection().collapseToEnd(); // addDiv(); } } function indentFunc() { updateElement(); const HeadContent = current_Line.querySelector(".inputContent").textContent; current_subLine = current_Line.querySelector(".sub-line-off"); if (HeadContent == "") { current_Editable.focus(); } else if (subLineActive) { subLineActive = false; const label = current_Line.querySelector(".Head").querySelector("label"); current_Label = label.className; if (current_Label == "headingLabel") { current_Label = "textLabel"; } current_Editable = current_subEditable .closest(".sub-Head") .closest(".line") .querySelector(".inputContent"); addDiv(); } else if (current_subLine != null && HeadContent != "") { const current_subLine_Amount = current_subLine.querySelectorAll(".sub-Head").length; const actionBtn = current_Line.querySelector(".actionsOff"); if (current_subLine_Amount == 1 && actionBtn != null) { subLineActive = true; current_subLine.classList.replace("sub-line-off", "sub-line"); actionBtn.classList.replace("actionsOff", "actions"); // current_subHead = current_subLine.querySelector(".sub-Head"); current_subEditable = current_subLine.querySelector(".inputSubContent"); const label = current_subEditable .closest(".sub-Head") .querySelector("label"); current_Label = label.className; current_subEditable.focus(); window.getSelection().selectAllChildren(current_subEditable); window.getSelection().collapseToEnd(); } else { subLineActive = false; // let expand = current_Line.querySelector(".sub-line"); const expandBtn = current_Line.querySelector(".collapse"); current_subLine = current_Line.querySelector(".sub-line-off"); current_subLine.classList.replace("sub-line-off", "sub-line"); expandBtn.classList.replace("collapse", "expand"); expandBtn.innerHTML = ` <i class="fa-solid fa-caret-down"></i>`; current_Editable.focus(); window.getSelection().selectAllChildren(current_Editable); window.getSelection().collapseToEnd(); } } else if ( current_subLine == null && current_subEditable.textContent != "" ) { subLineActive = false; const expandBtn = current_Line.querySelector(".expand"); current_subLine = current_Line.querySelector(".sub-line"); current_subLine.classList.replace("sub-line", "sub-line-off"); expandBtn.classList.replace("expand", "collapse"); expandBtn.innerHTML = `<i class="fa-solid fa-caret-right"></i>`; current_Editable.focus(); window.