diff --git a/search_analyzer.js b/search_analyzer.js index 185db9a..a8a6c0a 100644 --- a/search_analyzer.js +++ b/search_analyzer.js @@ -31,7 +31,7 @@ // ─── Find Result Container ─────────────────────────────────────────────── function getSearchResultsContainer() { - return document.querySelector('.search-results-container, .reusable-search__entity-result-list, ul.reusable-search__entity-result-list'); + return document.querySelector('.search-results-container, .reusable-search__entity-result-list, ul.reusable-search__entity-result-list, .search-results__list'); } // ─── Extract Person Data ───────────────────────────────────────────────── @@ -43,30 +43,38 @@ summary: '' }; - // Name - const nameEl = cardEl.querySelector('.entity-result__title-text a span[dir="ltr"], .entity-result__title-line a span[dir="ltr"], span.entity-result__title-text, .app-aware-link span[dir="ltr"]'); + // 1. Extract Name (Usually inside a link with /in/) + const nameEl = cardEl.querySelector('.entity-result__title-text, .search-result__title, span[dir="ltr"]'); if (nameEl) { - data.name = nameEl.innerText.trim(); + data.name = nameEl.innerText.trim().split('\n')[0]; + } else { + const profileLinks = Array.from(cardEl.querySelectorAll('a[href*="/in/"]')).filter(a => a.innerText.trim().length > 0); + if (profileLinks.length > 0) { + data.name = profileLinks[0].innerText.trim().split('\n')[0]; + } } - // Headline - const headlineEl = cardEl.querySelector('.entity-result__primary-subtitle'); + // 2. Extract Headline + const headlineEl = cardEl.querySelector('.entity-result__primary-subtitle, .search-result__truncate, .linked-area'); if (headlineEl) { data.headline = headlineEl.innerText.trim(); } - // Location - const locationEl = cardEl.querySelector('.entity-result__secondary-subtitle'); + // 3. Extract Location + const locationEl = cardEl.querySelector('.entity-result__secondary-subtitle, .search-result__info'); if (locationEl) { data.location = locationEl.innerText.trim(); } - // Summary/Snippet - const summaryEl = cardEl.querySelector('.entity-result__summary'); + // 4. Extract Summary + const summaryEl = cardEl.querySelector('.entity-result__summary, .search-result__snippets'); if (summaryEl) { data.summary = summaryEl.innerText.trim(); } + // Clean up "View Profile" texts + data.name = data.name.replace(/View .* profile/gi, '').trim(); + return data; } @@ -74,14 +82,20 @@ function injectScanButton(cardEl) { if (cardEl.querySelector('.lja-scan-person-btn') || cardEl.querySelector('.lja-investor-result')) return; - // Find a good place to put the button. Usually near the title or actions. - const actionArea = cardEl.querySelector('.entity-result__actions') || cardEl.querySelector('.entity-result__item'); - if (!actionArea) return; - const btn = document.createElement('button'); btn.className = 'lja-scan-person-btn'; btn.innerHTML = '🔍 Scan Investor'; + // Add some basic styling just in case CSS fails to load or apply correctly + btn.style.margin = '10px 0'; + btn.style.padding = '5px 15px'; + btn.style.cursor = 'pointer'; + btn.style.backgroundColor = '#6C63FF'; + btn.style.color = '#fff'; + btn.style.border = 'none'; + btn.style.borderRadius = '5px'; + btn.style.fontWeight = 'bold'; + // Create a container for the result const resultContainer = document.createElement('div'); resultContainer.className = 'lja-result-wrapper'; @@ -92,16 +106,16 @@ await scanPerson(cardEl, btn, resultContainer); }); - // Try to append button to actions area if possible, else to the item - if (actionArea.classList.contains('entity-result__actions')) { + // Try to append to actions area, if not just append at the end of the card + const actionArea = cardEl.querySelector('.entity-result__actions, .search-result__actions'); + if (actionArea) { actionArea.prepend(btn); } else { - const titleLine = cardEl.querySelector('.entity-result__title-line') || actionArea; - titleLine.appendChild(btn); + cardEl.appendChild(btn); } cardEl.appendChild(resultContainer); - console.log('[LJA] Injected button for a profile'); + console.log('[LJA] Injected button for a profile:', extractPersonData(cardEl).name); } // ─── Scan a Single Person ──────────────────────────────────────────────── @@ -171,11 +185,11 @@ const colorClass = isGreen ? 'green' : 'red'; resultContainer.innerHTML = ` -
-
+
+
${badgeIcon} ${badgeText}
-
+
${resultData.reason}
@@ -185,7 +199,7 @@ } catch (e) { console.error('[LJA Search]', e); - resultContainer.innerHTML = `
❌ Error: ${e.message}
`; + resultContainer.innerHTML = `
❌ Error: ${e.message}
`; btnEl.disabled = false; btnEl.innerHTML = '🔍 Scan Investor'; } @@ -195,17 +209,31 @@ function injectScanAllButton() { if (document.querySelector('.lja-scan-list-btn')) return; - const container = getSearchResultsContainer(); - if (!container) return; + let container = getSearchResultsContainer(); const btn = document.createElement('button'); btn.className = 'lja-scan-list-btn'; btn.innerHTML = '✨ Scan All Investors'; btn.title = 'Scan all loaded profiles on this page'; + + // Robust styling for the Scan All button + btn.style.margin = '20px auto'; + btn.style.display = 'block'; + btn.style.padding = '10px 20px'; + btn.style.cursor = 'pointer'; + btn.style.backgroundColor = '#6C63FF'; + btn.style.color = '#fff'; + btn.style.border = 'none'; + btn.style.borderRadius = '8px'; + btn.style.fontWeight = 'bold'; + btn.style.fontSize = '16px'; + btn.style.boxShadow = '0 4px 6px rgba(0,0,0,0.1)'; btn.addEventListener('click', async () => { - // Allow broader class matches for people cards - const cards = document.querySelectorAll('.reusable-search__result-container, li.search-result__occluded-item, li.search-result'); + // Find all cards using our robust selector + const allLis = Array.from(document.querySelectorAll('li')); + const cards = allLis.filter(li => li.querySelector('a[href*="/in/"]')); + if (cards.length === 0) { alert('No profiles found to scan.'); return; @@ -214,15 +242,13 @@ btn.disabled = true; btn.innerHTML = ' Scanning profiles...'; - // Scan sequentially to avoid hammering the API + // Scan sequentially for (const card of cards) { const scanBtn = card.querySelector('.lja-scan-person-btn'); if (scanBtn && scanBtn.style.display !== 'none') { - // Scroll to card card.scrollIntoView({ behavior: 'smooth', block: 'center' }); - await new Promise(r => setTimeout(r, 500)); // Small delay + await new Promise(r => setTimeout(r, 500)); scanBtn.click(); - // Wait for result while (scanBtn.disabled && scanBtn.style.display !== 'none') { await new Promise(r => setTimeout(r, 500)); } @@ -234,18 +260,32 @@ setTimeout(() => { btn.innerHTML = '✨ Scan All Investors'; }, 3000); }); - container.parentNode.insertBefore(btn, container); + if (container && container.parentNode) { + container.parentNode.insertBefore(btn, container); + } else { + // Fallback: Floating button bottom right + btn.style.position = 'fixed'; + btn.style.bottom = '20px'; + btn.style.right = '20px'; + btn.style.zIndex = '99999'; + btn.style.margin = '0'; + document.body.appendChild(btn); + } console.log('[LJA] Injected Scan All button'); } // ─── Process Page ──────────────────────────────────────────────────────── function processPage() { - // Prevent running outside of search page just in case if (!window.location.href.includes('linkedin.com/search/results/')) return; - injectScanAllButton(); - const cards = document.querySelectorAll('.reusable-search__result-container, li.search-result__occluded-item, li.search-result'); + // Robustly find any
  • that contains a link to a LinkedIn profile + const allLis = Array.from(document.querySelectorAll('li')); + const cards = allLis.filter(li => li.querySelector('a[href*="/in/"]')); + + console.log('[LJA] processPage found cards:', cards.length); + if (cards.length > 0) { + injectScanAllButton(); cards.forEach(injectScanButton); } } @@ -257,7 +297,7 @@ observerTimer = setTimeout(() => { processPage(); observerTimer = null; - }, 800); + }, 1500); }); // ─── Initialize ────────────────────────────────────────────────────────── @@ -265,9 +305,6 @@ console.log('[LJA] Initializing Search Analyzer...'); processPage(); observer.observe(document.body, { childList: true, subtree: true }); - - // Listen for SPA navigation from background script if implemented, - // or just rely on MutationObserver for body changes when URL changes } // Handle SPA navigation by checking URL changes @@ -276,7 +313,8 @@ if (window.location.href !== lastUrl) { lastUrl = window.location.href; if (lastUrl.includes('linkedin.com/search/results/')) { - setTimeout(processPage, 1500); + console.log('[LJA] SPA Navigation detected, re-processing...'); + setTimeout(processPage, 2000); } } }, 1000); @@ -285,6 +323,6 @@ document.addEventListener('DOMContentLoaded', init); } else { init(); - setTimeout(init, 2000); // Fallback for delayed renders + setTimeout(init, 3000); // Fallback for delayed renders } })();