Advertisement
Guenni007

find-snippet

May 10th, 2025 (edited)
187
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
PHP 10.22 KB | None | 0 0
  1. <?php
  2.  
  3. function window_find_button(){
  4. ?>
  5. <script>
  6. window.addEventListener("DOMContentLoaded", function () {
  7.  
  8.     // --- Helper function to escape special characters for RegExp ---
  9.     function GCM_escapeRegExp(string) {
  10.       if (string === null || string === undefined) {
  11.         return '';
  12.       }
  13.       return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
  14.     }
  15.  
  16.     // --- Function to remove previous highlights ---
  17.     function GCM_removeAllHighlights() {
  18.       const highlightedElements = document.querySelectorAll('span.custom-highlight');
  19.       highlightedElements.forEach(span => {
  20.         const parent = span.parentNode;
  21.         if (parent) {
  22.           while (span.firstChild) {
  23.             parent.insertBefore(span.firstChild, span);
  24.           }
  25.           parent.removeChild(span);
  26.           parent.normalize();
  27.         }
  28.       });
  29.     }
  30.  
  31.     // --- Function to process a single text node ---
  32.     function GCM_highlightInTextNode(textNode, searchTermRegex, firstHighlightRef, allHighlightsArray) {
  33.       const originalText = textNode.nodeValue;
  34.       let match;
  35.       const fragment = document.createDocumentFragment();
  36.       let lastIndex = 0;
  37.       let localMatchCount = 0;
  38.  
  39.       while ((match = searchTermRegex.exec(originalText)) !== null) {
  40.         localMatchCount++;
  41.         if (match.index > lastIndex) {
  42.           fragment.appendChild(document.createTextNode(originalText.substring(lastIndex, match.index)));
  43.         }
  44.         const span = document.createElement('span');
  45.         span.className = 'custom-highlight';
  46.         span.textContent = match[0];
  47.         fragment.appendChild(span);
  48.         allHighlightsArray.push(span);
  49.  
  50.         if (!firstHighlightRef.element) {
  51.           firstHighlightRef.element = span;
  52.         }
  53.         lastIndex = searchTermRegex.lastIndex;
  54.       }
  55.  
  56.       if (lastIndex < originalText.length) {
  57.         fragment.appendChild(document.createTextNode(originalText.substring(lastIndex)));
  58.       }
  59.  
  60.       if (localMatchCount > 0) {
  61.         textNode.parentNode.replaceChild(fragment, textNode);
  62.       }
  63.       return localMatchCount;
  64.     }
  65.  
  66.     // --- Recursive function to traverse DOM ---
  67.     function GCM_MarkInNodeRecursive(node, searchTermRegex, firstHighlightRef, currentTotalMatches, allHighlightsArray) {
  68.       if (node.nodeType === Node.TEXT_NODE) {
  69.         currentTotalMatches.count += GCM_highlightInTextNode(node, searchTermRegex, firstHighlightRef, allHighlightsArray);
  70.       } else if (node.nodeType === Node.ELEMENT_NODE) {
  71.         if (node.nodeName === 'SCRIPT' || node.nodeName === 'STYLE' ||
  72.             node.nodeName === 'TEXTAREA' || node.nodeName === 'INPUT' ||
  73.             node.id === 'gcmSearchUIContainer' ||
  74.             node.classList.contains('custom-highlight')) {
  75.           return;
  76.         }
  77.         const children = Array.from(node.childNodes);
  78.         for (let i = 0; i < children.length; i++) {
  79.           GCM_MarkInNodeRecursive(children[i], searchTermRegex, firstHighlightRef, currentTotalMatches, allHighlightsArray);
  80.         }
  81.       }
  82.     }
  83.  
  84.     // --- Main function to highlight all occurrences ---
  85.     function GCM_highlightAllOccurrences(searchTerm, containerNode) {
  86.       if (!searchTerm) {
  87.         return { count: 0, firstElement: null, allElements: [] };
  88.       }
  89.       const searchRegex = new RegExp(GCM_escapeRegExp(searchTerm), 'gi');
  90.       const firstHighlight = { element: null };
  91.       const totalMatches = { count: 0 };
  92.       const allHighlightedSpans = [];
  93.  
  94.       GCM_MarkInNodeRecursive(containerNode || document.body, searchRegex, firstHighlight, totalMatches, allHighlightedSpans);
  95.  
  96.       return { count: totalMatches.count, firstElement: firstHighlight.element, allElements: allHighlightedSpans };
  97.     }
  98.  
  99.  
  100.     // --- Draggable Logic ---
  101.     function GCM_makeDraggable(element, handle) {
  102.       let currentX, currentY, initialX, initialY;
  103.       let xOffset = 0, yOffset = 0;
  104.  
  105.       handle.onmousedown = dragMouseDown;
  106.  
  107.       function dragMouseDown(e) {
  108.         e = e || window.event;
  109.         e.preventDefault(); // Prevent text selection while dragging
  110.         // Get the mouse cursor position at startup:
  111.         initialX = e.clientX;
  112.         initialY = e.clientY;
  113.  
  114.         document.onmouseup = closeDragElement;
  115.         // Call a function whenever the cursor moves:
  116.         document.onmousemove = elementDrag;
  117.       }
  118.  
  119.       function elementDrag(e) {
  120.         e = e || window.event;
  121.         e.preventDefault();
  122.         // Calculate the new cursor position:
  123.         currentX = initialX - e.clientX;
  124.         currentY = initialY - e.clientY;
  125.         initialX = e.clientX;
  126.         initialY = e.clientY;
  127.         // Set the element's new position:
  128.         element.style.top = (element.offsetTop - currentY) + "px";
  129.         element.style.left = (element.offsetLeft - currentX) + "px";
  130.       }
  131.  
  132.       function closeDragElement() {
  133.         // Stop moving when mouse button is released:
  134.         document.onmouseup = null;
  135.         document.onmousemove = null;
  136.       }
  137.     }
  138.  
  139.     // --- Search UI State and Management ---
  140.     let GCM_searchUIContainer = null; // Renamed
  141.     let GCM_searchInputDraggable = null; // Renamed
  142.     let GCM_searchResultsCountDraggable = null; // Renamed
  143.     let GCM_highlightedElements = [];
  144.     let GCM_currentHighlightIndex = -1;
  145.  
  146.     function GCM_createSearchUI() {
  147.       if (document.getElementById('gcmSearchUIContainer')) {
  148.         GCM_searchUIContainer = document.getElementById('gcmSearchUIContainer');
  149.         GCM_searchInputDraggable = document.getElementById('gcmSearchInputDraggable');
  150.         GCM_searchResultsCountDraggable = document.getElementById('gcmResultsCountDraggable');
  151.         GCM_searchUIContainer.classList.remove('hidden');
  152.         if (GCM_searchInputDraggable) GCM_searchInputDraggable.focus();
  153.         return;
  154.       }
  155.  
  156.       GCM_searchUIContainer = document.createElement('div');
  157.       GCM_searchUIContainer.id = 'gcmSearchUIContainer';
  158.       GCM_searchUIContainer.innerHTML = `
  159.         <div id="gcmSearchUIHeader">
  160.           <span class="gcm-title">Find on Page</span>
  161.           <button id="gcmCloseSearchBtnDraggable" title="Close Search">&times;</button>
  162.         </div>
  163.         <div id="gcmSearchUIBody">
  164.           <input type="text" id="gcmSearchInputDraggable" placeholder="Enter search term...">
  165.           <div class="gcm-controls-row">
  166.             <button id="gcmSearchBtnDraggable">Find</button>
  167.             <div class="gcm-navigation">
  168.                 <button id="gcmPrevBtnDraggable" title="Previous">&lt;</button>
  169.                 <button id="gcmNextBtnDraggable" title="Next">&gt;</button>
  170.             </div>
  171.           </div>
  172.           <div class="gcm-controls-row">
  173.             <span id="gcmResultsCountDraggable" class="gcm-results-count-draggable">0 of 0</span>
  174.           </div>
  175.         </div>
  176.       `;
  177.       document.body.appendChild(GCM_searchUIContainer);
  178.  
  179.       GCM_searchInputDraggable = document.getElementById('gcmSearchInputDraggable');
  180.       GCM_searchResultsCountDraggable = document.getElementById('gcmResultsCountDraggable');
  181.       const header = document.getElementById('gcmSearchUIHeader');
  182.  
  183.       document.getElementById('gcmSearchBtnDraggable').addEventListener('click', GCM_performSearch);
  184.       if (GCM_searchInputDraggable) {
  185.         GCM_searchInputDraggable.addEventListener('keydown', function(e) {
  186.           if (e.key === 'Enter') {
  187.             e.preventDefault(); // Prevent form submission if it's in one
  188.             GCM_performSearch();
  189.           }
  190.         });
  191.       }
  192.       document.getElementById('gcmNextBtnDraggable').addEventListener('click', GCM_navigateToNext);
  193.       document.getElementById('gcmPrevBtnDraggable').addEventListener('click', GCM_navigateToPrevious);
  194.       document.getElementById('gcmCloseSearchBtnDraggable').addEventListener('click', GCM_closeSearchUI);
  195.  
  196.       if (GCM_searchInputDraggable) GCM_searchInputDraggable.focus();
  197.       if (header && GCM_searchUIContainer) GCM_makeDraggable(GCM_searchUIContainer, header); // Make it draggable
  198.     }
  199.  
  200.     function GCM_closeSearchUI() {
  201.       if (GCM_searchUIContainer) {
  202.         GCM_searchUIContainer.classList.add('hidden');
  203.       }
  204.       GCM_removeAllHighlights();
  205.       GCM_highlightedElements = [];
  206.       GCM_currentHighlightIndex = -1;
  207.       if (GCM_searchResultsCountDraggable) GCM_searchResultsCountDraggable.textContent = "0 of 0";
  208.       if (GCM_searchInputDraggable) GCM_searchInputDraggable.value = ""; // Clear input on close
  209.     }
  210.  
  211.     function GCM_performSearch() {
  212.       if (!GCM_searchInputDraggable) return;
  213.       const searchTerm = GCM_searchInputDraggable.value;
  214.       GCM_removeAllHighlights(); // Always remove old highlights
  215.       GCM_highlightedElements = [];
  216.       GCM_currentHighlightIndex = -1;
  217.  
  218.       if (searchTerm.trim() === "") {
  219.         if (GCM_searchResultsCountDraggable) GCM_searchResultsCountDraggable.textContent = "0 of 0";
  220.         return;
  221.       }
  222.  
  223.       const result = GCM_highlightAllOccurrences(searchTerm, document.body);
  224.       GCM_highlightedElements = result.allElements;
  225.  
  226.       if (result.count > 0) {
  227.         GCM_currentHighlightIndex = 0;
  228.         GCM_navigateToHighlight(GCM_currentHighlightIndex);
  229.       } else {
  230.         // GCM_searchResultsCountDraggable will be updated by GCM_updateResultCount
  231.       }
  232.       GCM_updateResultCount(); // Update count regardless of found or not
  233.     }
  234.  
  235.     function GCM_navigateToHighlight(index) {
  236.       if (index < 0 || index >= GCM_highlightedElements.length) return;
  237.  
  238.       const currentActive = document.querySelector('.custom-highlight.current-custom-highlight');
  239.       if (currentActive) {
  240.         currentActive.classList.remove('current-custom-highlight');
  241.       }
  242.  
  243.       const elementToScrollTo = GCM_highlightedElements[index];
  244.       if (elementToScrollTo) {
  245.         elementToScrollTo.classList.add('current-custom-highlight');
  246.         elementToScrollTo.scrollIntoView({
  247.           behavior: 'smooth',
  248.           block: 'center',
  249.           inline: 'nearest'
  250.         });
  251.       }
  252.       GCM_updateResultCount();
  253.     }
  254.  
  255.     function GCM_navigateToNext() {
  256.       if (GCM_highlightedElements.length === 0) return;
  257.       GCM_currentHighlightIndex = (GCM_currentHighlightIndex + 1) % GCM_highlightedElements.length;
  258.       GCM_navigateToHighlight(GCM_currentHighlightIndex);
  259.     }
  260.  
  261.     function GCM_navigateToPrevious() {
  262.       if (GCM_highlightedElements.length === 0) return;
  263.       GCM_currentHighlightIndex = (GCM_currentHighlightIndex - 1 + GCM_highlightedElements.length) % GCM_highlightedElements.length;
  264.       GCM_navigateToHighlight(GCM_currentHighlightIndex);
  265.     }
  266.  
  267.     function GCM_updateResultCount() {
  268.       if (GCM_searchResultsCountDraggable) {
  269.         const total = GCM_highlightedElements.length;
  270.         const current = total > 0 ? GCM_currentHighlightIndex + 1 : 0;
  271.         GCM_searchResultsCountDraggable.textContent = `${current} of ${total}`;
  272.       }
  273.     }
  274.  
  275.  
  276.     const mainFindButton = document.querySelector('.my-find-button'); // Your Enfold button
  277.  
  278.     if (mainFindButton) {
  279.       mainFindButton.addEventListener('click', function(event) {
  280.         event.preventDefault();
  281.         event.stopPropagation();
  282.         GCM_createSearchUI();
  283.       });
  284.     } else {
  285.       // console.log("Main find button (.my-find-button) not found.");
  286.     }
  287.  
  288.    
  289. });
  290. </script>
  291. <?php
  292. }
  293. add_action('wp_footer', 'window_find_button');
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement