דילוג לתוכן
  • חוקי הפורום
  • פופולרי
  • לא נפתר
  • משתמשים
  • חיפוש גוגל בפורום
  • צור קשר
עיצובים
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • ברירת מחדל (ללא עיצוב (ברירת מחדל))
  • ללא עיצוב (ברירת מחדל)
כיווץ
מתמחים טופ
  1. דף הבית
  2. מחשבים וטכנולוגיה
  3. עזרה הדדית - מחשבים וטכנולוגיה
  4. סקריפט לניווט, קיפול והרחבת קטעי קוד ב-ChatGPT ו-AI Studio

סקריפט לניווט, קיפול והרחבת קטעי קוד ב-ChatGPT ו-AI Studio

מתוזמן נעוץ נעול הועבר עזרה הדדית - מחשבים וטכנולוגיה
5 פוסטים 3 כותבים 119 צפיות 5 עוקבים
  • מהישן לחדש
  • מהחדש לישן
  • הכי הרבה הצבעות
תגובה
  • תגובה כנושא
התחברו כדי לפרסם תגובה
נושא זה נמחק. רק משתמשים עם הרשאות מתאימות יוכלו לצפות בו.
  • לאציל מנותק
    לאציל מנותק
    לאצי
    כתב נערך לאחרונה על ידי לאצי
    #1

    בתור אחד שעובד די הרבה עם בכתיבת קוד עם הבינה מלאכותית (כלומר, היא כותבת בשבילי...) עצבן אותי מאוד כל פעם שהייתי מקבל קטע קוד ארוך הייתי צריך לגלול את כולו כדי להגיע לסוף. אז בס"ד פניתי (איך לא? 😉 ) לעזרת הבינה והיא יצרה לי סקריפט לטמפרמונקי שמוסיף כפתורי קיפול והרחבת בלוקי הקוד וגם אפשרות גלילה לסוף/תחילת הקוד. (יצוין, שהבעיה קיימת רק ב-ChatGPT ו-AI Studio שכן בגרוק כבר קיימים כפתורים כאלו ובקלוד הקוד נפתח בקנבס צדדי כך שזה מיותר.)

    אז מה יש לנו?

    1. כפתורים שימושיים לכל בלוק קוד:

      • מעל כל קטע קוד יופיעו שני כפתורים:
        • כפתור "קפל": לחיצה עליו תעלים את הקוד (כדי לחסוך מקום במסך), ולחיצה נוספת תחזיר אותו ותשנה את הכפתור ל"הרחב".
        • כפתור חץ למטה (↓): לחיצה עליו תקפיץ אתכם ישר לסוף של אותו קטע קוד.
      • מתחת לכל קטע קוד יופיע כפתור נוסף:
        • כפתור חץ למעלה (↑): לחיצה עליו תקפיץ אתכם חזרה להתחלה של אותו קטע קוד.
    2. קיצורי דרך במקלדת (עם Ctrl):

      • נמאס לכם להשתמש בעכבר לכל דבר? סתם שתדעו אפשר גם עם המקלדת... 😉
        • Ctrl + חץ ימינה או Ctrl + חץ שמאלה: יקפל או ירחיב את בלוק הקוד שהכי קרוב למרכז המסך שלכם, או את האחרון שקיפלתם/הרחבתם.
        • Ctrl + חץ למטה:
          • אם אתם בתחילת בלוק קוד, זה יקפיץ אתכם לסוף שלו.
          • אם אתם כבר בסוף בלוק, זה יקפיץ אתכם לסוף של הבלוק הבא אחריו (אם יש).
        • Ctrl + חץ למעלה:
          • אם אתם בסוף בלוק קוד, זה יקפיץ אתכם להתחלה שלו.
          • אם אתם כבר בהתחלה של בלוק, זה יקפיץ אתכם להתחלה של הבלוק הקודם (אם יש).
    3. עובד גם כשנוסף קוד חדש:

      • הסקריפט חכם מספיק כדי לזהות מתי ChatGPT או AI Studio מוסיפים קטעי קוד חדשים לשיחה, והוא ידאג להוסיף את הכפתורים והיכולות האלה גם אליהם באופן אוטומטי.

    בשורה התחתונה:
    הסקריפט הזה פשוט מוסיף כמה כפתורים קטנים ונוחים כדי להתמודד טוב יותר עם קטעי קוד ארוכים, לקפל אותם כשצריך, ולנווט ביניהם במהירות עם העכבר או המקלדת. לא מבין איך הסתדרתי בלעדיו עד היום...

    // ==UserScript==
    // @name         Collapsible Code Blocks with RTL, Dynamic Tooltips & Keyboard Shortcuts
    // @namespace    http://tampermonkey.net/
    // @version      1.9.6
    // @description  Adds RTL code tools with smart tooltips, keyboard shortcuts (Ctrl+Arrows for navigation/toggle), styled UI and scroll features for ChatGPT and AI Studio. Further refined navigation with multiple collapsed blocks.
    // @author       לאצי&AI
    // @match        https://chatgpt.com/*
    // @match        https://aistudio.google.com/*
    // @grant        none
    // @icon         https://img.icons8.com/ios-filled/50/programming.png
    // ==/UserScript==
    
    (function () {
        'use strict';
    
        // ... (CSS and functions: enhanceCodeBlocks, getAllEnhancedBlocksInDOM, findClosestBlock, updateNavigationStateIfNeeded - remain the same as 1.9.4 / 1.9.5) ...
        const style = document.createElement('style');
        style.textContent = `
        .code-toolbar-top,
        .code-toolbar-bottom {
            display: flex;
            gap: 6px;
            justify-content: flex-start;
            direction: rtl;
            text-align: right;
            margin: 6px 0;
        }
    
        .code-btn {
            background-color: #444;
            color: #fff;
            border: none;
            padding: 4px 8px;
            font-size: 12px;
            border-radius: 5px;
            cursor: pointer;
            transition: background-color 0.2s ease;
            position: relative;
        }
    
        .code-btn:hover {
            background-color: #666;
        }
    
        .code-btn::after {
            content: attr(data-tooltip);
            position: absolute;
            bottom: 100%;
            right: 0;
            background-color: #222;
            color: #fff;
            padding: 4px 6px;
            border-radius: 4px;
            white-space: nowrap;
            font-size: 11px;
            opacity: 0;
            pointer-events: none;
            transition: opacity 0.2s ease;
            margin-bottom: 6px;
            z-index: 9999;
            text-align: right;
        }
    
        .tooltip-below::after {
            bottom: auto;
            top: 100%;
            margin-bottom: 0;
            margin-top: 6px;
        }
    
        .code-btn:hover::after {
            opacity: 1;
        }
        `;
        document.head.appendChild(style);
    
        const enhancedBlockRegistry = [];
        let currentNavigationState = {
            blockInfo: null, 
            targetPoint: 'top'
        };
        let lastInteractedBlockForToggle = null; 
        let lastManuallyCollapsedBlock = null;
    
        function enhanceCodeBlocks() {
            const blocks = document.querySelectorAll('pre');
            blocks.forEach((block) => {
                if (block.dataset.enhanced) return;
    
                const toggleBtn = document.createElement('button');
                toggleBtn.textContent = 'קפל';
                toggleBtn.className = 'code-btn tooltip-below';
                toggleBtn.setAttribute('data-tooltip', 'הצג או הסתר את בלוק הקוד');
    
                const toBottomBtn = document.createElement('button');
                toBottomBtn.textContent = '↓';
                toBottomBtn.className = 'code-btn tooltip-below';
                toBottomBtn.setAttribute('data-tooltip', 'גלול לסוף בלוק הקוד');
    
                const toTopBtn = document.createElement('button');
                toTopBtn.textContent = '↑';
                toTopBtn.className = 'code-btn';
                toTopBtn.setAttribute('data-tooltip', 'גלול לתחילת בלוק הקוד');
    
                const toolbarTop = document.createElement('div');
                toolbarTop.className = 'code-toolbar-top';
                toolbarTop.appendChild(toggleBtn);
                toolbarTop.appendChild(toBottomBtn);
    
                const toolbarBottom = document.createElement('div');
                toolbarBottom.className = 'code-toolbar-bottom';
                toolbarBottom.appendChild(toTopBtn);
                
                const blockInfo = {
                    preElement: block,
                    toolbarTopElement: toolbarTop,
                    toolbarBottomElement: toolbarBottom,
                    toggleButtonElement: toggleBtn,
                    id: `enhanced-block-${enhancedBlockRegistry.length}`
                };
    
                toggleBtn.addEventListener('click', () => {
                    const visible = block.style.display !== 'none';
                    block.style.display = visible ? 'none' : 'block';
                    toggleBtn.textContent = visible ? 'הרחב' : 'קפל';
                    if (!visible) { // Block was just expanded
                        if (lastManuallyCollapsedBlock && lastManuallyCollapsedBlock.id === blockInfo.id) {
                            lastManuallyCollapsedBlock = null; 
                        }
                    }
                    // Note: lastManuallyCollapsedBlock is primarily set via keydown for intent.
                });
    
                toBottomBtn.addEventListener('click', () => {
                    toolbarBottom.scrollIntoView({ behavior: 'smooth', block: 'center' });
                });
    
                toTopBtn.addEventListener('click', () => {
                    toolbarTop.scrollIntoView({ behavior: 'smooth', block: 'center' });
                });
    
                if (block.parentNode) {
                    block.parentNode.insertBefore(toolbarTop, block);
                    block.parentNode.insertBefore(toolbarBottom, block.nextSibling);
                }
    
                enhancedBlockRegistry.push(blockInfo);
                block.dataset.enhanced = "true";
                block.dataset.blockId = blockInfo.id;
            });
        }
    
        function getAllEnhancedBlocksInDOM() {
            // Ensure this list is always up-to-date with the DOM order
            // This might need re-evaluation if blocks can be reordered in the DOM by other means
            const livePreElements = Array.from(document.querySelectorAll('pre[data-enhanced="true"]'));
            return livePreElements.map(pre => {
                const foundInfo = enhancedBlockRegistry.find(info => info.id === pre.dataset.blockId);
                return foundInfo; // Should always find it if registry is in sync
            }).filter(Boolean); // Filter out any undefined if a pre was removed weirdly
        }
    
    
        function findClosestBlock(blocksToSearch, includeCollapsed = false) {
            if (!blocksToSearch || blocksToSearch.length === 0) return null;
            let closestBlockInfo = null;
            let minDistance = Infinity;
            const viewportCenterY = window.innerHeight / 2;
    
            blocksToSearch.forEach(blockInfo => {
                if(!blockInfo) return; // Safety check
                const preElement = blockInfo.preElement;
                if (!includeCollapsed && preElement.style.display === 'none') return;
                const elementForLocation = preElement.style.display === 'none' ? blockInfo.toolbarTopElement : preElement;
                if (!elementForLocation || !document.body.contains(elementForLocation)) return;
                const rect = elementForLocation.getBoundingClientRect();
                if (rect.bottom > 0 && rect.top < window.innerHeight) {
                    const elementCenterY = rect.top + rect.height / 2;
                    const distance = Math.abs(elementCenterY - viewportCenterY);
                    if (distance < minDistance) {
                        minDistance = distance;
                        closestBlockInfo = blockInfo;
                    }
                }
            });
            return closestBlockInfo;
        }
    
        function updateNavigationStateIfNeeded(purpose = 'navigation') {
            const allDomBlocks = getAllEnhancedBlocksInDOM(); // This now reflects current DOM order
            if (allDomBlocks.length === 0) {
                currentNavigationState.blockInfo = null;
                if (lastInteractedBlockForToggle && !document.body.contains(lastInteractedBlockForToggle.preElement)) lastInteractedBlockForToggle = null;
                if (lastManuallyCollapsedBlock && !document.body.contains(lastManuallyCollapsedBlock.preElement)) lastManuallyCollapsedBlock = null;
                return { allBlocks: [], visibleBlocks: [] };
            }
    
            let blockToFocus = null;
            let visibleBlocks = allDomBlocks.filter(b => b.preElement.style.display !== 'none');
    
            if (purpose === 'toggle') {
                if (lastInteractedBlockForToggle && document.body.contains(lastInteractedBlockForToggle.preElement)) {
                    blockToFocus = allDomBlocks.find(b => b.id === lastInteractedBlockForToggle.id);
                }
                if (!blockToFocus) {
                    blockToFocus = findClosestBlock(allDomBlocks, true);
                }
            } else { 
                let currentNavBlockId = currentNavigationState.blockInfo?.id;
                const currentBlockFromAll = currentNavBlockId ? allDomBlocks.find(b => b.id === currentNavBlockId) : null;
    
                if (currentBlockFromAll && currentBlockFromAll.preElement.style.display !== 'none') {
                    blockToFocus = currentBlockFromAll;
                } else if (lastManuallyCollapsedBlock && document.body.contains(lastManuallyCollapsedBlock.preElement) && lastManuallyCollapsedBlock.preElement.style.display === 'none' && currentBlockFromAll && currentBlockFromAll.id === lastManuallyCollapsedBlock.id) {
                    blockToFocus = currentBlockFromAll;
                }
                else {
                    blockToFocus = findClosestBlock(visibleBlocks, false);
                }
    
                if (!blockToFocus && visibleBlocks.length > 0) {
                    blockToFocus = visibleBlocks[0];
                } else if (!blockToFocus && lastManuallyCollapsedBlock && lastManuallyCollapsedBlock.preElement.style.display === 'none') {
                    blockToFocus = allDomBlocks.find(b => b.id === lastManuallyCollapsedBlock.id);
                }
    
    
                if (blockToFocus && blockToFocus.preElement.style.display !== 'none' && (!currentNavigationState.blockInfo || blockToFocus.id !== currentNavigationState.blockInfo.id) ) {
                    const rect = blockToFocus.preElement.getBoundingClientRect();
                    currentNavigationState.targetPoint = (rect.height > 0 && Math.abs(rect.top - window.innerHeight / 2) < Math.abs(rect.bottom - window.innerHeight / 2)) ? 'top' : 'bottom';
                } else if (!blockToFocus) {
                    currentNavigationState.blockInfo = null;
                }
            }
            currentNavigationState.blockInfo = blockToFocus;
            return { allBlocks: allDomBlocks, visibleBlocks: visibleBlocks };
        }
    
        document.addEventListener('keydown', function (event) {
            if (!event.ctrlKey) return;
    
            const { allBlocks, visibleBlocks } = updateNavigationStateIfNeeded(event.key === 'ArrowLeft' || event.key === 'ArrowRight' ? 'toggle' : 'navigation');
            let currentBlockForNav = currentNavigationState.blockInfo;
    
            switch (event.key) {
                case 'ArrowLeft':
                case 'ArrowRight':
                    event.preventDefault();
                    if (currentBlockForNav) {
                        currentBlockForNav.toggleButtonElement.click(); 
                        lastInteractedBlockForToggle = currentBlockForNav;
                        if (currentBlockForNav.preElement.style.display === 'none') { 
                            lastManuallyCollapsedBlock = currentBlockForNav; 
                        } else { 
                            if (lastManuallyCollapsedBlock && lastManuallyCollapsedBlock.id === currentBlockForNav.id) {
                                lastManuallyCollapsedBlock = null; 
                            }
                        }
                    }
                    break;
    
                case 'ArrowDown':
                    event.preventDefault();
                    if (!currentBlockForNav) { 
                        currentBlockForNav = visibleBlocks.length > 0 ? visibleBlocks[0] : (lastManuallyCollapsedBlock && lastManuallyCollapsedBlock.preElement.style.display === 'none' ? allBlocks.find(b => b.id === lastManuallyCollapsedBlock.id) : null);
                        if (!currentBlockForNav) break;
                        currentNavigationState.blockInfo = currentBlockForNav; 
                        currentNavigationState.targetPoint = (currentBlockForNav.preElement.style.display === 'none') ? 'top' : 'top';
                    }
    
                    if (currentBlockForNav.preElement.style.display !== 'none' && currentNavigationState.targetPoint === 'top') {
                        currentBlockForNav.toolbarBottomElement.scrollIntoView({ behavior: 'smooth', block: 'center' });
                        currentNavigationState.targetPoint = 'bottom';
                    } else {
                        const currentBlockIndexInFullList = allBlocks.findIndex(b => b.id === currentBlockForNav.id);
                        let nextTargetBlock = null;
    
                        for (let i = currentBlockIndexInFullList + 1; i < allBlocks.length; i++) {
                            const potentialTarget = allBlocks[i];
                            if (lastManuallyCollapsedBlock && potentialTarget.id === lastManuallyCollapsedBlock.id && potentialTarget.preElement.style.display === 'none') {
                                nextTargetBlock = potentialTarget;
                                break; 
                            }
                            if (potentialTarget.preElement.style.display !== 'none') {
                                nextTargetBlock = potentialTarget;
                                break; 
                            }
                        }
                        
                        if (nextTargetBlock) {
                            currentNavigationState.blockInfo = nextTargetBlock;
                            const targetElementForScroll = nextTargetBlock.preElement.style.display === 'none' ? nextTargetBlock.toolbarTopElement : nextTargetBlock.toolbarBottomElement;
                            const scrollTargetPoint = nextTargetBlock.preElement.style.display === 'none' ? 'top' : 'bottom';
                            targetElementForScroll.scrollIntoView({ behavior: 'smooth', block: 'center' });
                            currentNavigationState.targetPoint = scrollTargetPoint;
                            if (nextTargetBlock.preElement.style.display === 'none') {
                                lastInteractedBlockForToggle = nextTargetBlock;
                            } else {
                                lastInteractedBlockForToggle = null;
                            }
                        }
                    }
                    break;
    
                case 'ArrowUp':
                    event.preventDefault();
                    if (!currentBlockForNav) {
                        currentBlockForNav = visibleBlocks.length > 0 ? visibleBlocks[visibleBlocks.length - 1] : (lastManuallyCollapsedBlock && lastManuallyCollapsedBlock.preElement.style.display === 'none' ? allBlocks.find(b => b.id === lastManuallyCollapsedBlock.id) : null);
                        if (!currentBlockForNav) break;
                        currentNavigationState.blockInfo = currentBlockForNav;
                        currentNavigationState.targetPoint = (currentBlockForNav.preElement.style.display === 'none') ? 'bottom' : 'bottom';
                    }
    
                    if (currentBlockForNav.preElement.style.display !== 'none' && currentNavigationState.targetPoint === 'bottom') {
                        currentBlockForNav.toolbarTopElement.scrollIntoView({ behavior: 'smooth', block: 'center' });
                        currentNavigationState.targetPoint = 'top';
                    } else {
                        const currentBlockIndexInFullList = allBlocks.findIndex(b => b.id === currentBlockForNav.id);
                        let prevTargetBlock = null;
    
                        for (let i = currentBlockIndexInFullList - 1; i >= 0; i--) {
                            const potentialTarget = allBlocks[i];
                            if (lastManuallyCollapsedBlock && potentialTarget.id === lastManuallyCollapsedBlock.id && potentialTarget.preElement.style.display === 'none') {
                                prevTargetBlock = potentialTarget;
                                break; 
                            }
                            if (potentialTarget.preElement.style.display !== 'none') {
                                prevTargetBlock = potentialTarget;
                                break; 
                            }
                        }
                        
                        if (prevTargetBlock) {
                            currentNavigationState.blockInfo = prevTargetBlock;
                            prevTargetBlock.toolbarTopElement.scrollIntoView({ behavior: 'smooth', block: 'center' });
                            currentNavigationState.targetPoint = 'top';
                            if (prevTargetBlock.preElement.style.display === 'none') {
                                lastInteractedBlockForToggle = prevTargetBlock;
                            } else {
                                lastInteractedBlockForToggle = null;
                            }
                        }
                    }
                    break;
            }
        });
    
        const observer = new MutationObserver(() => {
            enhanceCodeBlocks();
            // Potentially re-validate currentNavigationState if DOM changes significantly
            // For now, rely on keydown to re-evaluate.
        });
        observer.observe(document.body, { childList: true, subtree: true });
    
        enhanceCodeBlocks();
        updateNavigationStateIfNeeded('navigation');
    })();
    

    קיים באג קטן בניווט בין קטעי הקוד באמצעות מקשי הקיצור, כשחלק מהבלוקים מקופלים הוא עלול לדלג עליהם.
    כמו"כ אשמח אם מישהו יוכל לשפר את הקוד כך שהכפתורים יהיו דביקים ויופיעו כל הזמן לאורך כל הגלילה בבלוק הקוד הנוכחי, כך שיהיו זמינים כל הזמן. כמובן שבמקרה כזה כל הכפתורים צריכים להופיע בשורה אחת ולא בשני שורות נפרדות כמו עכשיו.

    יום חדש מתחילי תגובה 1 תגובה אחרונה
    9
    • לאציל לאצי

      בתור אחד שעובד די הרבה עם בכתיבת קוד עם הבינה מלאכותית (כלומר, היא כותבת בשבילי...) עצבן אותי מאוד כל פעם שהייתי מקבל קטע קוד ארוך הייתי צריך לגלול את כולו כדי להגיע לסוף. אז בס"ד פניתי (איך לא? 😉 ) לעזרת הבינה והיא יצרה לי סקריפט לטמפרמונקי שמוסיף כפתורי קיפול והרחבת בלוקי הקוד וגם אפשרות גלילה לסוף/תחילת הקוד. (יצוין, שהבעיה קיימת רק ב-ChatGPT ו-AI Studio שכן בגרוק כבר קיימים כפתורים כאלו ובקלוד הקוד נפתח בקנבס צדדי כך שזה מיותר.)

      אז מה יש לנו?

      1. כפתורים שימושיים לכל בלוק קוד:

        • מעל כל קטע קוד יופיעו שני כפתורים:
          • כפתור "קפל": לחיצה עליו תעלים את הקוד (כדי לחסוך מקום במסך), ולחיצה נוספת תחזיר אותו ותשנה את הכפתור ל"הרחב".
          • כפתור חץ למטה (↓): לחיצה עליו תקפיץ אתכם ישר לסוף של אותו קטע קוד.
        • מתחת לכל קטע קוד יופיע כפתור נוסף:
          • כפתור חץ למעלה (↑): לחיצה עליו תקפיץ אתכם חזרה להתחלה של אותו קטע קוד.
      2. קיצורי דרך במקלדת (עם Ctrl):

        • נמאס לכם להשתמש בעכבר לכל דבר? סתם שתדעו אפשר גם עם המקלדת... 😉
          • Ctrl + חץ ימינה או Ctrl + חץ שמאלה: יקפל או ירחיב את בלוק הקוד שהכי קרוב למרכז המסך שלכם, או את האחרון שקיפלתם/הרחבתם.
          • Ctrl + חץ למטה:
            • אם אתם בתחילת בלוק קוד, זה יקפיץ אתכם לסוף שלו.
            • אם אתם כבר בסוף בלוק, זה יקפיץ אתכם לסוף של הבלוק הבא אחריו (אם יש).
          • Ctrl + חץ למעלה:
            • אם אתם בסוף בלוק קוד, זה יקפיץ אתכם להתחלה שלו.
            • אם אתם כבר בהתחלה של בלוק, זה יקפיץ אתכם להתחלה של הבלוק הקודם (אם יש).
      3. עובד גם כשנוסף קוד חדש:

        • הסקריפט חכם מספיק כדי לזהות מתי ChatGPT או AI Studio מוסיפים קטעי קוד חדשים לשיחה, והוא ידאג להוסיף את הכפתורים והיכולות האלה גם אליהם באופן אוטומטי.

      בשורה התחתונה:
      הסקריפט הזה פשוט מוסיף כמה כפתורים קטנים ונוחים כדי להתמודד טוב יותר עם קטעי קוד ארוכים, לקפל אותם כשצריך, ולנווט ביניהם במהירות עם העכבר או המקלדת. לא מבין איך הסתדרתי בלעדיו עד היום...

      // ==UserScript==
      // @name         Collapsible Code Blocks with RTL, Dynamic Tooltips & Keyboard Shortcuts
      // @namespace    http://tampermonkey.net/
      // @version      1.9.6
      // @description  Adds RTL code tools with smart tooltips, keyboard shortcuts (Ctrl+Arrows for navigation/toggle), styled UI and scroll features for ChatGPT and AI Studio. Further refined navigation with multiple collapsed blocks.
      // @author       לאצי&AI
      // @match        https://chatgpt.com/*
      // @match        https://aistudio.google.com/*
      // @grant        none
      // @icon         https://img.icons8.com/ios-filled/50/programming.png
      // ==/UserScript==
      
      (function () {
          'use strict';
      
          // ... (CSS and functions: enhanceCodeBlocks, getAllEnhancedBlocksInDOM, findClosestBlock, updateNavigationStateIfNeeded - remain the same as 1.9.4 / 1.9.5) ...
          const style = document.createElement('style');
          style.textContent = `
          .code-toolbar-top,
          .code-toolbar-bottom {
              display: flex;
              gap: 6px;
              justify-content: flex-start;
              direction: rtl;
              text-align: right;
              margin: 6px 0;
          }
      
          .code-btn {
              background-color: #444;
              color: #fff;
              border: none;
              padding: 4px 8px;
              font-size: 12px;
              border-radius: 5px;
              cursor: pointer;
              transition: background-color 0.2s ease;
              position: relative;
          }
      
          .code-btn:hover {
              background-color: #666;
          }
      
          .code-btn::after {
              content: attr(data-tooltip);
              position: absolute;
              bottom: 100%;
              right: 0;
              background-color: #222;
              color: #fff;
              padding: 4px 6px;
              border-radius: 4px;
              white-space: nowrap;
              font-size: 11px;
              opacity: 0;
              pointer-events: none;
              transition: opacity 0.2s ease;
              margin-bottom: 6px;
              z-index: 9999;
              text-align: right;
          }
      
          .tooltip-below::after {
              bottom: auto;
              top: 100%;
              margin-bottom: 0;
              margin-top: 6px;
          }
      
          .code-btn:hover::after {
              opacity: 1;
          }
          `;
          document.head.appendChild(style);
      
          const enhancedBlockRegistry = [];
          let currentNavigationState = {
              blockInfo: null, 
              targetPoint: 'top'
          };
          let lastInteractedBlockForToggle = null; 
          let lastManuallyCollapsedBlock = null;
      
          function enhanceCodeBlocks() {
              const blocks = document.querySelectorAll('pre');
              blocks.forEach((block) => {
                  if (block.dataset.enhanced) return;
      
                  const toggleBtn = document.createElement('button');
                  toggleBtn.textContent = 'קפל';
                  toggleBtn.className = 'code-btn tooltip-below';
                  toggleBtn.setAttribute('data-tooltip', 'הצג או הסתר את בלוק הקוד');
      
                  const toBottomBtn = document.createElement('button');
                  toBottomBtn.textContent = '↓';
                  toBottomBtn.className = 'code-btn tooltip-below';
                  toBottomBtn.setAttribute('data-tooltip', 'גלול לסוף בלוק הקוד');
      
                  const toTopBtn = document.createElement('button');
                  toTopBtn.textContent = '↑';
                  toTopBtn.className = 'code-btn';
                  toTopBtn.setAttribute('data-tooltip', 'גלול לתחילת בלוק הקוד');
      
                  const toolbarTop = document.createElement('div');
                  toolbarTop.className = 'code-toolbar-top';
                  toolbarTop.appendChild(toggleBtn);
                  toolbarTop.appendChild(toBottomBtn);
      
                  const toolbarBottom = document.createElement('div');
                  toolbarBottom.className = 'code-toolbar-bottom';
                  toolbarBottom.appendChild(toTopBtn);
                  
                  const blockInfo = {
                      preElement: block,
                      toolbarTopElement: toolbarTop,
                      toolbarBottomElement: toolbarBottom,
                      toggleButtonElement: toggleBtn,
                      id: `enhanced-block-${enhancedBlockRegistry.length}`
                  };
      
                  toggleBtn.addEventListener('click', () => {
                      const visible = block.style.display !== 'none';
                      block.style.display = visible ? 'none' : 'block';
                      toggleBtn.textContent = visible ? 'הרחב' : 'קפל';
                      if (!visible) { // Block was just expanded
                          if (lastManuallyCollapsedBlock && lastManuallyCollapsedBlock.id === blockInfo.id) {
                              lastManuallyCollapsedBlock = null; 
                          }
                      }
                      // Note: lastManuallyCollapsedBlock is primarily set via keydown for intent.
                  });
      
                  toBottomBtn.addEventListener('click', () => {
                      toolbarBottom.scrollIntoView({ behavior: 'smooth', block: 'center' });
                  });
      
                  toTopBtn.addEventListener('click', () => {
                      toolbarTop.scrollIntoView({ behavior: 'smooth', block: 'center' });
                  });
      
                  if (block.parentNode) {
                      block.parentNode.insertBefore(toolbarTop, block);
                      block.parentNode.insertBefore(toolbarBottom, block.nextSibling);
                  }
      
                  enhancedBlockRegistry.push(blockInfo);
                  block.dataset.enhanced = "true";
                  block.dataset.blockId = blockInfo.id;
              });
          }
      
          function getAllEnhancedBlocksInDOM() {
              // Ensure this list is always up-to-date with the DOM order
              // This might need re-evaluation if blocks can be reordered in the DOM by other means
              const livePreElements = Array.from(document.querySelectorAll('pre[data-enhanced="true"]'));
              return livePreElements.map(pre => {
                  const foundInfo = enhancedBlockRegistry.find(info => info.id === pre.dataset.blockId);
                  return foundInfo; // Should always find it if registry is in sync
              }).filter(Boolean); // Filter out any undefined if a pre was removed weirdly
          }
      
      
          function findClosestBlock(blocksToSearch, includeCollapsed = false) {
              if (!blocksToSearch || blocksToSearch.length === 0) return null;
              let closestBlockInfo = null;
              let minDistance = Infinity;
              const viewportCenterY = window.innerHeight / 2;
      
              blocksToSearch.forEach(blockInfo => {
                  if(!blockInfo) return; // Safety check
                  const preElement = blockInfo.preElement;
                  if (!includeCollapsed && preElement.style.display === 'none') return;
                  const elementForLocation = preElement.style.display === 'none' ? blockInfo.toolbarTopElement : preElement;
                  if (!elementForLocation || !document.body.contains(elementForLocation)) return;
                  const rect = elementForLocation.getBoundingClientRect();
                  if (rect.bottom > 0 && rect.top < window.innerHeight) {
                      const elementCenterY = rect.top + rect.height / 2;
                      const distance = Math.abs(elementCenterY - viewportCenterY);
                      if (distance < minDistance) {
                          minDistance = distance;
                          closestBlockInfo = blockInfo;
                      }
                  }
              });
              return closestBlockInfo;
          }
      
          function updateNavigationStateIfNeeded(purpose = 'navigation') {
              const allDomBlocks = getAllEnhancedBlocksInDOM(); // This now reflects current DOM order
              if (allDomBlocks.length === 0) {
                  currentNavigationState.blockInfo = null;
                  if (lastInteractedBlockForToggle && !document.body.contains(lastInteractedBlockForToggle.preElement)) lastInteractedBlockForToggle = null;
                  if (lastManuallyCollapsedBlock && !document.body.contains(lastManuallyCollapsedBlock.preElement)) lastManuallyCollapsedBlock = null;
                  return { allBlocks: [], visibleBlocks: [] };
              }
      
              let blockToFocus = null;
              let visibleBlocks = allDomBlocks.filter(b => b.preElement.style.display !== 'none');
      
              if (purpose === 'toggle') {
                  if (lastInteractedBlockForToggle && document.body.contains(lastInteractedBlockForToggle.preElement)) {
                      blockToFocus = allDomBlocks.find(b => b.id === lastInteractedBlockForToggle.id);
                  }
                  if (!blockToFocus) {
                      blockToFocus = findClosestBlock(allDomBlocks, true);
                  }
              } else { 
                  let currentNavBlockId = currentNavigationState.blockInfo?.id;
                  const currentBlockFromAll = currentNavBlockId ? allDomBlocks.find(b => b.id === currentNavBlockId) : null;
      
                  if (currentBlockFromAll && currentBlockFromAll.preElement.style.display !== 'none') {
                      blockToFocus = currentBlockFromAll;
                  } else if (lastManuallyCollapsedBlock && document.body.contains(lastManuallyCollapsedBlock.preElement) && lastManuallyCollapsedBlock.preElement.style.display === 'none' && currentBlockFromAll && currentBlockFromAll.id === lastManuallyCollapsedBlock.id) {
                      blockToFocus = currentBlockFromAll;
                  }
                  else {
                      blockToFocus = findClosestBlock(visibleBlocks, false);
                  }
      
                  if (!blockToFocus && visibleBlocks.length > 0) {
                      blockToFocus = visibleBlocks[0];
                  } else if (!blockToFocus && lastManuallyCollapsedBlock && lastManuallyCollapsedBlock.preElement.style.display === 'none') {
                      blockToFocus = allDomBlocks.find(b => b.id === lastManuallyCollapsedBlock.id);
                  }
      
      
                  if (blockToFocus && blockToFocus.preElement.style.display !== 'none' && (!currentNavigationState.blockInfo || blockToFocus.id !== currentNavigationState.blockInfo.id) ) {
                      const rect = blockToFocus.preElement.getBoundingClientRect();
                      currentNavigationState.targetPoint = (rect.height > 0 && Math.abs(rect.top - window.innerHeight / 2) < Math.abs(rect.bottom - window.innerHeight / 2)) ? 'top' : 'bottom';
                  } else if (!blockToFocus) {
                      currentNavigationState.blockInfo = null;
                  }
              }
              currentNavigationState.blockInfo = blockToFocus;
              return { allBlocks: allDomBlocks, visibleBlocks: visibleBlocks };
          }
      
          document.addEventListener('keydown', function (event) {
              if (!event.ctrlKey) return;
      
              const { allBlocks, visibleBlocks } = updateNavigationStateIfNeeded(event.key === 'ArrowLeft' || event.key === 'ArrowRight' ? 'toggle' : 'navigation');
              let currentBlockForNav = currentNavigationState.blockInfo;
      
              switch (event.key) {
                  case 'ArrowLeft':
                  case 'ArrowRight':
                      event.preventDefault();
                      if (currentBlockForNav) {
                          currentBlockForNav.toggleButtonElement.click(); 
                          lastInteractedBlockForToggle = currentBlockForNav;
                          if (currentBlockForNav.preElement.style.display === 'none') { 
                              lastManuallyCollapsedBlock = currentBlockForNav; 
                          } else { 
                              if (lastManuallyCollapsedBlock && lastManuallyCollapsedBlock.id === currentBlockForNav.id) {
                                  lastManuallyCollapsedBlock = null; 
                              }
                          }
                      }
                      break;
      
                  case 'ArrowDown':
                      event.preventDefault();
                      if (!currentBlockForNav) { 
                          currentBlockForNav = visibleBlocks.length > 0 ? visibleBlocks[0] : (lastManuallyCollapsedBlock && lastManuallyCollapsedBlock.preElement.style.display === 'none' ? allBlocks.find(b => b.id === lastManuallyCollapsedBlock.id) : null);
                          if (!currentBlockForNav) break;
                          currentNavigationState.blockInfo = currentBlockForNav; 
                          currentNavigationState.targetPoint = (currentBlockForNav.preElement.style.display === 'none') ? 'top' : 'top';
                      }
      
                      if (currentBlockForNav.preElement.style.display !== 'none' && currentNavigationState.targetPoint === 'top') {
                          currentBlockForNav.toolbarBottomElement.scrollIntoView({ behavior: 'smooth', block: 'center' });
                          currentNavigationState.targetPoint = 'bottom';
                      } else {
                          const currentBlockIndexInFullList = allBlocks.findIndex(b => b.id === currentBlockForNav.id);
                          let nextTargetBlock = null;
      
                          for (let i = currentBlockIndexInFullList + 1; i < allBlocks.length; i++) {
                              const potentialTarget = allBlocks[i];
                              if (lastManuallyCollapsedBlock && potentialTarget.id === lastManuallyCollapsedBlock.id && potentialTarget.preElement.style.display === 'none') {
                                  nextTargetBlock = potentialTarget;
                                  break; 
                              }
                              if (potentialTarget.preElement.style.display !== 'none') {
                                  nextTargetBlock = potentialTarget;
                                  break; 
                              }
                          }
                          
                          if (nextTargetBlock) {
                              currentNavigationState.blockInfo = nextTargetBlock;
                              const targetElementForScroll = nextTargetBlock.preElement.style.display === 'none' ? nextTargetBlock.toolbarTopElement : nextTargetBlock.toolbarBottomElement;
                              const scrollTargetPoint = nextTargetBlock.preElement.style.display === 'none' ? 'top' : 'bottom';
                              targetElementForScroll.scrollIntoView({ behavior: 'smooth', block: 'center' });
                              currentNavigationState.targetPoint = scrollTargetPoint;
                              if (nextTargetBlock.preElement.style.display === 'none') {
                                  lastInteractedBlockForToggle = nextTargetBlock;
                              } else {
                                  lastInteractedBlockForToggle = null;
                              }
                          }
                      }
                      break;
      
                  case 'ArrowUp':
                      event.preventDefault();
                      if (!currentBlockForNav) {
                          currentBlockForNav = visibleBlocks.length > 0 ? visibleBlocks[visibleBlocks.length - 1] : (lastManuallyCollapsedBlock && lastManuallyCollapsedBlock.preElement.style.display === 'none' ? allBlocks.find(b => b.id === lastManuallyCollapsedBlock.id) : null);
                          if (!currentBlockForNav) break;
                          currentNavigationState.blockInfo = currentBlockForNav;
                          currentNavigationState.targetPoint = (currentBlockForNav.preElement.style.display === 'none') ? 'bottom' : 'bottom';
                      }
      
                      if (currentBlockForNav.preElement.style.display !== 'none' && currentNavigationState.targetPoint === 'bottom') {
                          currentBlockForNav.toolbarTopElement.scrollIntoView({ behavior: 'smooth', block: 'center' });
                          currentNavigationState.targetPoint = 'top';
                      } else {
                          const currentBlockIndexInFullList = allBlocks.findIndex(b => b.id === currentBlockForNav.id);
                          let prevTargetBlock = null;
      
                          for (let i = currentBlockIndexInFullList - 1; i >= 0; i--) {
                              const potentialTarget = allBlocks[i];
                              if (lastManuallyCollapsedBlock && potentialTarget.id === lastManuallyCollapsedBlock.id && potentialTarget.preElement.style.display === 'none') {
                                  prevTargetBlock = potentialTarget;
                                  break; 
                              }
                              if (potentialTarget.preElement.style.display !== 'none') {
                                  prevTargetBlock = potentialTarget;
                                  break; 
                              }
                          }
                          
                          if (prevTargetBlock) {
                              currentNavigationState.blockInfo = prevTargetBlock;
                              prevTargetBlock.toolbarTopElement.scrollIntoView({ behavior: 'smooth', block: 'center' });
                              currentNavigationState.targetPoint = 'top';
                              if (prevTargetBlock.preElement.style.display === 'none') {
                                  lastInteractedBlockForToggle = prevTargetBlock;
                              } else {
                                  lastInteractedBlockForToggle = null;
                              }
                          }
                      }
                      break;
              }
          });
      
          const observer = new MutationObserver(() => {
              enhanceCodeBlocks();
              // Potentially re-validate currentNavigationState if DOM changes significantly
              // For now, rely on keydown to re-evaluate.
          });
          observer.observe(document.body, { childList: true, subtree: true });
      
          enhanceCodeBlocks();
          updateNavigationStateIfNeeded('navigation');
      })();
      

      קיים באג קטן בניווט בין קטעי הקוד באמצעות מקשי הקיצור, כשחלק מהבלוקים מקופלים הוא עלול לדלג עליהם.
      כמו"כ אשמח אם מישהו יוכל לשפר את הקוד כך שהכפתורים יהיו דביקים ויופיעו כל הזמן לאורך כל הגלילה בבלוק הקוד הנוכחי, כך שיהיו זמינים כל הזמן. כמובן שבמקרה כזה כל הכפתורים צריכים להופיע בשורה אחת ולא בשני שורות נפרדות כמו עכשיו.

      יום חדש מתחילי מנותק
      יום חדש מתחילי מנותק
      יום חדש מתחיל
      כתב נערך לאחרונה על ידי
      #2

      @לאצי גם ב GPT יש אפשרות לקנבס

      לאציל תגובה 1 תגובה אחרונה
      2
      • יום חדש מתחילי יום חדש מתחיל

        @לאצי גם ב GPT יש אפשרות לקנבס

        לאציל מנותק
        לאציל מנותק
        לאצי
        כתב נערך לאחרונה על ידי
        #3

        @יום-חדש-מתחיל ידוע לי, אבל אני לא אוהב להשתמש אתו כי הוא מחליף לי כל קוד בקוד הקודם. לדוג' אם אני צריך שני קודים שונים אז את הקוד השני הוא כותב ע"ג אותו קנבס של הקוד הראשון ומוחק את הראשון. מה שקצת מסבך את העניינים.

        ע תגובה 1 תגובה אחרונה
        0
        • לאציל לאצי

          @יום-חדש-מתחיל ידוע לי, אבל אני לא אוהב להשתמש אתו כי הוא מחליף לי כל קוד בקוד הקודם. לדוג' אם אני צריך שני קודים שונים אז את הקוד השני הוא כותב ע"ג אותו קנבס של הקוד הראשון ומוחק את הראשון. מה שקצת מסבך את העניינים.

          ע מנותק
          ע מנותק
          ע"ה דכו"ע
          כתב נערך לאחרונה על ידי
          #4

          @לאצי כתב בסקריפט לניווט, קיפול והרחבת קטעי קוד ב-ChatGPT ו-AI Studio:

          @יום-חדש-מתחיל ידוע לי, אבל אני לא אוהב להשתמש אתו כי הוא מחליף לי כל קוד בקוד הקודם. לדוג' אם אני צריך שני קודים שונים אז את הקוד השני הוא כותב ע"ג אותו קנבס של הקוד הראשון ומוחק את הראשון. מה שקצת מסבך את העניינים.

          יש אפשרות לחזור לגירסאות קודמות.

          כמובן זה עדיין מסבך מאוד, רק אני מקווה שאתה מודע לאפשרות הזו.

          לאציל תגובה 1 תגובה אחרונה
          0
          • ע ע"ה דכו"ע

            @לאצי כתב בסקריפט לניווט, קיפול והרחבת קטעי קוד ב-ChatGPT ו-AI Studio:

            @יום-חדש-מתחיל ידוע לי, אבל אני לא אוהב להשתמש אתו כי הוא מחליף לי כל קוד בקוד הקודם. לדוג' אם אני צריך שני קודים שונים אז את הקוד השני הוא כותב ע"ג אותו קנבס של הקוד הראשון ומוחק את הראשון. מה שקצת מסבך את העניינים.

            יש אפשרות לחזור לגירסאות קודמות.

            כמובן זה עדיין מסבך מאוד, רק אני מקווה שאתה מודע לאפשרות הזו.

            לאציל מנותק
            לאציל מנותק
            לאצי
            כתב נערך לאחרונה על ידי
            #5

            @ע-ה-דכו-ע כן, מודע. אבל כדבריך;

            @ע-ה-דכו-ע כתב בסקריפט לניווט, קיפול והרחבת קטעי קוד ב-ChatGPT ו-AI Studio:

            זה עדיין מסבך מאוד

            תגובה 1 תגובה אחרונה
            1

            • התחברות

            • אין לך חשבון עדיין? הרשמה

            • התחברו או הירשמו כדי לחפש.
            • פוסט ראשון
              פוסט אחרון
            0
            • חוקי הפורום
            • פופולרי
            • לא נפתר
            • משתמשים
            • חיפוש גוגל בפורום
            • צור קשר