function insertAssist(text) { var area = document.querySelector('textarea[name=\"text\"]'); if (!area) return; area.focus(); try { if (!document.execCommand('insertText', false, text)) { var start = area.selectionStart; var end = area.selectionEnd; area.setRangeText(text, start, end, 'end'); area.dispatchEvent(new Event('input', { bubbles: true })); } } catch (e) { var start = area.selectionStart; var end = area.selectionEnd; var val = area.value; area.value = val.substring(0, start) + text + val.substring(end); area.selectionStart = area.selectionEnd = start + text.length; } } function modifyLines(action) { var area = document.querySelector('textarea[name=\"text\"]'); if (!area) return; var scrollTop = area.scrollTop; var scrollLeft = area.scrollLeft; var selStart = area.selectionStart; var selEnd = area.selectionEnd; var val = area.value; // 1. Identify the block of lines var blockStart = (selStart === 0) ? 0 : val.lastIndexOf('\\n', selStart - 1) + 1; var blockEnd = val.indexOf('\\n', selEnd); if (blockEnd === -1) blockEnd = val.length; var fullText = val.substring(blockStart, blockEnd); var lines = fullText.split('\\n'); var currentPos = blockStart; var diffStart = 0; var diffTotal = 0; var modifiedLines = lines.map(function(line, index) { var lineStart = currentPos; var lineEnd = currentPos + line.length; var oldLen = line.length; var newLine = line; var shouldProcess = false; // NEW RULE: If nothing is selected (cursor only), process the line the cursor is on if (selStart === selEnd) { if (selStart >= lineStart && selStart <= lineEnd) { shouldProcess = true; } } else if (line.trim() === \"\") { // Rule: Blank lines process if any part is selected (even if no hilite) if (selStart <= lineEnd && selEnd >= lineStart) { shouldProcess = true; } } else { // Rule: Text lines process ONLY if text character is actually highlighted var intersectStart = Math.max(selStart, lineStart); var intersectEnd = Math.min(selEnd, lineEnd); if (intersectEnd > intersectStart) { shouldProcess = true; } } if (shouldProcess) { if (action === 'comment') { newLine = '#' + line; } else if (action === 'uncomment') { if (line.charAt(0) === '#') { newLine = line.substring(1); } } } var change = newLine.length - oldLen; diffTotal += change; if (index === 0) diffStart = change; currentPos = lineEnd + 1; return newLine; }); var newBlockText = modifiedLines.join('\\n'); area.focus(); area.setSelectionRange(blockStart, blockEnd); try { if (!document.execCommand('insertText', false, newBlockText)) { area.setRangeText(newBlockText, blockStart, blockEnd, 'select'); area.dispatchEvent(new Event('input', { bubbles: true })); } } catch (e) { area.value = val.substring(0, blockStart) + newBlockText + val.substring(blockEnd); } // Restore selection/cursor position var newSelStart = (selStart === blockStart) ? selStart : selStart + diffStart; var newSelEnd = selEnd + diffTotal; // Ensure cursor doesn't drift if it was at the very start of a line if (selStart === selEnd) { area.setSelectionRange(newSelEnd, newSelEnd); } else { area.setSelectionRange(newSelStart, newSelEnd); } requestAnimationFrame(function() { area.scrollTop = scrollTop; area.scrollLeft = scrollLeft; }); } function setAssistDisabled(state) { document.querySelectorAll('.gui-assist-btn').forEach(function(b) { b.disabled = state; }); } window.addEventListener('load', function() { var area = document.querySelector('textarea[name=\"text\"]'); if (area) { area.addEventListener('focus', function() { setAssistDisabled(false); }); area.addEventListener('blur', function(e) { if (e.relatedTarget && e.relatedTarget.classList.contains('gui-assist-btn')) return; setAssistDisabled(true); }); if (document.activeElement !== area) setAssistDisabled(true); } var area = document.querySelector('textarea[name=\"text\"]'); if (!area) return; area.focus(); document.getElementById('up_arrow').addEventListener('click', (e) => { e.preventDefault(); moveCursor('up'); }); document.getElementById('down_arrow').addEventListener('click', (e) => { e.preventDefault(); moveCursor('down'); }); }); function moveCursor(direction) { var area = document.querySelector('textarea[name=\"text\"]'); const text = area.value; const start = area.selectionStart; const lines = text.split(\"\\n\"); let currentLineIdx = 0; let currentColumn = 0; let accumulatedChars = 0; // 1. Determine current line and column for (let i = 0; i < lines.length; i++) { const lineLengthWithNewline = lines[i].length + 1; if (accumulatedChars + lineLengthWithNewline > start) { currentLineIdx = i; currentColumn = start - accumulatedChars; break; } accumulatedChars += lineLengthWithNewline; } // 2. Determine target line index let targetLineIdx = (direction === 'up') ? currentLineIdx - 1 : currentLineIdx + 1; // 3. If target line is valid, calculate new character index if (targetLineIdx >= 0 && targetLineIdx < lines.length) { let newPos = 0; for (let i = 0; i < targetLineIdx; i++) { newPos += lines[i].length + 1; } // Ensure we don't go past the end of a shorter target line const targetLineContentLength = lines[targetLineIdx].length; newPos += Math.min(currentColumn, targetLineContentLength); // 4. Apply new position and refocus area.focus(); area.setSelectionRange(newPos, newPos); } else { // Keep focus even if we hit the top/bottom boundary area.focus(); } } "; #------------------------------------------------------------------------------------------------------------------------------------------------------------- # button line shorteners $btn1 = ""); $GUIButtons['assist_open' ] = array(3000,'','','', "$btn1'Open Directive' $btn2\"(:\")' >(: "); $GUIButtons['assist_close' ] = array(3000,'','','', "$btn1'Close Directive' $btn2\":)\")' >:) "); $GUIButtons['assist_pgdir' ] = array(3000,'','','', "$btn1'Directive' $btn2\"(::)\")' >(::) "); $GUIButtons['assist_dptv' ] = array(3000,'','','', "$btn1'Define Page Text Variable' $btn2\"(:::)\")' >(:::) "); $GUIButtons['assist_sptv' ] = array(3000,'','','', "$btn1'Show Page Text Variable' $btn2\"{\$:}\")' >{\$:} "); $GUIButtons['assist_pre_op' ] = array(3000,'','','', "$btn1'Preformatted Text Open' $btn2\"[@\")' >[@ "); $GUIButtons['assist_pre_cl' ] = array(3000,'','','', "$btn1'Preformatted Text Close' $btn2\"@]\")' >@] "); $GUIButtons['assist_pre' ] = array(3000,'','','', "$btn1'Preformatted Text' $btn2\"[@@]\")' >[@@] "); $GUIButtons['assist_mono' ] = array(3000,'','','', "$btn1'Monospace Text' $btn2\"@@\")' >@@ "); $GUIButtons['assist_esctxt_op'] = array(3000,'','','', "$btn1'Escape Text Open' $btn2\"[=\")' >[= "); $GUIButtons['assist_esctxt_cl'] = array(3000,'','','', "$btn1'Escape Text Close' $btn2\"=]\")' >=] "); $GUIButtons['assist_esctxt' ] = array(3000,'','','', "$btn1'Escape Text' $btn2\"[==]\")' >[==] "); $GUIButtons['assist_spider' ] = array(3000,'','','', "$btn1'Icky Spider' $btn2\">><<\")' >>><< "); $GUIButtons['separator1' ] = array(3000,'','','', "$btn_sep$btn_sep_end" ); $GUIButtons['assist_title' ] = array(3000,'','','', "$btn1'(:title :)' $btn2\"(:title :)\")' >title "); $GUIButtons['assist_lb' ] = array(3000,'','','', "$btn1'(:linebreaks:) Mode' $btn2\"(:linebreaks:)\")' >LB "); $GUIButtons['assist_nlb' ] = array(3000,'','','', "$btn1'(:nolinebreaks:) Mode' $btn2\"(:nolinebreaks:)\")'>NLB "); $GUIButtons['assist_hashlists'] = array(3000,'','','', "$btn1'#Lists Mode' $btn2\"(:#Lists:)\")' >#lists "); $GUIButtons['assist_hashcomnt'] = array(3000,'','','', "$btn1'#Comments Mode' $btn2\"(:#Comments:)\")' >#comments "); $GUIButtons['assist_sig' ] = array(3000,'','','', "$btn1'Signature ~~~~' $btn2\"~~~~\")' >sig "); $GUIButtons['separator2' ] = array(3000,'','','', "$btn_sep$btn_sep_end" ); $GUIButtons['assist_tilde' ] = array(3000,'','','', "$btn1'Tilde' $btn2\"~\")' >~ "); $GUIButtons['assist_exclam' ] = array(3000,'','','', "$btn1'Exclamation Point' $btn2\"!\")' >! "); $GUIButtons['assist_at' ] = array(3000,'','','', "$btn1'At Symbol' $btn2\"@\")' >@ "); $GUIButtons['assist_question' ] = array(3000,'','','', "$btn1'Question Mark' $btn2\"?\")' >? "); $GUIButtons['assist_hash' ] = array(3000,'','','', "$btn1'Hash' $btn2\"#\")' ># "); $GUIButtons['assist_dollar' ] = array(3000,'','','', "$btn1'Dollar' $btn2\"$\")' >$ "); $GUIButtons['assist_percent' ] = array(3000,'','','', "$btn1'Percent' $btn2\"%\")' >% "); $GUIButtons['assist_caret' ] = array(3000,'','','', "$btn1'Caret' $btn2\"^\")' >^ "); $GUIButtons['assist_amp' ] = array(3000,'','','', "$btn1'Ampersand' $btn2\"&\")' >& "); $GUIButtons['assist_asterisk' ] = array(3000,'','','', "$btn1'Asterisk' $btn2\"*\")' >* "); $GUIButtons['assist_paren_op' ] = array(3000,'','','', "$btn1'Open Parenthesis' $btn2\"(\")' >( "); $GUIButtons['assist_paren_cl' ] = array(3000,'','','', "$btn1'Close Parenthesis' $btn2\")\")' >) "); $GUIButtons['assist_brckt_op' ] = array(3000,'','','', "$btn1'Open Bracket' $btn2\"[\")' >[ "); $GUIButtons['assist_brckt_cl' ] = array(3000,'','','', "$btn1'Close Bracket' $btn2\"]\")' >] "); $GUIButtons['assist_angle_op' ] = array(3000,'','','', "$btn1'Less Than' $btn2\"<\")' >< "); $GUIButtons['assist_angle_cl' ] = array(3000,'','','', "$btn1'Greater Than' $btn2\">\")' >> "); $GUIButtons['assist_brace_op' ] = array(3000,'','','', "$btn1'Open Brace' $btn2\"{\")' >{ "); $GUIButtons['assist_brace_cl' ] = array(3000,'','','', "$btn1'Close Brace' $btn2\"}\")' >} "); $GUIButtons['assist_slash' ] = array(3000,'','','', "$btn1'Forward Slash' $btn2\"/\")' >/ "); $GUIButtons['assist_backslash'] = array(3000,'','','', "$btn1'Back Slash' $btn2\"\\\\\\\\\")' >\\ "); $GUIButtons['assist_pipe' ] = array(3000,'','','', "$btn1'Pipe' $btn2\"|\")' >| "); $GUIButtons['assist_colon' ] = array(3000,'','','', "$btn1'Colon' $btn2\":\")' >: "); $GUIButtons['assist_semicolon'] = array(3000,'','','', "$btn1'Semi Colon' $btn2\";\")' >; "); $GUIButtons['assist_period' ] = array(3000,'','','', "$btn1'Period' $btn2\".\")' >. "); $GUIButtons['assist_comma' ] = array(3000,'','','', "$btn1'Comma' $btn2\",\")' >, "); $GUIButtons['assist_quote_sn' ] = array(3000,'','','', "$btn1'Single Quote' $btn2\"'\")' >' "); $GUIButtons['assist_quote_db' ] = array(3000,'','','', "$btn1'Double Quote' $btn2\"\\\"\")' >\" "); $GUIButtons['assist_plus' ] = array(3000,'','','', "$btn1'Plus' $btn2\"+\")' >+ "); $GUIButtons['assist_equal' ] = array(3000,'','','', "$btn1'Equal' $btn2\"=\")' >= "); $GUIButtons['assist_backtick' ] = array(3000,'','','', "$btn1'Backtick' $btn2\"`\")' >` "); $GUIButtons['separator3' ] = array(3000,'','','', "$btn_sep$btn_sep_end" ); $GUIButtons['assist_top' ] = array(3000,'','','', "$btn1'Top' $btn3 if(a){a.focus(); a.setSelectionRange(0,0);}'>Top"); $GUIButtons['assist_bottom' ] = array(3000,'','','', "$btn1'Bottom' $btn3 if(a){a.focus(); var len=a.value.length; a.setSelectionRange(len,len);}'>Bottom"); $GUIButtons['assist_pgup' ] = array(3000,'','','', "$btn1'PgUp' $btn3 if(a){ var lh=parseFloat(getComputedStyle(a).lineHeight)||20; var lines=Math.floor(a.clientHeight/lh)-1; a.scrollTop-=(lines*lh); }'>PgUp"); $GUIButtons['assist_pgdn' ] = array(3000,'','','', "$btn1'PgDn' $btn3 if(a){ var lh=parseFloat(getComputedStyle(a).lineHeight)||20; var lines=Math.floor(a.clientHeight/lh)-1; a.scrollTop+=(lines*lh); }'>PgDn"); $GUIButtons['assist_up' ] = array(3000,'','','', "$btn1'Move Cursor Up' id='up_arrow' >↑"); $GUIButtons['assist_down' ] = array(3000,'','','', "$btn1'Move Cursor Down' id='down_arrow' >↓"); $GUIButtons['assist_left' ] = array(3000,'','','', "$btn1'Move Cursor Left' $btn3 if(a){a.focus(); var s=a.selectionStart; if(s>0)a.setSelectionRange(s-1,s-1);}'>←"); $GUIButtons['assist_right' ] = array(3000,'','','', "$btn1'Move Cursor Right' $btn3 if(a){a.focus(); var s=a.selectionStart; a.setSelectionRange(s+1,s+1);}'>→"); $GUIButtons['separator4' ] = array(3000,'','','', "$btn_sep$btn_sep_end" ); $GUIButtons['assist_del' ] = array(3000,'','','', "$btn1'Delete' $btn3 if(a){a.focus(); document.execCommand(\"forwardDelete\");}'>Del "); $GUIButtons['assist_bksp' ] = array(3000,'','','', "$btn1'Backspace' $btn3 if(a){a.focus(); document.execCommand(\"delete\" );}'>Bksp "); $GUIButtons['assist_undo' ] = array(3000,'','','', "$btn1'Undo' $btn3 if(a){a.focus(); document.execCommand(\"undo\");}'>Undo"); $GUIButtons['assist_redo' ] = array(3000,'','','', "$btn1'Redo' $btn3 if(a){a.focus(); document.execCommand(\"redo\");}'>Redo"); $GUIButtons['assist_comment' ] = array(3000,'','','', "$btn1'Comment Selected Page Lines' onclick='modifyLines(\"comment\")' >comment "); $GUIButtons['assist_uncomment'] = array(3000,'','','', "$btn1'Uncomment Selected Page Lines' onclick='modifyLines(\"uncomment\")'>uncomment"); $GUIButtons['assist_enter' ] = array(3000,'','','', "$btn1'Enter' $btn2\"\\x0a\")' >Enter "); $GUIButtons['separator5' ] = array(3000,'','','', "$btn_sep$btn_sep_end" ); $GUIButtons['assist_copy' ] = array(3000,'','','', "$btn1'Copy' $btn3 if(a){a.focus(); document.execCommand(\"copy\" );}'>Copy "); $GUIButtons['assist_cut' ] = array(3000,'','','', "$btn1'Cut' $btn3 if(a){a.focus(); document.execCommand(\"cut\" );}'>Cut "); $GUIButtons['assist_paste' ] = array(3000,'','','', "$btn1'Paste' $btn3 if(a){a.focus(); document.execCommand(\"paste\" );}'>Paste"); $GUIButtons['separator6' ] = array(3000,'','','', "$btn_sep$btn_sep_end" ); #------------------------------------------------------------------------------------------------------------------------------------------------------------- } #---------------------------------------------------------------------------------------------------------------------------------------------------------------------