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

תחומים - פורום חרדי מקצועי

💡 רוצה לזכור קריאת שמע בזמן? לחץ כאן!
pcinfogmachP

pcinfogmach

@pcinfogmach
אודות
פוסטים
647
נושאים
175
קבוצות
0
עוקבים
3
עוקב אחרי
1

פוסטים

פוסטים אחרונים הגבוה ביותר שנוי במחלוקת

  • תוסף חיפוש רגקס בוורד
    pcinfogmachP pcinfogmach

    עקב המגבלות של החיפוש הרגיל בוורד וגם החיפוש עם תוים כלליים, פיתחתי תוסף לחיפוש בוורד באמצעות רגקס. (למשל, בחיפוש המובנה של וורד אין אפשרות לחפש אפס או יותר מופעים).

    חשוב לזכור: חיפוש באמצעות רגקס אינו "עצל" כמו החיפוש הרגיל של וורד!
    מצו"ב לינק עם מדריך יפה כיצד לערוך חיפוש רגקס:
    https://tchumim.com/post/10185

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

    להורדה לחץ כאן:
    https://github.com/pcinfogmach/RegexInWordPublish/releases
    מדריך וסקירה של התוסף לחץ כאן
    https://tchumim.com/assets/uploads/files/1745951333924-regexinword-userguide.dotm

    RegexInWord.jpg


  • תורת אמת בוורד - עכשיו בvsto
    pcinfogmachP pcinfogmach

    תוסף חדש לוורד - תורת אמת בוורד
    המאגר התורני החינמי בתוך וורד
    להורדת התוסף לחץ כאן
    לפני החילוץ של הקובץ לחץ לחיצה ימנית על הקובץ והסר חסימה אינטרנטית
    באפשרויות הקובץ

    כדי להשתמש בתוסף יש להתקין את תורת אמת במחשב. להריץ את התוכנה כמנהל מערכת לכה"פ פעם אחת.

    תודה מיוחדת ל:
    @האדם-החושב
    @dovid
    שעזרו רבות בבניית התוסף.

    הערה: קיצור מקשים Cntrl + T אמור להעביר את הפוקוס חזרה למסמך הפתוח (לא תמיד עובד תלוי אם הפוקוס באמת נמצא בתוך התוסף או לא).

    9c37f203-9f65-4ccb-9068-07de894625b4-e608d29f-2af6-4c0c-9b13-1df6a06e4408-image.png
    51bd67fe-11e9-4e97-8065-094c743852e7-d740219e-d027-401c-813f-3f7b2c3f070b-image.png
    c195b348-15d4-4c4b-9169-6ea38a38fafc-86d02530-38cc-414b-ae1f-6ad53e4667a8-image.png


  • תוסף חדש - תורת אמת בוורד
    pcinfogmachP pcinfogmach

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

    2b5099c8-64c7-4093-b2f6-a6355cfbf12f-image.png

    לעת עתה יש עדיין קצת בעיה מצד החזות של המסמכים כי צריך להתאים את הקודים של המסמכים של תורת אמת לhtml מי שיודע איך לעשות זאת אשמח מאוד לשמוע.

    כדי לנווט בקלות אפשר להקליד לחיפוש לדוגמא: "דף כב" או "פרק כב" או "פרשת וארא"

    כמובן שיש להתקין קודם את תורת אמת כדי להשתמש בתבנית

    כדי להתקיןאת יש להעתיק את התבנית אל תוך תיקייה זו

    %AppData%\Microsoft\Word\STARTUP
    

    ואז לפתוח דרך תפריט המאקרו בכרטיסיית 'תצוגה'
    או ללחוץ על קיצור המקשים (Alt + T)

    להלן הקובץ:

    תורת-אמת-בוורד.dotm


    פרויקט נוסף שלי:

    [תוסף עיצוב תורני לוורד]
    https://mitmachim.top/post/626904


  • תוסף חיפוש רגקס בוורד
    pcinfogmachP pcinfogmach

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


  • הצגת מסמכי pdf ב-.net - כל המידע שאספתי בנושא
    pcinfogmachP pcinfogmach

    לאחר שחקרתי את הנושא אני חייב להגיד שיצאתי מאוכזב רוב הפקדים לא שווים כלום גם אלו שבשתלום כל מה שהם עושים זה להמיר את המסמך לתמונות ולהציג אותו בlistview וכדומה.

    pdfiumviewer - אפשרות פשוטה יחסית:
    תודות ל@חגי הצלחתי להפעיל את pdfium https://tchumim.com/post/161320 אמנם הוא מוגבל ל-winforms אבל הוא די מתקדם התפעלתי מהעובדה שיש שם גם אפשרות חיפוש. אבל תכל'ס המראה לא מרשים מדאי. וגם אין שם אפשרות לבחור סטקסט של מסמכים שעברו ocr ועוד כמה חסרונות.
    בכל אופן בשביל הצגת מסמכים פשוטה הפקד של pdfiumviewer נחמד מאוד.

    מה כן עובד טוב יחסית:

    1. תכל'ס אפשר להציג pdf בתוך פקד webview דא עקא שאין שום שליטה על המסמך רק לטעון אותו וחסל ואש יש את הפקודות המובנות של edge. - לא רע אבל לא מושלם.
    2. אפשרות אחרת הוא להתקין אדובי מעודכן ואז דרך לחיצה ימנית על תפריט של הפקדים בwinforms יש אפשרות להוסיף פקד של pdf של אדובי. יש גם אפשרות לשחק עם הפקד ועם המסמך קצת. ממש פקד נחמד דא קא שהוא קצת איטי בwinforms - וכמובן צריך שיהיה אדובי מעודכן מותקן במחשב כדי שזה יעבוד.

    מה עוד לא הצלחתי לבדוק:

    1. gecko של פיירפוקס לא הצלחתי להתקדם כלום שם.
    2. sumatra pdf יש בעיקרון פקד של winforms אבל לא עבד לי. (למרות שאני לא כל כך מתרגש להשתמש עם sumatra הספרייה שלו לא משוכללת בעליל).

  • ספר טלפונים ב-html
    pcinfogmachP pcinfogmach

    מצו"ב קוד לספר טלפונים בhtml - אשמח לקבל משוב:

    http://tpcg.io/_BIGXW4

    או למי שרוצה לראות את הקוד כאן בפורום:

    <!DOCTYPE html>
    <html lang="he">
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>ספר טלפונים</title>
      <style>
        table {
          border-collapse: collapse;
          width: 100%;
        }
    
        th, td {
          border: 1px solid #dddddd;
          padding: 8px;
        }
    
        th {
          background-color: #f2f2f2;
        }
        
         select {
        border: 1px solid #ccc; 
        border-radius: 3px; 
        padding: 3px; 
      }
      </style>
    </head>
    <body dir="rtl">
    
    <h2>ספר טלפונים</h2>
    
    <select id="searchType">
      <option value="name">שם</option>
      <option value="occupation">מקצוע</option>
      <option value="phone">טלפון</option>
      <option value="email">מייל</option>
    </select>
    
    <input type="text" id="searchInput" onkeyup="searchTable()" placeholder="חפש..">
    
    <p>
    
    <table id="phoneDirectory">
      <tr>
        <th>שם</th>
        <th>מספר טלפון</th>
        <th>כתובת דואר אלקטרוני</th>
        <th>מקצוע</th>
      </tr>
      <tr>
        <td>יוחנן כהן</td>
        <td>123-456-7890</td>
        <td>yochanan@example.com</td>
        <td>מהנדס תוכנה</td>
      </tr>
      <tr>
        <td>יצחק לוי</td>
        <td></td>
        <td>yitz@example.com</td>
        <td>מעצב גרפי</td>
      </tr>
      <!-- Add more rows as needed -->
    </table>
    
    <script>
    function searchTable() {
      var input, filter, table, tr, td, i, txtValue;
      input = document.getElementById("searchInput");
      filter = input.value.toUpperCase();
      table = document.getElementById("phoneDirectory");
      tr = table.getElementsByTagName("tr");
      var columnIndex;
    
      var select = document.getElementById("searchType");
      var searchType = select.value;
    
      if (searchType === "name") {
        columnIndex = 0;
      } else if (searchType === "phone") {
        columnIndex = 1;
      } else if (searchType === "email") {
        columnIndex = 2;
      } else if (searchType === "occupation") {
        columnIndex = 3;
      }
    
      for (i = 0; i < tr.length; i++) {
        td = tr[i].getElementsByTagName("td")[columnIndex]; 
        if (td) {
          txtValue = td.textContent || td.innerText;
          if (txtValue.toUpperCase().indexOf(filter) > -1) {
            tr[i].style.display = "";
          } else {
            tr[i].style.display = "none";
          }
        }
      }
    }
    </script>
    
    </body>
    </html>
    
    

  • חומרי עזר (למחשב) לאברך - חוברות הדרכה ועוד
    pcinfogmachP pcinfogmach

    מדי פעם אעלה פה עוד חומרים לפי המזדמן ובלי נדר


    1. מדריך קצר עבור קניית מחשב חדש.pdf

    1. שימוש במחשב
    • מידע-מחשבים-כללי.pdf
    • בעיות מצויות ופתרונותיהם
    • ווירוסים מצויים ופתרונותיהם

    1. 12-תכנות-שימושיות.htm

    1. טיפים-לעבודה-נכונה-עם-וורד-גרסה-2.dotm
      הופץ על ידי בעבר במקומות שונים כעת שופץ מחדש ונוספו לו תוספות רבות.

    1. תוסף עיצוב תורני 7.7.exe. תוסף חינמי לוורד.
      תורת אמת בוורד

    1. המילון התורני - תיקון שגיאות תורני לוורד.

    1. חיפוש בתוכן הקבצים Docfetcher
      הוראות שימוש: מדריך עבור תוכנת DocFetcher.pdf
      דוקפטשר - הוראות מתורגמות על ידי המנוע של וורד.docx

    1. פתרון באג שצג בוורד

    1. חיפוש והחלפה מתקדמים בתוכנת וורד.
      עריכה: מדריך בסיסי
      מדריך כללי
      אוסף קודים שימושיים

    1. גמ"ח עזרה לעורכים תורניים

    1. גמ"ח ספרים דרך המייל

    #. חומרים נוספים


  • לימודי נהיגה
    pcinfogmachP pcinfogmach

    אוקיי, אכתוב לך סקירה קצרה של כמה נקודות שאולי יעזרו לך או למישהו אחר:

    1. מהירות נהיגה:
      יש כללים חשובים שיש לשנן, אבל זה לא הנושא שלי כאן. בגדול, בתוך אזור עירוני הנסיעה במבחן תהיה במהירות של 30 קמ"ש, אלא אם הכביש פנוי – אז הנסיעה תהיה על 50 קמ"ש. שים לב! בטסטים אוהבים לקחת אותך לכבישים עירוניים רחבים ולראות אם אתה עובר את ה-50 קמ"ש. בגדול, בכביש רחב חובה לשים לב לתמרורים!

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

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

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

    5. מבטים:
      בכביש דברים משתנים כל הזמן! מה שהיה נכון לפני רגע, כבר לא נכון עכשיו. אז אם הסתכלת וראית שפנוי, זה עדיין לא אומר שאתה יכול להיכנס לצומת. מה עושים? מסתכלים כל הזמן שוב ושוב מבטים קצרים, כדי שתוכל להיות ערני לכל הכיוונים: קודם לצד שאתה פונה אליו, ואז שוב לצד שאתה לא פונה אליו, ואז שוב לכיוון שאתה פונה אליו.

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

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

    8. מעברי חצייה והולכי רגל:
      הבעיה עם הולכי רגל היא שאין לך שום אינדיקציה מי הוא הבא בתור שיחליט לקפוץ לכביש. אנשים מפטפטים ופתאום מחליטים לעבור. הכלל הוא שכל עוד יש סיכוי שהוא יגיע למעבר חציה לפניך, הוא חשוד בעיניך כקופץ הבא. אם אתה לא בטוח – תאט לקראת המעבר ותגשש. כדאי מאוד לקלוט הולכי רגל מרחוק. אם אתה רחוק 10 מטר מהמעבר והולך הרגל במרחק 2 מטר – מי עלול להגיע ראשון למעבר? קח בחשבון שהוא עלול להחליט לרוץ פתאום. בקיצור, מבחינתך הולכי רגל הם בלתי צפויים לחלוטין.

    9. איתותים
      שלא כמו בשאר חלקי החיים בגדול הכלל הוא כולם צריכים לדעת מה אתה עושה עוד לפני שאתה עושה את זה.

    10. חניות:
      חשוב ללמוד את הכללים והטריקים ולהיצמד אליהם – ככה ורק ככה תצליח.


  • אתר עם תמונות יפות (ללא רקע) לגרפיקה או לכל צורך אחר
    pcinfogmachP pcinfogmach

    אתר עם תמונות יפות לגרפיקה - ללא רקע - או לכל צורך אחר
    https://www.pngwing.com/
    הופתעתי לטובה.


  • תורת אמת בוורד - עכשיו בvsto
    pcinfogmachP pcinfogmach

    בס"ד יצא לאור גרסה מס 3
    עם הרבה שיכלולים

    להורדה לחץ על הקישור דלהלן
    https://github.com/pcinfogmach/ToratEmetInWord/releases/tag/ToratEmetInWord

    3afb5eb8-74e5-4780-917f-88472d387b29-eae880e4-2f68-4564-816b-b1f85325dacd-_--_____.jpg


  • דף html עם חיפוש טקסט (עם רגקס)
    pcinfogmachP pcinfogmach
    <!DOCTYPE html>
    <html lang="auto">
    <head>
        <meta charset="UTF-8">
        <title>Search Highlight Page</title>
        <style>
            body {margin:0;}
            .highlight {
                background-color: yellow;
            }
            .selected-highlight {
                background-color: orange;
            }
        </style>
    </head>
    <body dir='rtl'>
        <div id="searchContainer" style="position: fixed; top: 0; margin:0; padding: 5px; width: 100%; background-color:whitesmoke;">
            <input type="text" id="searchBar" placeholder="הזן טקסט לחיפוש" style="border: none; padding:5px;" onkeydown="handleEnter(event)">
            <button id="searchButton" style="border: none; padding:5px;" onclick="searchNext()">חפש</button>
            <button id="previousButton" style="border: none; padding:5px;" onclick="searchPrevious()">הקודם</button>
            <label><input type="checkbox" id="regexCheckbox"> חיפוש בעזרת Regex</label>
        </div>
    
        <div id="content" style="padding-top: 25px; margin:5px;">
            <!-- Example content to search through -->
            <p>וידאו מספק דרך רבת-עוצמה שתעזור לך להוכיח את הנקודה שלך. בעת הלחיצה על 'וידאו מקוון', באפשרותך להדביק את הקוד המוטבע של הווידאו שברצונך להוסיף. ניתן גם להקליד מילת מפתח כדי לחפש באופן מקוון אחר וידאו שיתאים בצורה הטובה ביותר למסמך שלך.</p>
            <p>כדי להעניק למסמך שלך מראה מקצועי, Word מספק עיצובים של כותרת עליונה, כותרת תחתונה, עמוד שער ותיבת טקסט אשר משלימים זה את זה. לדוגמה, באפשרותך להוסיף עמוד שער, כותרת עליונה וסרגל צידי תואמים. לחץ על 'הוסף' ולאחר מכן בחר את הרכיבים הרצויים מהגלריות השונות.</p>
            <p>ערכות נושא וסגנונות גם שומרים על התיאום של המסמך שלך. בעת הלחיצה על 'עיצוב' ובחירת ערכת נושא חדשה, התמונות, התרשימים וגרפיקת SmartArt משתנים בהתאם לערכת הנושא החדשה שלך. בעת החלת סגנונות, הכותרות משתנות בהתאם לערכת הנושא החדשה.</p>
            <p>חסוך זמן בעבודה ב- Word בעזרת לחצנים חדשים המופיעים במקומות הנכונים. כדי לשנות את אופן ההתאמה של תמונה למסמך, לחץ עליה ולצידה יופיע לחצן של אפשרויות פריסה. בעת העבודה על טבלה כלשהי, לחץ במקום שבו ברצונך להוסיף שורה או עמודה, ולאחר מכן לחץ על סימן החיבור.</p>
            <p>כמו כן, קל יותר לקרוא בתצוגת הקריאה החדשה. באפשרותך לכווץ חלקים של המסמך ולהתמקד בטקסט הרצוי. אם עליך להפסיק לקרוא לפני שאתה מגיע לסוף המסמך, Word זוכר את המקום שאליו הגעת - אפילו בהתקן אחר.</p>
        </div>
    
        <script>
            let currentIndex = 0;
            let previousSearchTerm = "";
            let direction = 'next';
    
            function removeHighlights() {
                const highlights = document.querySelectorAll('.highlight, .selected-highlight');
                highlights.forEach(highlight => {
                    const parent = highlight.parentNode;
                    while (highlight.firstChild) {
                        parent.insertBefore(highlight.firstChild, highlight);
                    }
                    parent.removeChild(highlight);
                });
            }
    
            function highlightSearchTerm(searchTerm, useRegex) {
                const regex = useRegex ? new RegExp(`(${searchTerm})`, 'gi') : new RegExp(`(${searchTerm.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')})`, 'gi');
                const content = document.getElementById('content');
                content.innerHTML = content.innerHTML.replace(regex, '<span class="highlight">$1</span>');
            }
    
            function searchAndHighlight() {
                const searchTerm = document.getElementById('searchBar').value;
                const useRegex = document.getElementById('regexCheckbox').checked;
                removeHighlights();
                if (searchTerm) {
                    highlightSearchTerm(searchTerm, useRegex);
                    const highlightedElements = document.querySelectorAll('.highlight');
                    if (highlightedElements.length) {
                        if (searchTerm === previousSearchTerm && direction === 'next') {
                            currentIndex++;
                            if (currentIndex >= highlightedElements.length) {
                                currentIndex = 0;
                            }
                        } else if (searchTerm === previousSearchTerm && direction === 'previous') {
                            currentIndex--;
                            if (currentIndex < 0) {
                                currentIndex = highlightedElements.length - 1;
                            }
                        } else {
                            currentIndex = 0;
                        }
    
                        highlightedElements.forEach(element => element.classList.remove('selected-highlight'));
                        highlightedElements[currentIndex].classList.add('selected-highlight');
                        highlightedElements[currentIndex].scrollIntoView({ block: "center" });
                    }
                } else {
                    alert('Please enter a search term.');
                }
                previousSearchTerm = searchTerm;
            }
    
            function searchPrevious() {
                direction = 'previous';
                searchAndHighlight();
            }
    
            function searchNext() {
                direction = 'next';
                searchAndHighlight();
            }
    
            function handleEnter(event) {
                if (event.key === 'Enter') {
                    event.preventDefault(); // Prevent default Enter key behavior (like form submission)
                    searchNext();
                }
            }
        </script>
    </body>
    </html>
    
    
    
    

  • מדריך בסיסי עבור מנוע החיפוש הפופולרי lucene ב-C#
    pcinfogmachP pcinfogmach

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

    כדי להשתמש בספרייה זו תצטרכו להתקין דרך ממשק ה-nuget ב-Visual Studio כמה ספריות. הספרייה הנוכחית של Lucene עדיין בשלבי בטא ולכן תצטרכו לסמן בחלונית ה-nuget את האפשרות "Include prerelease".

    להלן הספריות שתצטרכו:

    Lucene.Net
    Lucene.Net.QueryParser
    

    שלב א' - יצירת analyzer

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

    לכן, שלב ראשון עלינו לייצר Analyzer:

    Analyzer analyzer = new StandardAnalyzer(LuceneVersion.LUCENE_48);
    

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

    אם ברצונכם לתמוך בחיפוש גם בטקסט מנוקד תצטרכו לייצר analyzer משלכם שמסיר את הניקוד כדלהלן:

    public class DiacriticsAnalyzer : Analyzer
    {
        LuceneVersion version;
        public DiacriticsAnalyzer(LuceneVersion luceneVersion)
        {
            version = luceneVersion;
        }
        protected override TokenStreamComponents CreateComponents(string fieldName, TextReader reader)
        {
            var tokenizer = new StandardTokenizer(version, reader);
            TokenStream filter = new HebrewTokenFilter(tokenizer);
            filter = new LowerCaseFilter(version, filter);
            filter = new StopFilter(version, filter, StopAnalyzer.ENGLISH_STOP_WORDS_SET);
            return new TokenStreamComponents(tokenizer, filter);
        }
    
        sealed class HebrewTokenFilter : TokenFilter
        {
            private readonly ICharTermAttribute termAttr;
    
            public HebrewTokenFilter(TokenStream input) : base(input)
            {
                this.termAttr = AddAttribute<ICharTermAttribute>();
            }
    
            public sealed override bool IncrementToken()
            {
                if (m_input.IncrementToken())
                {
                    string token = termAttr.ToString();
                    string cleanedToken = Regex.Replace(token, @"\p{M}", "");
    
                    if (!string.Equals(token, cleanedToken))
                    {
                        termAttr.SetEmpty().Append(cleanedToken);
                    }
    
                    return true;
                }
                return false;
            }
        }
    }
    

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


    שלב ב' - יצירת האינדקס

    להלן קוד דוגמא ליצירת אינדקס מתוך מערך של קבצי טקסט

    public void IndexFiles(List<string> files)
    {
        using (var directory = FSDirectory.Open(new DirectoryInfo(indexPath)))
        {
            var indexConfig = new IndexWriterConfig(LuceneVersion.LUCENE_48, analyzer);
            using (var writer = new IndexWriter(directory, indexConfig))
            {
                foreach (string file in files)
                {
                    string content = File.ReadAllText(file);
                    var doc = new Document
                    {
                        new StringField("Path", file, Field.Store.YES),
                        new TextField("Content", content, Field.Store.YES)
                    };
                  
                    var term = new Term("Path", file); // Create a term to search for the existing document by its path
    
                    writer.UpdateDocument(term, doc);  // Update the document if it exists, otherwise add it
                }
    
                writer.Flush(triggerMerge: true, applyAllDeletes: true);
            }
        }
    }
    
    מאוד חשוב להקפיד על ה-using כדי למנוע מצב בו האינדקס נשאר נעול במצב כתיבה.

    כדי למחוק קבצים מהאינדקס תוכלו להתמש עם הקוד דלהלן:

     public void RemoveFiles(List<string> files)
     {
         using (var directory = FSDirectory.Open(new DirectoryInfo(indexPath)))
         {
             var indexConfig = new IndexWriterConfig(Lucene.Net.Util.LuceneVersion.LUCENE_48, analyzer);
             using (var writer = new IndexWriter(directory, indexConfig))
             {
                 var parser = new QueryParser(Lucene.Net.Util.LuceneVersion.LUCENE_48, "Path", analyzer);
    
                 foreach (string file in files)
                 {
                     Query query = parser.Parse(file);
                     writer.DeleteDocuments(query);
                 }
                 writer.Flush(triggerMerge: false, applyAllDeletes: false);
             }
         }
     }
    

    שלב ג' חיפוש באינדקס

    כדי לחפש באינדקס קודם כל תצטרכו ליישם QueryParser אשר תפקידו לעשות parsing למחרוזת הטקסט של החיפוש.
    ישנם כמה וכמה סוגים של QueryParsers תלוי מאוד מה הצורך שלכם תוכלו לקרוא על כך בהרחבה בלינק שהבאתי בתחלילת הפוסט, עבור חיפוש עם אפשרויות מגוונות אני ממליץ לכם להתשמש עם ComplexPhraseQueryParser מה שיאפשר למשתמש אפשרויות חיפוש מגווונות כגון חיפוש טבלאי וחיפוש עם wildcards חיפוש מטושטש ועוד ועוד. תוכלו לקרוא על הסינטקס של חיפוש lucene בקישור שבתחילת הפוסט.

     Analyzer analyzer = new StandardAnalyzer(LuceneVersion.LUCENE_48);
    ComplexPhraseQueryParser queryParser = new ComplexPhraseQueryParser(LuceneVersion.LUCENE_48, "Content", analyzer);
    

    שימו לב! חיפוש מילה עם ראשי תיבות יחזיר שגיאה יש להזין את הראשי תיבות בתוספת slash ככה

    אא\"כ
    

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

      public List<string> Search(string queryText, List<string> checkedTreeNodes)
      {
          using (var directory = FSDirectory.Open(new DirectoryInfo(indexPath)))
          {
              var searcher = new IndexSearcher(DirectoryReader.Open(directory));
              var parser = new CostumeQueryParser(Lucene.Net.Util.LuceneVersion.LUCENE_48, "Content", analyzer);
    
              var query = parser.Parse(queryText);
    
              var topDocs = searcher.Search(query, int.MaxValue);
    
              List<string> results = new List<string>();
              foreach (var scoreDoc in topDocs.ScoreDocs)
              {
                  var path = searcher.Doc(scoreDoc.Doc).Get("Path");
                  results.Add(path);
              }
              return results;
          }
      }
    

    שלב ג' -2 איך לייצר גזירים

    כדי לייצר גזירים תצטרכו להתקין את חבילת ה-nuget
    Lucene.Net.Highlighter

    לאחמ"כ תוכלו להשתמש עם הקוד הזה

     string[] GetFragments(int docId, IndexSearcher searcher,  Query query)
     {
    
    //create fragmenter
         var reader = searcher.IndexReader;  
         var scorer = new QueryScorer(query);
         var fragmenter = new SimpleSpanFragmenter(scorer, 250); // 250 is the fragment size 
    
    // create highlighter
         var formatter = new SimpleHTMLFormatter("<", ">"); //define how to mark found keywords if left empty <b> tags is the default
         var highlighter = new Highlighter(formatter, scorer);         
         highlighter.TextFragmenter = fragmenter;
    
    //extract snippets
         var content = searcher.Doc(docId).Get("Content");
         var tokenStream = TokenSources.GetAnyTokenStream(reader, docId, "Content", analyzer);
         var fragments = highlighter.GetBestTextFragments(tokenStream, content, false, 10); // 10 is the number of snippets
    
    // return filters the list and converts to string filtering is needed only if number of fragments is set to more then 1
         return fragments.Where(fragment => fragment.Score > 0).Select(fragment =>  fragment.ToString()).ToList().ToArray();
     }
    

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


  • שאלה: מה הסוד מאחורי מנוע החיפוש של בר אילן? (מבחינת תיכנות)
    pcinfogmachP pcinfogmach

    @dovid כתב בשאלה: מה הסוד מאחורי מנוע החיפוש של בר אילן? (מבחינת תיכנות):

    (אם יש לך שאלה מעשית - ולא המשך של השאלה הרעיונית שיש בנושא זה - שאל אותה בנושא קונקרטי עבורה).

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

    התוכנה כעת בפיתוח בשפת c#

    מצו"ב תמונה (למרות שזה ממש באמצע העבודה - לשם האמינות)
    0f969cc6-97d3-44e0-8973-374f28835c5f-image.png

    יש לנו עוד פרוייקט בשלב יותר מתקדם - תוסף תורת אמת בוורד
    שם לבינתיים אילתרנו משהו אבל אם כבר שם נוכל לעשות מנוע חיפוש זה יהיה כמעט מושלם.

    6e2d05a3-e6a4-4d3a-b7fe-8a33c25ccbf2-image.png
    dcca6841-b156-4655-8902-f7e82c65d874-image.png


  • קוד לעורך טקסט בhtml - שמישהו שלח לי - אולי יהיה שימושי למישהו
    pcinfogmachP pcinfogmach

    קוד לעורך טקסט בhtml - מקור לא ידוע
    צריך כמה תיקונים אבל בגדול עובד.

    <!DOCTYPE html>
    <html>
    <head>
        <title>Text Editor</title>
        <style>
            body {
                margin: 0;
                padding: 0;
                font-family: 'Noto Sans Hebrew', Arial, sans-serif;
                background-color: #f0f0f0; /* Light gray background for the entire page */
            }
    
            #editor-container {
                margin: 50px auto; /* Center the editor container horizontally and provide top margin */
                width: 793px; /* Fixed width for the editor */
                height: 410px; /* Fixed height for the editor */
                border: 1px solid #ccc;
                padding: 20px; /* Add margins here */
                background-color: #fff; /* White content area background */
                overflow: auto; /* Enable vertical scrolling */
    			 margin-top: 100px; /* Adjust the margin-top to move the editor lower */
            }
    
            #editor:focus {
                outline: none; /* Remove the default focus outline */
                /* You can add additional styles or borders here as needed */
            }
    
            .floating-toolbar {
                position: fixed;
                top: 0;
                left: 0;
                width: 100%;
                background-color: #fff;
                border-bottom: 1px solid #ccc;
                box-shadow: 0 1px 5px rgba(0, 0, 0, 0.1);
                z-index: 1000;
    			display: flex;
                align-items: center; /* Vertically center the items within the toolbar */
                justify-content: center; /* Horizontally center the items within the toolbar */
            }
    		
    		
    
            .button-container {
                display: flex;
                flex-wrap: wrap; /* Allow buttons to wrap to the next line */
                justify-content: center; /* Center-align the buttons horizontally */
                gap: 5px;
                padding: 5px 0; /* Adjust top and bottom padding to center vertically */
            }
    
            .button {
                font-size: 14px;
                background-color: #eee;
                color: #333;
                border: none;
                border-radius: 5px;
                cursor: pointer;
                min-width: 30px;
                padding: 5px; /* Add padding to match the size */
            }
    
            .button:hover {
                background-color: #ccc;
            }
    
            .underline-button {
                text-decoration: underline;
            }
    
            .dropdown select {
                padding: 5px;
                font-size: 14px;
                background-color: #eee;
                color: #333;
                border: none;
                border-radius: 5px;
                cursor: pointer;
            }
    
            .color-dropdown {
                position: relative;
            }
    
            .color-dropdown-content {
                display: none;
                position: absolute;
                background-color: #f9f9f9;
                width: 100px; /* Set a fixed width for the dropdown list */
                max-height: 100px; /* Limit the height of the dropdown */
                overflow-y: auto; /* Enable vertical scrolling */
                border: 1px solid #ccc;
                z-index: 1;
            }
    
            .color-dropdown-content button {
                display: block;
                width: 100%;
                text-align: left;
                padding: 8px 12px;
                border: none;
                background-color: transparent;
                cursor: pointer;
            }
    
            .color-dropdown-content button:hover {
                background-color: #ddd;
            }
    
            /* Add Hebrew fonts here */
            @import url('https://fonts.googleapis.com/css2?family=Noto+Sans+Hebrew&display=swap');
    
            /* Media query for smaller screens */
            @media (max-width: 480px) {
                .button-container {
                    flex-direction: column; /* Stack buttons vertically */
                    align-items: center; /* Center-align buttons vertically */
                }
            }
    		
    		.label-font-size {
                padding: 5px 10px; /* Adjust the padding as needed */
                line-height: 1; /* Set line-height to 1 for vertical centering */
            }
        </style>
    </head>
    <body>
        <div class="floating-toolbar">
            <div class="button-container">
                <button class="button" onclick="formatText('bold')" title="Bold (Ctrl+B)">B</button>
                <button class="button" onclick="formatText('italic')" title="Italic (Ctrl+I)">I</button>
                <button class="button underline-button" onclick="formatText('underline')" title="Underline (Ctrl+U)">U</button>
                <button class="button" onclick="toggleJustify()" title="Justify">J</button>
                <button class="button" onclick="alignText('left')" title="Left Align">L</button>
                <button class="button" onclick="alignText('center')" title="Center Align">C</button>
                <button class="button" onclick="alignText('right')" title="Right Align">R</button>
                <div class="dropdown">
                    <select id="styleDropdown" onchange="formatHeader()" title="Style">
                        <option value="hidden" disabled selected style="display:none">Style</option>
                        <option value="normal">Normal</option>
                        <option value="h1">H1</option>
                        <option value="h2">H2</option>
                        <option value="h3">H3</option>
                        <option value="h4">H4</option>
                        <option value="h5">H5</option>
                        <option value="h6">H6</option>
                    </select>
                </div>
                <div class="dropdown">
                    <select id="fontDropdown" onchange="changeFont()" title="Font">
                        <option value="Arial">Arial</option>
                        <option value="Helvetica">Helvetica</option>
                        <option value="Verdana">Verdana</option>
                        <option value="Georgia">Georgia</option>
                        <option value="Times New Roman">Times New Roman</option>
                        <option value="Courier New">Courier New</option>
                        <option value="Arial Black">Arial Black</option>
                        <option value="Impact">Impact</option>
                        <option value="Lucida Console">Lucida Console</option>
                        <option value="Tahoma">Tahoma</option>
                        <option value="Trebuchet MS">Trebuchet MS</option>
                        <option value="Palatino Linotype">Palatino Linotype</option>
                        <!-- Change "Frank Ruhl Libre" to "FrankRuhl" -->
                        <option value="FrankRuhl">Frank Ruhl</option>
                        <!-- Add Hebrew fonts below -->
                        <option value="David">David</option>
                        <option value="Narkisim">Narkisim</option>
                        <option value="Hadassa">Hadassa</option>
                    </select>
                </div>
                
                <!-- Added buttons for creating HTML lists -->
                <button class="button" onclick="createUnorderedList()" title="Unordered HTML List"><b>&#8226</b></button>
                <button class="button" onclick="createOrderedList()" title="Ordered HTML List">1.2.3.</button>
                
                <!-- RTL button -->
                <button class="button" onclick="toggleRTL()" title="Toggle Right-to-Left">RTL</button>
                
                <!-- HR button -->
                <button class="button" onclick="insertHorizontalRule()" title="Insert Horizontal Line">HR</button>
    
                <!-- Text Color dropdown -->
                <div class="color-dropdown">
                    <button class="button" onclick="toggleTextColorDropdown()" title="Text Color">Text Color</button>
                    <div class="color-dropdown-content" id="textColorDropdown">
                        <button onclick="changeTextColor('black')" style="color: black;">Black</button>
                        <button onclick="changeTextColor('red')" style="color: red;">Red</button>
                        <button onclick="changeTextColor('green')" style="color: green;">Green</button>
                        <button onclick="changeTextColor('blue')" style="color: blue;">Blue</button>
                        <button onclick="changeTextColor('purple')" style="color: purple;">Purple</button>
                        <button onclick="changeTextColor('orange')" style="color: orange;">Orange</button>
                        <button onclick="changeTextColor('yellow')" style="color: yellow;">Yellow</button>
                        <button onclick="changeTextColor('pink')" style="color: pink;">Pink</button>
                        <button onclick="changeTextColor('brown')" style="color: brown;">Brown</button>
                        <button onclick="changeTextColor('gray')" style="color: gray;">Gray</button>
                        <button onclick="changeTextColor('lightblue')" style="color: lightblue;">Light Blue</button>
                        <button onclick="changeTextColor('lightgreen')" style="color: lightgreen;">Light Green</button>
                        <button onclick="changeTextColor('teal')" style="color: teal;">Teal</button>
                        <button onclick="changeTextColor('indigo')" style="color: indigo;">Indigo</button>
                        <button onclick="changeTextColor('violet')" style="color: violet;">Violet</button>
                    </div>
                </div>
    
                <!-- Highlight Color dropdown -->
                <div class="color-dropdown">
                    <button class="button" onclick="toggleHighlightColorDropdown()" title="Highlight Text">Highlight</button>
                    <div class="color-dropdown-content" id="highlightColorDropdown">
                        <button onclick="highlightText('yellow')" style="background-color: #ffffcc;">Yellow</button>
                        <button onclick="highlightText('lightgreen')" style="background-color: #ccffcc;">Light Green</button>
                        <button onclick="highlightText('lightpink')" style="background-color: #ffcce6;">Light Pink</button>
                        <button onclick="highlightText('lightblue')" style="background-color: #cce6ff;">Light Blue</button>
                        <button onclick="highlightText('lightorange')" style="background-color: #ffe6cc;">Light Orange</button>
                        <button onclick="highlightText('lightpurple')" style="background-color: #e6ccff;">Light Purple</button>
                        <button onclick="highlightText('lightgray')" style="background-color: #f2f2f2;">Light Gray</button>
                        <button onclick="highlightText('white')" style="background-color: #ffffff; color: #000000;">White</button>
                    </div>
                </div>
                
                <!-- Remove Formatting button -->
                <button class="button" onclick="removeFormatting()" title="Remove Color">Remove Formatting</button>
    			
    			<button class="button" onclick="formatText('superscript')" title="Superscript">Sup</button>
                <button class="button" onclick="formatText('subscript')" title="Subscript">Sub</button>
                <button class="button" onclick="increaseIndent()" title="Increase Indent">&#x2B72;</button>
                <button class="button" onclick="decreaseIndent()" title="Decrease Indent">&#x2B70;</button>
    
    			<!-- Font size buttons -->
                <label for="fontSizeSpan" class="label-font-size">Font Size:</label>
                <button class="button" onclick="changeFontSize('increase')" title="Increase Font Size">+</button>
                <button class="button" onclick="changeFontSize('decrease')" title="Decrease Font Size">-</button>
    			
    			 <!-- Spacing between paragraphs buttons -->
                <label for="spacingBetweenParagraphs" class="label-font-size">Spacing:</label>
                <button class="button" onclick="changeSpacing('increase')" title="Increase Spacing">+</button>
                <button class="button" onclick="changeSpacing('decrease')" title="Decrease Spacing">-</button>
    
    			<!-- Add Link button -->
                <button class="button add-link-button" title="Add Link">&#128279</button>
    			
    			
    
     <button class="button" onclick="exportHTML()" title="Export HTML">Export HTML</button>
     <button class="button" onclick="exportToTxt()" title="Export to TXT">Export As Code</button>
        <!-- Add this button for exporting HTML -->
    	
    	   </div>
        </div>
        <div id="editor-container">
            <div id="editor" contenteditable="true" onkeypress="handleKeyPress(event)">
                <!-- Automatically start with a <p> tag -->
                <p>Start typing here...</p>
            </div>
        </div>
    	
    
        <script>
            let isJustified = false;
            let isRTL = false;
    
            function formatText(command) {
                document.execCommand(command, false, null);
            }
    
            function toggleJustify() {
                isJustified = !isJustified;
                document.execCommand(isJustified ? 'justifyFull' : 'justifyLeft', false, null);
            }
    
            function alignText(align) {
                document.execCommand('justify' + align, false, null);
                isJustified = false;
            }
    
            function formatHeader() {
                const styleDropdown = document.getElementById('styleDropdown');
                const selectedStyle = styleDropdown.value;
                if (selectedStyle === 'normal') {
                    document.execCommand('formatBlock', false, 'p');
                } else if (selectedStyle) {
                    document.execCommand('formatBlock', false, selectedStyle);
                }
                styleDropdown.selectedIndex = 0;
            }
    
            function changeFont() {
                const fontDropdown = document.getElementById('fontDropdown');
                const selectedFont = fontDropdown.value;
                document.execCommand('fontName', false, selectedFont);
            }
    
            function createUnorderedList() {
                document.execCommand("insertUnorderedList");
            }
    
            function createOrderedList() {
                document.execCommand("insertOrderedList");
            }
    
            function handleKeyPress(event) {
                if (event.keyCode === 13) { // Enter key
                    document.execCommand('insertHTML', false, '<p><br></p>');
                    event.preventDefault();
                }
            }
    
            function insertHorizontalRule() {
                document.execCommand('insertHorizontalRule', false, null);
            }
    
            function toggleRTL() {
                isRTL = !isRTL;
                const editorContainer = document.getElementById('editor-container');
                editorContainer.style.direction = isRTL ? 'rtl' : 'ltr';
            }
    
            function toggleTextColorDropdown() {
                const textColorDropdown = document.getElementById('textColorDropdown');
                textColorDropdown.style.display = (textColorDropdown.style.display === 'block') ? 'none' : 'block';
            }
    
            function changeTextColor(color) {
                document.execCommand("foreColor", false, color);
                toggleTextColorDropdown(); // Close the dropdown
            }
    
            function toggleHighlightColorDropdown() {
                const highlightColorDropdown = document.getElementById('highlightColorDropdown');
                highlightColorDropdown.style.display = (highlightColorDropdown.style.display === 'block') ? 'none' : 'block';
            }
    
            function highlightText(color) {
                document.execCommand("hiliteColor", false, color);
                toggleHighlightColorDropdown(); // Close the dropdown
            }
    
            function removeFormatting() {
                document.execCommand("removeFormat", false, null);
            }
    		
    		function increaseIndent() {
                document.execCommand("indent", false, null);
            }
            
            function decreaseIndent() {
                document.execCommand("outdent", false, null);
            }
    		
    		function changeFontSize(action) {
                const editor = document.getElementById('editor');
                const selectedText = document.getSelection();
                const span = document.createElement('span');
                
                if (action === 'increase') {
                    span.style.fontSize = 'larger';
                } else if (action === 'decrease') {
                    span.style.fontSize = 'smaller';
                }
                
                if (!selectedText.isCollapsed) {
                    const range = selectedText.getRangeAt(0);
                    range.surroundContents(span);
                }
            }
    		
    		function changeSpacing(action) {
                const editor = document.getElementById('editor');
                const selectedParagraphs = document.querySelectorAll('#editor p');
                
                selectedParagraphs.forEach(paragraph => {
                    let currentMargin = parseInt(window.getComputedStyle(paragraph).marginBottom);
                    
                    if (action === 'increase') {
                        currentMargin += 5; // Increase spacing by 5px
                    } else if (action === 'decrease') {
                        currentMargin -= 5; // Decrease spacing by 5px
                    }
                    
                    paragraph.style.marginBottom = currentMargin + 'px';
                });
            }
    		
    		
    
      function exportHTML() {
                // Get the content of the editor
                const editorContent = document.getElementById('editor').innerHTML;
    
                // Create a new window or tab to preview the HTML content
                const previewWindow = window.open('', '_blank');
    
                // Create a blob containing the editor's HTML content
                const blob = new Blob([editorContent], { type: 'text/html' });
    
                // Create a URL for the blob
                const url = URL.createObjectURL(blob);
    
                // Create an anchor element to trigger the download
                const a = document.createElement('a');
                a.href = url;
                a.download = 'exported_text.html'; // Define the file name
    
                // Create a button to allow the user to download the HTML
                const downloadButton = document.createElement('button');
                downloadButton.textContent = 'Download HTML';
                downloadButton.style.position = 'absolute'; // Set the button position to absolute
                downloadButton.style.top = '10px'; // Adjust the top position as needed
                downloadButton.style.left = '10px'; // Adjust the left position as needed
                downloadButton.onclick = () => {
                    // Trigger a click event on the anchor element to start the download
                    a.click();
                    // Clean up by revoking the blob URL
                    URL.revokeObjectURL(url);
                };
    
                // Append the download button to the preview window
                previewWindow.document.body.appendChild(downloadButton);
    
                // Write the editor's HTML content to the new window
                previewWindow.document.open();
                previewWindow.document.write(editorContent);
                previewWindow.document.close();
            }
    		
    		
    
    
    		// Function to create a link using selected text or prompt for text and link address
    function createLink() {
        const selectedText = document.getSelection().toString();
        let linkText = selectedText;
        let linkURL = '';
    
        if (!selectedText) {
            linkText = prompt('Enter the text for the link:');
            if (!linkText) {
                return; // Cancelled by the user
            }
        }
    
        linkURL = prompt('Enter the link address:');
        if (!linkURL) {
            return; // Cancelled by the user
        }
    
        const linkHTML = `<a href="${linkURL}" target="_blank">${linkText}</a>`;
        document.execCommand('insertHTML', false, linkHTML);
    }
    
    // Add event listener for the "Add Link" button
    document.querySelector('.button.add-link-button').addEventListener('click', createLink);
    
    
    function exportToTxt() {
        // Get the editor content
        const editorContent = document.getElementById('editor').innerHTML;
    
        // Create a Blob containing the content and specify the MIME type as plain text
        const blob = new Blob([editorContent], { type: 'text/plain' });
    
        // Create a download link for the Blob
        const url = URL.createObjectURL(blob);
        const a = document.createElement('a');
        a.href = url;
        a.download = 'exported_text.txt';
    
        // Trigger a click event on the link to start the download
        a.click();
    
        // Release the object URL to free up resources
        URL.revokeObjectURL(url);
    }
    
    		
        </script>
    </body>
    </html>
    

  • קוד vba לייצוא כל המודולים בבת אחת
    pcinfogmachP pcinfogmach

    קוד vba לייצוא מודולים

    Sub ייצוא_מודולים()
    'נוצר על ידי pcinfogmach
    
    Dim sourceDoc As Object ' מסמך מקור המכיל את המודולים
    Dim targetDoc As Object ' מסמך יעד להעתקת המודולים אליו
    Dim sourceModule As Object ' מודול מקור
    Dim targetModule As Object ' מודול יעד
    Dim fileDialog As Object ' דיאלוג לבחירת קובץ
    Dim savePath As String ' נתיב לשמירת המודולים המיוצאים
    Dim mysavePath As String ' נתיב לשמירת המודולים המיוצאים
    Dim saveFolder As Object ' דיאלוג לבחירת תיקייה
        
        ' יצירת דיאלוג לבחירת קובץ
        Set fileDialog = Application.fileDialog(msoFileDialogFilePicker)
        
        ' אפשרות לבחירת קובץ יחיד בלבד
        fileDialog.AllowMultiSelect = False
        
    '    הגדרת הכותרת והסינונים לדיאלוג
        fileDialog.Title = "בחר מסמך מקור"
        fileDialog.Filters.Clear
        fileDialog.Filters.Add "מסמכי וורד", "*.docm; *.dotm; *.dot"
        
        ' הצגת הדיאלוג ובדיקה אם נבחר קובץ
        If fileDialog.Show = -1 Then
        ' הגדרת הקובץ הנבחר כמסמך המקור
            Set sourceDoc = Documents.Open(fileDialog.SelectedItems(1))
            
        ' יצירת דיאלוג לבחירת תיקיית יעד
        Set saveFolder = Application.fileDialog(msoFileDialogFolderPicker)
        ' הגדרת הכותרת לדיאלוג
        saveFolder.Title = "בחר תיקיית יעד"
    
                ' הצגת הדיאלוג ובדיקה אם נבחרה תיקייה
            If saveFolder.Show = -1 Then
                        ' הגדרת התיקייה הנבחרת כנתיב השמירה
                savePath = saveFolder.SelectedItems(1) & Application.PathSeparator
    
            ' לולאה על כל מודול במסמך המקור
            For Each sourceModule In ActiveDocument.VBProject.VBComponents
             'קבלת שם המודול
                    Dim moduleName As String
                    moduleName = sourceModule.Name
                    
                ' בניית נתיב הקובץ לשמירת המודול המיוצא באמצעות השם המקורי
                If sourceModule.Type = 1 Or sourceModule.Type = 100 Then
                    mysavePath = savePath & moduleName & ".bas"
                ElseIf sourceModule.Type = 2 Then
                    mysavePath = savePath & moduleName & ".cls"
                ElseIf sourceModule.Type = 3 Then
                    mysavePath = savePath & moduleName & ".frm"
                End If
                
         ' ייצוא המודול מהמסמך המקור באמצעות נתיב הקובץ
                    sourceModule.Export mysavePath
    
            Next sourceModule
            
          ' סגירת המסמך המקור בלי שמירת שינויים
            sourceDoc.Close False
        End If
        End If
    End Sub
    

  • הגדה של פסח כפשוטו - סיפור ההגדה מתוך ההגדה
    pcinfogmachP pcinfogmach

    ניסיון שלי לבאר את חלק הסיפור שבהגדה כפשוטו - מבלי להצטרך להוספות חוץ מהטקסט. הביאור נכתב על פי דברי רבותינו הראשונים והאחרונים. וכפי שליקטתי בהגדה של פסח המפורשת תנו שבח.
    הגדה של פסח כפשוטו.pdf


  • קוד להצגת התקדמות ב-statusbar של וורד
    pcinfogmachP pcinfogmach

    הקוד ב-C# אבל אפשר להמיר ל-vba די בקלות (אולי לא הכל אבל את העיקרון) למי שירצה.
    הקוד מציג התקדמות בסרגל התחתון של וורד.
    היה לי את זה באחד מהפרוייקטים הישנים שלי, פעם שלחתי את זה למישהו והיה לו בזה שימוש, עכשיו נתקלתי בזה אמרתי אולי יהיה למישהו אחר שימוש.

     public static void ReportProgress(string actionDescription, int Currentvalue, int maxValue, int timePerIteration)
     {
         var progressPercent = (int)((double)(100 * Currentvalue) / maxValue);
         string timeLeft = TimeSpan.FromSeconds((maxValue - Currentvalue) * timePerIteration).ToString(@"hh\:mm\:ss");
         string[] progressBars = new string[] { "●○○○○○○○○○", "●●○○○○○○○○", "●●●○○○○○○○", "●●●●○○○○○○", "●●●●●○○○○○", "●●●●●●○○○○", "●●●●●●●○○○", "●●●●●●●●○○", "●●●●●●●●●○", "●●●●●●●●●●", };
         Globals.ThisAddIn.Application.StatusBar = $"- {timeLeft} -     {progressPercent}%  {progressBars[Math.Max((progressPercent / 10) - 1, 0)]}     {actionDescription} {Currentvalue} \\ {maxValue}";
     }
    

  • מבנה נתונים גלובלי עבור Checked TreeView ב-Wpf
    pcinfogmachP pcinfogmach

    7565919b-5ed3-46b3-a7ae-98317cc9b0df-image.png

    כידוע, הדרך הטובה ביותר להתנהל עם TreeView ב-WPF היא עם מבנה נתונים הררכי, ו-HierarchicalDataTemplate ב-WPF נבנה במיוחד למטרה זו.
    אחרי שמצאתי את עצמי בפעם השלישית בונה מבנה נתונים עבור Checked TreeView (ראה תמונה), החלטתי לשבת כמה דקות ולבנות משהו יותר גלובלי שיאפשר לי להשתמש בו גם בעתיד. הרעיון הוא לייצר מחלקה בסיסית המכילה את כל מה שדרוש עבור מטרה זו, כך שאוכל לרשת אותה ולהשתמש בה עבור כל מבנה נתונים הררכי באופן כללי עם הדרישה הזו של Checked TreeView.

    שימו לב! אני הגדרתי את ה-Default של ה-IsChecked כ-false ייתכן ותרצו לשנות את זה ל-true תלוי באמפלמנטציה שלכם.

    אם לא הבנתם את הנושא דיו והוא מעניין אתכם? אנא קיראו כתבה זו כהקדמה:
    https://www.codeproject.com/Articles/26288/Simplifying-the-WPF-TreeView-by-Using-the-ViewMode

    להלן הקוד:

    using System;
    using System.Collections.Generic;
    using System.Collections.ObjectModel;
    using System.Linq;
    
    namespace MyModels
    {
        public class CheckedTreeViewItemModelBase : ViewModelBase
        {
            string _name;
            bool? _isChecked = false;
            ObservableCollection<CheckedTreeViewItemModelBase> _children = new ObservableCollection<CheckedTreeViewItemModelBase>();
    
            public CheckedTreeViewItemModelBase Parent;
    
            public virtual string Name { get => _name; set => SetProperty(ref _name, value); }
            public bool? IsChecked { get => _isChecked; set => SetCheckedValue(value, true); }
            public ObservableCollection<CheckedTreeViewItemModelBase> Children { get => _children; set => SetChildren(value); }
    
            public override string ToString() => Name;
    
            void SetChildren(ObservableCollection<CheckedTreeViewItemModelBase> children)
            {
                if (SetProperty(ref _children, children))
                {
                    foreach (var child in _children) child.Parent = this;
                }
            }
    
            public void SetCheckedValue(bool? isChecked, bool updateChildren)
            {
                if (SetProperty(ref _isChecked, isChecked, nameof(IsChecked)))
                {
                    if (updateChildren && Children != null)
                    {
                        foreach (var child in Children)
                        {
                            if (child.IsChecked != isChecked)
                                child.IsChecked = (isChecked == true);
                        }
                    }
    
                    if (Parent != null)
                    {
                        var parentCheckedValue = Parent.Children.All(c => c.IsChecked == true) ? true :
                            Parent.Children.All(c => c.IsChecked == false) ? (bool?)false : null;
                        Parent.SetCheckedValue(parentCheckedValue, false);
                    }
                }
            }
    
            public IEnumerable<CheckedTreeViewItemModelBase> GetAllCheckedChildren()
            {
                if (Children != null)
                {
                    foreach (var child in Children)
                    {
                        if (child.IsChecked == true)
                            yield return child;
    
                        foreach (var item in child.GetAllCheckedChildren())
                            yield return item;
                    }
                }
            }
        }
    }
    
    

    המודל יורש מודל אחר שימושי בשם ViewModelBase המהווה בסיס טוב עבור כל viewModle ב-Wpf

    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Runtime.CompilerServices;
    
    namespace MyModels
    {
        public class ViewModelBase : INotifyPropertyChanged
        {
            public event PropertyChangedEventHandler PropertyChanged;
    
            protected virtual void OnPropertyChanged(string propertyName)
            {
                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
            }
    
            protected bool SetProperty<T>(ref T field, T value, [CallerMemberName] string propertyName = null)
            {
                if (EqualityComparer<T>.Default.Equals(field, value)) return false;
                field = value;
                OnPropertyChanged(propertyName);
                return true;
            }
        }
    
    }
    
    

  • מדריך: איך לייצר לוקליזציה ב-wpf בצורה פשוטה וקלילה
    pcinfogmachP pcinfogmach

    פתרון פשוט וקליל ללוקליזציה באפליקציות WPF

    (הקוד נמצא בסוף הכתבה)

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

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

    למעשה, עבור יישומים שאינם דורשים מורכבות כזו, גישה זו יכולה לחסוך הרבה זמן ומאמץ.

    השלבים לבניית הפתרון:
    א. שימוש בקובץ JSON
    קובץ JSON מאפשר לנו לנהל ולערוך את כל המחרוזות של האפליקציה בצורה מסודרת ונוחה. המפתח (Key) מייצג את שם הפריט, והערך (Value) מייצג את המחרוזת המתורגמת.
    עבור כל שפה נייצר קובץ נפרד עם הקידומת של השפה בתוך התיקייה הייעודית (בקוד להלן אני בחרתי "Asstes//Locale").
    הקידומת תהיה בת שני אותיות בלבד ובאותיות קטנות למשל "he" או "en".
    שימו לב! בקוד שכתבתי שפת המערכת מזוהה באופן אוטומטי ייתכן וגישה זו איננה מתאימה לכם.
    ב. שימוש במבנה Dictionary סטטי
    אנו נטען את תוכן ה-JSON לקובץ זיכרון באמצעות מילון (Dictionary) סטטי, שיהיה זמין לכל רכיבי האפליקציה.
    ג. שימוש ב-Markup Extension
    ניצור הרחבה מותאמת אישית (Markup Extension) שתאפשר לנו לגשת למחרוזות מתוך ה-JSON ישירות מתוך ה-XAML. (כמו"כ נוכל לצפות בתוצאות בתצוגה המקדימה של עורך ה-Xaml).

    דגשים חשובים לניהול הפתרון:

    • שמות זהים לשמות הפקדים: הקפידו על כך ששמות המפתחות ב-JSON יהיו זהים לשמות הפקדים שאותם הם מתארים. כך, תוכלו לשמור על עקביות ולמנוע טעויות.

    • מבנה עם תיאור ברור: הוסיפו תיאור לכל מפתח בקובץ ה-JSON, כך שיהיה קל להבין מה הוא מייצג. מומלץ לצורך זה להשתמש בתיאורים המובנים של WPF. לדוגמה:

    {
        "Tooltip.MinimizeButton": "Minimize",
        "Tooltip.CloseButton": "Close",
        "Title.MainWindowTitle": "My Application"
    }
    

    העיקרון הזה יקל עליכם גם בכתיבת ה-JSON וגם בייחוס המפתחות ישירות מתוך ה-XAML.
    סדר אלפא ביתי של המפתחות ייקל על עריכת שינויים והתמצאות כללית ב-JSON.

    להלן הקוד:

    using System.Globalization;
    using System.IO;
    using System.Text.Json;
    using System.Text.RegularExpressions;
    using System.Windows;
    using System.Windows.Markup;
    
    namespace Assets.Locale
    {
     public class LocalizedStringExtension : MarkupExtension
     {
         public string Key { get; set; }
    
         public LocalizedStringExtension() { }
         public LocalizedStringExtension(string key) { Key = key; }
    
         public override object ProvideValue(IServiceProvider serviceProvider)
         {
             if (string.IsNullOrEmpty(Key)) return "[Missing Key]"; 
             else  return LocaleHelper.LocaleDictionary.TryGetValue(Key, out var value) ? value : $"[{Key}]";
         }
     }
    
        public static class LocaleHelper
        {
            private static readonly string LocaleDir = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Assets", "Locale");
            private static string LocalePath =>
                Path.Combine(LocaleDir, $"{CultureInfo.CurrentCulture.TwoLetterISOLanguageName}.json") is string path && File.Exists(path)
                    ? path
                    : Path.Combine(LocaleDir, "en.json");
    
            private static Dictionary<string, string>? _localeDictionary;
            public static Dictionary<string, string> LocaleDictionary => _localeDictionary ??= LoadLocaleDictionary();
    
            private static Dictionary<string, string> LoadLocaleDictionary()
            {
                if (!File.Exists(LocalePath))
                    return new Dictionary<string, string>();
    
                try
                {
                    string json = File.ReadAllText(LocalePath);
                    return JsonSerializer.Deserialize<Dictionary<string, string>>(json) ?? new Dictionary<string, string>();
                }
                catch
                {
                    // Return an empty dictionary if reading or deserialization fails
                    return new Dictionary<string, string>();
                }
            }
        }
    }
    
    

    ובתוך ה-xaml יש להוסיף

     xmlns:locale="clr-namespace:Assets.Locale"
    

    ואז תוכלו למשל לעשות כך

      <Button x:Name="MinimizeButton"
      ToolTip="{locale:LocalizedString Key='Tooltip.MinimizeButton'}">
    

  • קוד ל- treeview ב- html כולל חיפוש
    pcinfogmachP pcinfogmach

    קוד ל- treeview ב- html כולל חיפוש - אשמח לקבל משוב - תודה

    עריכה: עשיתי המון שיפורים מצו"ב דוגמא מליאה.
    בגירסה זו ה-treeview נוצר באופן דינאמי לפי הכותרות שבמסמך
    (נחסם לי משום מה בנטפרי ה-jsfiddle שלו תוכלו להעתיק את הקוד לכאן כדי לראות את התוצאה).

    <!DOCTYPE html>
    <html lang="he">
    <head>
    <meta charset="UTF-8">
    <style>
    html, body {
      height: 100%;
      margin: 0;
      padding: 0;
    }
    
    .container {
      display: flex;
      height: 100%;
    }
    
    .textContentBox {
      background-color: white;
      flex: 1;
      height: 100%;
      margin: 5px;
      padding: 5px;
      overflow-y: auto;
    }
    
    .treeView-container {
       -webkit-touch-callout: none; /* iOS Safari */
        -webkit-user-select: none; /* Safari */
        -khtml-user-select: none; /* Konqueror HTML */
        -moz-user-select: none; /* Firefox */
        -ms-user-select: none; /* Internet Explorer/Edge */
        user-select: none; /* Non-prefixed version, currently supported by Chrome and Opera */
      max-width: 35%;
      background-color: whitesmoke;
      display: flex;
      flex-direction: column;
      margin: 5px;
      padding: 5px;
      height: 100%;
    }
    
    #treeView-SearchInput {
      height:25px;
      border: 1px solid #ccc;
    }
    
    #treeView-SearchInput:focus {
      outline: none;
    }
    
    .treeView {
     height:100%;
      overflow: auto;
      margin-top: 5px;
      white-space: nowrap;
      text-indent: -40px;
    }
    
    .treeView details {
      border-top: 1px solid  #eaeaea;
      border-bottom: 1px solid  #eaeaea;
    }
    
    .treeView summary::-webkit-details-marker {
        display: none;
    }
    
    .treeView summary {
        transition: background-color 0.3s ease;
        list-style: none;
    }
    
    .treeView summary:hover {
      background-color: #eaeaea;
    }
    
    .treeView Button {
      background: none;
      border: none;
      cursor: pointer;
      font-weight: 500;
      margin: 5px;
      transition: background-color 0.3s ease;
      border-radius: 50px;
    }
    
    .treeView button:hover {
      background-color: #eaeaea;
    }
    
    </style>
    </head>
    <body dir="rtl">
    
    <div class="container">
        
      <div class="treeView-container">
          
        <input type="text" id="treeView-SearchInput" onkeyup="findAndSelectItem()" placeholder="חפש כותרת...">
        
        <div class="treeView" id="treeView"> </div>
        
      </div>
      
      <div class="textContentBox" id="contentBox">
      <h2 id="בעל הטורים בראשית המאור, פרק א">פרק א</h2>
    <h3 id="בעל הטורים בראשית המאור, פרק א, פסוק א">פסוק א</h3>
    בראשית ברא. בגימטריא בראש השנה נברא (העולם), בראשית נוטריקון בראשונה ראה אלהים שיקבלו ישראל תורה.<p>
    בראשית ברא אלהים ס''ת אמת מלמד שברא העולם באמת כמו שנאמר ראש דברך אמת וכן יש הרבה פסוקים ס''ת אמת:<p>
    <h3 id="בעל הטורים בראשית המאור, פרק א, פסוק ב">פסוק ב</h3>
    "תֹהוּ וָבֹהוּ" – ב'. הכא, ואידך: "רָאִיתִי אֶת הָאָרֶץ וְהִנֵּה תֹהוּ וָבֹהוּ" (ירמיהו ד כג). מלמד שצפה הקב"ה בבריאת העולם בחורבן הבית, שנחרב בשנת תה"ו, שהרי הבית הראשון עמד ת"י שנה, ונחרב בשנת תי"א. ובית שני עמד כמנין הית"ה, וזהו "וְהָאָרֶץ הָיְתָה". ואחר כך "חֹשֶׁךְ", רמז לגלויות. וכן דורש בבראשית רבה. דבר אחר: "וְהָאָרֶץ הָיְתָה תֹהוּ וָבֹהוּ" – בגימטריא "אלפים שנה בלי תורה".<p>
    "וְרוּחַ אֱלֹהִים מְרַחֶפֶת" – בגימטריא: "זו היא רוחו של מלך המשיח".<p>
    "וְחֹשֶׁךְ עַל פְּנֵי תְהוֹם" – ב' במסורת. הכא, ואידך: "וְחֹשֶׁךְ אֵי זֶה מְקֹמוֹ" (איוב לח יט). זה הוא שאמרו (חגיגה יא ב), שאין לשאול: "מה לפנים? מה לאחור?" "וְחֹשֶׁךְ אֵי זֶה מְקֹמוֹ", פירוש, שאין לשאול אי זה היה מקום החושך תחילה.<p>
    "וְרוּחַ אֱלֹהִים" – ב' דסמיכי. הכא, ואידך: "וְרוּחַ אֱלֹהִים לָבְשָׁה אֶת זְכַרְיָה" (דברי הימים ב כד כ). קרי ביה הכא נמי: "וְרוּחַ אֱלֹהִים לָבְשָׁה". פירוש, שעל ידי לבושו אמר "וַיְהִי אוֹר", דכתיב בתריה: "וַיֹּאמֶר אֱלֹהִים יְהִי אוֹר". וזה הוא שדרשו רז"ל (ב"ר פרשה ג): ממעטה לבושו נבראת האורה.<p>
    <h2 id="בעל הטורים בראשית המאור, פרק לח">פרק לח</h2>
    <h3 id="בעל הטורים בראשית המאור, פרק לח, פסוק טו">פסוק טו</h3>
    פרק לח, טו <p>
    ויחשבה. ג' במסורה. הכא. ואידך: בפרשת לך לך (לעיל טו, ו) ויחשבה לו צדקה. ואידך: ויחשבה עלי לשכורה (ש"א א, יג): <p>
    לזונה. ב' במסורה. ויחשבה לזונה. איכה היתה לזונה (ישעיה א, כא). מה תמר בבזיון ולבסוף בכבוד אף ירושלים סופה בכבוד, כדכתיב (זכריה ב, ט) ולכבוד אהיה בתוכה. וזהו זאת קומתך דמתה לתמר (שה"ש ז, ח).<p>
    <h2 id="בעל הטורים בראשית המאור, פרק מד">פרק מד</h2>
    <h3 id="בעל הטורים בראשית המאור, פרק מד, פסוק יח">פסוק יח</h3>
    ויגש אליו יהודה: ס"ת שוא. שאמר לו אני שוה לך שכמו שאתה מלך גם אני מלך. ועל זה דורש במדרש (ברשית רבה צ"נ:ב') כי הנה המלכים נועדו (תהילים מ"ח:ה'):<p>
    <h2 id="בעל הטורים בראשית המאור, פרק מט">פרק מט</h2>
    <h3 id="בעל הטורים בראשית המאור, פרק מט, פסוק א">פסוק א</h3>
    ויקרא יעקב אל בניו: שביקש לגלות להם הקץ ונסתם ממנו (פסחים נו.). אמר יעקב שמא יש בכם חטא. אמרו לו תדקדק בשמותנו ולא תמצא בהם אותיות חט. ואמר להם קם אין בהם אותיות קץ (עיין ירושלמי יומא ס״פ ז׳, בבלי שם עג:).<p>
    
      </div>
    </div>
    
    <script>
    function populateTreeView() {
      const contentBox = document.getElementById('contentBox');
      const treeView = document.getElementById('treeView');
    
      let currentDetails = treeView;
      let currentIndentLevel = 0;
    
      // Loop through each heading element in contentBox
      contentBox.querySelectorAll('h1, h2, h3, h4, h5, h6').forEach(heading => {
        const indentLevel = parseInt(heading.tagName[1]);
    
        // If the current heading has a lower or equal indent level to the previous one,
        // we need to move up the tree to the appropriate parent details element
        while (currentIndentLevel >= indentLevel) {
          currentDetails = currentDetails.parentElement;
          currentIndentLevel--;
        }
    
        // Create a new details and summary elements
        const details = document.createElement('details');
        const summary = document.createElement('summary');
        const button = document.createElement('button');
        summary.style.paddingRight = 20 * indentLevel + 'px';
        button.textContent = '👁';
        button.setAttribute('onclick', `treeViewSelection('${heading.id}')`);
        button.setAttribute('title', 'הצג');
        summary.appendChild(button);
        summary.appendChild(document.createTextNode(heading.textContent));
        details.appendChild(summary);
    
        // Append the new details element to the currentDetails
        currentDetails.appendChild(details);
    
        // Update the currentDetails and currentIndentLevel for the next iteration
        currentDetails = details;
        currentIndentLevel = indentLevel;
      });
    }
    
    function treeViewSelection(id) {
      // Scroll the corresponding heading into view
      const heading = document.getElementById(id);
      if (heading) {
        heading.scrollIntoView({ behavior: 'smooth', block: 'start' });
      }
    }
    
    // Populate the tree view on page load
    window.onload = populateTreeView;
    
    
    //
    //treeView-Search
    //
    
    function findAndSelectItem() {
        var input = document.getElementById("treeView-SearchInput");
        var filter = input.value.trim().toUpperCase().replace(/,/g, '');
        var details = document.querySelectorAll("details");
        var firstMatchFound = false;
        
        // Collapse all details if filter is empty
        if (filter === "") {
             for (var i = 0; i < details.length; i++) {
            details[i].open = false;
            var summary = details[i].querySelector("summary");
            details[i].style.display = "";
        }
            return; // Exit function
        }
        
        for (var i = 0; i < details.length; i++) {
            var summary = details[i].querySelector("summary");
            if (summary) {
                var parentPath = getParentText(details[i]).replace(/👁/g, '').toUpperCase();
                var summaryPath = summary.textContent.replace(/👁/g, '').trim().toUpperCase();
                var fullPath = parentPath + " " + summaryPath;
                
                // Highlight matching summaries
                if (fullPath.includes(filter)) {
                     details[i].open = true;
                     details[i].style.display = "";
                     
                      if (!firstMatchFound) {
                        summary.scrollIntoView({ behavior: 'smooth', block: 'center' });
                        firstMatchFound = true;
                    }
                     
                     // Open parent details elements recursively
                    var parentDetails = details[i].parentNode;
                    while (parentDetails.tagName === 'DETAILS') {
                        parentDetails.open = true;
                        parentDetails.style.display = "";
                        parentDetails = parentDetails.parentNode;
                    }
                    
                } else {
                     details[i].open = false;
                       details[i].style.display = "none";
                }
            }
        }
    }
     
    function getParentText(element) {
        var text = "";
        var parent = element.parentNode;
        while (parent && parent.tagName.toLowerCase() === 'details') {
            var summary = parent.querySelector("summary");
            if (summary) {
                text = summary.textContent.trim() + " " + text;
            }
            parent = parent.parentNode;
        }
        return text.trim();
    }
    </script>
    
    </body>
    </html>
    
    
    
  • 1 / 1
  • התחברות

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

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