Auto-deploy: 2026-05-17 02:26:43
This commit is contained in:
93
content.js
93
content.js
@@ -228,28 +228,76 @@
|
|||||||
|
|
||||||
function extractApplicationQuestions() {
|
function extractApplicationQuestions() {
|
||||||
const questions = [];
|
const questions = [];
|
||||||
const modal = document.querySelector('.artdeco-modal, .jobs-easy-apply-modal, #artdeco-modal-outlet');
|
|
||||||
if (!modal) return questions;
|
|
||||||
|
|
||||||
const labels = modal.querySelectorAll('label, legend');
|
|
||||||
const seen = new Set();
|
const seen = new Set();
|
||||||
|
|
||||||
labels.forEach(label => {
|
// Strategy 1: Look inside known modal containers
|
||||||
let text = label.textContent.replace(/\*/g, '').replace(/Submit/i, '').trim();
|
const containers = document.querySelectorAll(
|
||||||
if (text && text.length > 5 && text.length < 200 && !seen.has(text)) {
|
'.artdeco-modal, .jobs-easy-apply-modal, #artdeco-modal-outlet, ' +
|
||||||
seen.add(text);
|
'.jobs-easy-apply-content, .jobs-easy-apply-form-section__grouping, ' +
|
||||||
|
'[data-test-modal], [role="dialog"]'
|
||||||
|
);
|
||||||
|
|
||||||
|
// Strategy 2: If no modal found, scan the full page
|
||||||
|
const searchRoots = containers.length > 0 ? containers : [document.body];
|
||||||
|
|
||||||
|
searchRoots.forEach(container => {
|
||||||
|
// Scan labels, legends, spans that look like question text
|
||||||
|
const candidates = container.querySelectorAll(
|
||||||
|
'label, legend, .fb-dash-form-element__label, ' +
|
||||||
|
'.jobs-easy-apply-form-element__label, ' +
|
||||||
|
'span.t-14, span.t-bold'
|
||||||
|
);
|
||||||
|
|
||||||
|
candidates.forEach(el => {
|
||||||
|
let text = el.textContent.replace(/\*/g, '').replace(/required/gi, '').trim();
|
||||||
|
// Remove "Select an option" and similar noise
|
||||||
|
text = text.replace(/Select an option/gi, '').replace(/Show less|Show more/gi, '').trim();
|
||||||
|
|
||||||
|
if (!text || text.length < 8 || text.length > 300 || seen.has(text.toLowerCase())) return;
|
||||||
|
|
||||||
|
// Only accept text that looks like a question or form label
|
||||||
|
const isQuestion = (
|
||||||
|
text.endsWith('?') ||
|
||||||
|
/^(how many|what|do you|are you|have you|will you|can you|would you|is your|describe|tell us)/i.test(text) ||
|
||||||
|
/salary|experience|education|degree|visa|relocat|notice period|start date|certif/i.test(text)
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!isQuestion) return;
|
||||||
|
|
||||||
|
seen.add(text.toLowerCase());
|
||||||
|
|
||||||
|
// Detect input type from nearest form element
|
||||||
let inputType = 'text';
|
let inputType = 'text';
|
||||||
const parent = label.closest('div') || label.parentElement;
|
const parent = el.closest('.fb-dash-form-element, .jobs-easy-apply-form-section__grouping, div') || el.parentElement;
|
||||||
if (parent.querySelector('select')) inputType = 'select';
|
if (parent) {
|
||||||
else if (parent.querySelector('input[type="radio"]')) inputType = 'radio';
|
if (parent.querySelector('select')) inputType = 'select';
|
||||||
else if (parent.querySelector('textarea')) inputType = 'textarea';
|
else if (parent.querySelector('input[type="radio"]')) inputType = 'radio';
|
||||||
else if (parent.querySelector('input[type="checkbox"]')) inputType = 'checkbox';
|
else if (parent.querySelector('textarea')) inputType = 'textarea';
|
||||||
|
else if (parent.querySelector('input[type="checkbox"]')) inputType = 'checkbox';
|
||||||
|
else if (parent.querySelector('input[type="number"]')) inputType = 'number';
|
||||||
|
}
|
||||||
|
|
||||||
questions.push({ question: text, type: inputType });
|
questions.push({ question: text, type: inputType });
|
||||||
}
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Strategy 3: Last resort — scan ALL visible text for question patterns
|
||||||
|
if (questions.length === 0) {
|
||||||
|
const allSpans = document.querySelectorAll('span, label, legend, p');
|
||||||
|
allSpans.forEach(el => {
|
||||||
|
const text = el.textContent.replace(/\*/g, '').trim();
|
||||||
|
if (text && text.endsWith('?') && text.length > 10 && text.length < 200 && !seen.has(text.toLowerCase())) {
|
||||||
|
// Make sure this is a visible form question, not random page text
|
||||||
|
const rect = el.getBoundingClientRect();
|
||||||
|
if (rect.width > 0 && rect.height > 0 && rect.top > 0 && rect.top < window.innerHeight) {
|
||||||
|
seen.add(text.toLowerCase());
|
||||||
|
questions.push({ question: text, type: 'text' });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('[LJA] Scraped questions:', questions);
|
||||||
return questions.slice(0, 15);
|
return questions.slice(0, 15);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -586,7 +634,15 @@
|
|||||||
const isArabic = /[\u0600-\u06FF]/.test(text);
|
const isArabic = /[\u0600-\u06FF]/.test(text);
|
||||||
const rtlAttr = isArabic ? 'dir="rtl" style="text-align: right; padding-right: 15px;"' : '';
|
const rtlAttr = isArabic ? 'dir="rtl" style="text-align: right; padding-right: 15px;"' : '';
|
||||||
|
|
||||||
|
// For Q&A, show how many questions were detected
|
||||||
|
const qaHeader = (tab === 'qa' && jobData.questions)
|
||||||
|
? `<div style="background:rgba(108,99,255,0.2);padding:6px 10px;border-radius:6px;margin-bottom:10px;font-size:12px;color:#b0b0ff;">
|
||||||
|
🔍 Detected <strong>${jobData.questions.length}</strong> question(s) from Easy Apply form
|
||||||
|
</div>`
|
||||||
|
: '';
|
||||||
|
|
||||||
pane.innerHTML = `
|
pane.innerHTML = `
|
||||||
|
${qaHeader}
|
||||||
<div class="lja-result" ${rtlAttr}>
|
<div class="lja-result" ${rtlAttr}>
|
||||||
${renderMarkdown(text)}
|
${renderMarkdown(text)}
|
||||||
</div>
|
</div>
|
||||||
@@ -595,7 +651,7 @@
|
|||||||
copyBtn.style.display = 'block';
|
copyBtn.style.display = 'block';
|
||||||
|
|
||||||
// Show auto-fill button for Q&A tab
|
// Show auto-fill button for Q&A tab
|
||||||
if (tab === 'qa' && jobData.questions.length > 0) {
|
if (tab === 'qa') {
|
||||||
const fillBtn = document.createElement('button');
|
const fillBtn = document.createElement('button');
|
||||||
fillBtn.className = 'lja-fill-btn';
|
fillBtn.className = 'lja-fill-btn';
|
||||||
fillBtn.textContent = '📝 Auto-fill Answers';
|
fillBtn.textContent = '📝 Auto-fill Answers';
|
||||||
@@ -804,7 +860,12 @@ Brief honest assessment of this opportunity for my profile`
|
|||||||
}
|
}
|
||||||
|
|
||||||
let filled = 0;
|
let filled = 0;
|
||||||
const labels = document.querySelectorAll('.jobs-easy-apply-content label, .jobs-easy-apply-content legend, .jobs-easy-apply-content .fb-dash-form-element__label');
|
const labels = document.querySelectorAll(
|
||||||
|
'.jobs-easy-apply-content label, .jobs-easy-apply-content legend, ' +
|
||||||
|
'.artdeco-modal label, .artdeco-modal legend, ' +
|
||||||
|
'[role="dialog"] label, [role="dialog"] legend, ' +
|
||||||
|
'#artdeco-modal-outlet label, #artdeco-modal-outlet legend'
|
||||||
|
);
|
||||||
|
|
||||||
labels.forEach(label => {
|
labels.forEach(label => {
|
||||||
const qText = label.textContent.trim().toLowerCase();
|
const qText = label.textContent.trim().toLowerCase();
|
||||||
|
|||||||
Reference in New Issue
Block a user