Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- <?php
- function window_find_button(){
- ?>
- <script>
- window.addEventListener("DOMContentLoaded", function () {
- // --- Helper function to escape special characters for RegExp ---
- function GCM_escapeRegExp(string) {
- if (string === null || string === undefined) {
- return '';
- }
- return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
- }
- // --- Function to remove previous highlights ---
- function GCM_removeAllHighlights() {
- const highlightedElements = document.querySelectorAll('span.custom-highlight');
- highlightedElements.forEach(span => {
- const parent = span.parentNode;
- if (parent) {
- while (span.firstChild) {
- parent.insertBefore(span.firstChild, span);
- }
- parent.removeChild(span);
- parent.normalize();
- }
- });
- }
- // --- Function to process a single text node ---
- function GCM_highlightInTextNode(textNode, searchTermRegex, firstHighlightRef, allHighlightsArray) {
- const originalText = textNode.nodeValue;
- let match;
- const fragment = document.createDocumentFragment();
- let lastIndex = 0;
- let localMatchCount = 0;
- while ((match = searchTermRegex.exec(originalText)) !== null) {
- localMatchCount++;
- if (match.index > lastIndex) {
- fragment.appendChild(document.createTextNode(originalText.substring(lastIndex, match.index)));
- }
- const span = document.createElement('span');
- span.className = 'custom-highlight';
- span.textContent = match[0];
- fragment.appendChild(span);
- allHighlightsArray.push(span);
- if (!firstHighlightRef.element) {
- firstHighlightRef.element = span;
- }
- lastIndex = searchTermRegex.lastIndex;
- }
- if (lastIndex < originalText.length) {
- fragment.appendChild(document.createTextNode(originalText.substring(lastIndex)));
- }
- if (localMatchCount > 0) {
- textNode.parentNode.replaceChild(fragment, textNode);
- }
- return localMatchCount;
- }
- // --- Recursive function to traverse DOM ---
- function GCM_MarkInNodeRecursive(node, searchTermRegex, firstHighlightRef, currentTotalMatches, allHighlightsArray) {
- if (node.nodeType === Node.TEXT_NODE) {
- currentTotalMatches.count += GCM_highlightInTextNode(node, searchTermRegex, firstHighlightRef, allHighlightsArray);
- } else if (node.nodeType === Node.ELEMENT_NODE) {
- if (node.nodeName === 'SCRIPT' || node.nodeName === 'STYLE' ||
- node.nodeName === 'TEXTAREA' || node.nodeName === 'INPUT' ||
- node.id === 'gcmSearchUIContainer' ||
- node.classList.contains('custom-highlight')) {
- return;
- }
- const children = Array.from(node.childNodes);
- for (let i = 0; i < children.length; i++) {
- GCM_MarkInNodeRecursive(children[i], searchTermRegex, firstHighlightRef, currentTotalMatches, allHighlightsArray);
- }
- }
- }
- // --- Main function to highlight all occurrences ---
- function GCM_highlightAllOccurrences(searchTerm, containerNode) {
- if (!searchTerm) {
- return { count: 0, firstElement: null, allElements: [] };
- }
- const searchRegex = new RegExp(GCM_escapeRegExp(searchTerm), 'gi');
- const firstHighlight = { element: null };
- const totalMatches = { count: 0 };
- const allHighlightedSpans = [];
- GCM_MarkInNodeRecursive(containerNode || document.body, searchRegex, firstHighlight, totalMatches, allHighlightedSpans);
- return { count: totalMatches.count, firstElement: firstHighlight.element, allElements: allHighlightedSpans };
- }
- // --- Draggable Logic ---
- function GCM_makeDraggable(element, handle) {
- let currentX, currentY, initialX, initialY;
- let xOffset = 0, yOffset = 0;
- handle.onmousedown = dragMouseDown;
- function dragMouseDown(e) {
- e = e || window.event;
- e.preventDefault(); // Prevent text selection while dragging
- // Get the mouse cursor position at startup:
- initialX = e.clientX;
- initialY = e.clientY;
- document.onmouseup = closeDragElement;
- // Call a function whenever the cursor moves:
- document.onmousemove = elementDrag;
- }
- function elementDrag(e) {
- e = e || window.event;
- e.preventDefault();
- // Calculate the new cursor position:
- currentX = initialX - e.clientX;
- currentY = initialY - e.clientY;
- initialX = e.clientX;
- initialY = e.clientY;
- // Set the element's new position:
- element.style.top = (element.offsetTop - currentY) + "px";
- element.style.left = (element.offsetLeft - currentX) + "px";
- }
- function closeDragElement() {
- // Stop moving when mouse button is released:
- document.onmouseup = null;
- document.onmousemove = null;
- }
- }
- // --- Search UI State and Management ---
- let GCM_searchUIContainer = null; // Renamed
- let GCM_searchInputDraggable = null; // Renamed
- let GCM_searchResultsCountDraggable = null; // Renamed
- let GCM_highlightedElements = [];
- let GCM_currentHighlightIndex = -1;
- function GCM_createSearchUI() {
- if (document.getElementById('gcmSearchUIContainer')) {
- GCM_searchUIContainer = document.getElementById('gcmSearchUIContainer');
- GCM_searchInputDraggable = document.getElementById('gcmSearchInputDraggable');
- GCM_searchResultsCountDraggable = document.getElementById('gcmResultsCountDraggable');
- GCM_searchUIContainer.classList.remove('hidden');
- if (GCM_searchInputDraggable) GCM_searchInputDraggable.focus();
- return;
- }
- GCM_searchUIContainer = document.createElement('div');
- GCM_searchUIContainer.id = 'gcmSearchUIContainer';
- GCM_searchUIContainer.innerHTML = `
- <div id="gcmSearchUIHeader">
- <span class="gcm-title">Find on Page</span>
- <button id="gcmCloseSearchBtnDraggable" title="Close Search">×</button>
- </div>
- <div id="gcmSearchUIBody">
- <input type="text" id="gcmSearchInputDraggable" placeholder="Enter search term...">
- <div class="gcm-controls-row">
- <button id="gcmSearchBtnDraggable">Find</button>
- <div class="gcm-navigation">
- <button id="gcmPrevBtnDraggable" title="Previous"><</button>
- <button id="gcmNextBtnDraggable" title="Next">></button>
- </div>
- </div>
- <div class="gcm-controls-row">
- <span id="gcmResultsCountDraggable" class="gcm-results-count-draggable">0 of 0</span>
- </div>
- </div>
- `;
- document.body.appendChild(GCM_searchUIContainer);
- GCM_searchInputDraggable = document.getElementById('gcmSearchInputDraggable');
- GCM_searchResultsCountDraggable = document.getElementById('gcmResultsCountDraggable');
- const header = document.getElementById('gcmSearchUIHeader');
- document.getElementById('gcmSearchBtnDraggable').addEventListener('click', GCM_performSearch);
- if (GCM_searchInputDraggable) {
- GCM_searchInputDraggable.addEventListener('keydown', function(e) {
- if (e.key === 'Enter') {
- e.preventDefault(); // Prevent form submission if it's in one
- GCM_performSearch();
- }
- });
- }
- document.getElementById('gcmNextBtnDraggable').addEventListener('click', GCM_navigateToNext);
- document.getElementById('gcmPrevBtnDraggable').addEventListener('click', GCM_navigateToPrevious);
- document.getElementById('gcmCloseSearchBtnDraggable').addEventListener('click', GCM_closeSearchUI);
- if (GCM_searchInputDraggable) GCM_searchInputDraggable.focus();
- if (header && GCM_searchUIContainer) GCM_makeDraggable(GCM_searchUIContainer, header); // Make it draggable
- }
- function GCM_closeSearchUI() {
- if (GCM_searchUIContainer) {
- GCM_searchUIContainer.classList.add('hidden');
- }
- GCM_removeAllHighlights();
- GCM_highlightedElements = [];
- GCM_currentHighlightIndex = -1;
- if (GCM_searchResultsCountDraggable) GCM_searchResultsCountDraggable.textContent = "0 of 0";
- if (GCM_searchInputDraggable) GCM_searchInputDraggable.value = ""; // Clear input on close
- }
- function GCM_performSearch() {
- if (!GCM_searchInputDraggable) return;
- const searchTerm = GCM_searchInputDraggable.value;
- GCM_removeAllHighlights(); // Always remove old highlights
- GCM_highlightedElements = [];
- GCM_currentHighlightIndex = -1;
- if (searchTerm.trim() === "") {
- if (GCM_searchResultsCountDraggable) GCM_searchResultsCountDraggable.textContent = "0 of 0";
- return;
- }
- const result = GCM_highlightAllOccurrences(searchTerm, document.body);
- GCM_highlightedElements = result.allElements;
- if (result.count > 0) {
- GCM_currentHighlightIndex = 0;
- GCM_navigateToHighlight(GCM_currentHighlightIndex);
- } else {
- // GCM_searchResultsCountDraggable will be updated by GCM_updateResultCount
- }
- GCM_updateResultCount(); // Update count regardless of found or not
- }
- function GCM_navigateToHighlight(index) {
- if (index < 0 || index >= GCM_highlightedElements.length) return;
- const currentActive = document.querySelector('.custom-highlight.current-custom-highlight');
- if (currentActive) {
- currentActive.classList.remove('current-custom-highlight');
- }
- const elementToScrollTo = GCM_highlightedElements[index];
- if (elementToScrollTo) {
- elementToScrollTo.classList.add('current-custom-highlight');
- elementToScrollTo.scrollIntoView({
- behavior: 'smooth',
- block: 'center',
- inline: 'nearest'
- });
- }
- GCM_updateResultCount();
- }
- function GCM_navigateToNext() {
- if (GCM_highlightedElements.length === 0) return;
- GCM_currentHighlightIndex = (GCM_currentHighlightIndex + 1) % GCM_highlightedElements.length;
- GCM_navigateToHighlight(GCM_currentHighlightIndex);
- }
- function GCM_navigateToPrevious() {
- if (GCM_highlightedElements.length === 0) return;
- GCM_currentHighlightIndex = (GCM_currentHighlightIndex - 1 + GCM_highlightedElements.length) % GCM_highlightedElements.length;
- GCM_navigateToHighlight(GCM_currentHighlightIndex);
- }
- function GCM_updateResultCount() {
- if (GCM_searchResultsCountDraggable) {
- const total = GCM_highlightedElements.length;
- const current = total > 0 ? GCM_currentHighlightIndex + 1 : 0;
- GCM_searchResultsCountDraggable.textContent = `${current} of ${total}`;
- }
- }
- const mainFindButton = document.querySelector('.my-find-button'); // Your Enfold button
- if (mainFindButton) {
- mainFindButton.addEventListener('click', function(event) {
- event.preventDefault();
- event.stopPropagation();
- GCM_createSearchUI();
- });
- } else {
- // console.log("Main find button (.my-find-button) not found.");
- }
- });
- </script>
- <?php
- }
- add_action('wp_footer', 'window_find_button');
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement