Add on

ممتاز 👌
سأكتب لك نسخة مطوّرة من الإضافة بحيث تدعم كل الحقول (input, select, checkbox, radio, textarea، وحتى file upload) وتستفيد من الأفكار الذكية التي ذكرتها:


📁 بنية الملفات

my-extension/
  ├── manifest.json
  ├── content.js
  ├── background.js
  └── sites.json

⚙️ manifest.json

{
  "manifest_version": 3,
  "name": "Smart Autofill Assistant",
  "version": "1.0",
  "permissions": ["storage", "scripting", "activeTab"],
  "background": {
    "service_worker": "background.js"
  },
  "content_scripts": [
    {
      "matches": ["<all_urls>"],
      "js": ["content.js"],
      "run_at": "document_idle"
    }
  ],
  "action": {
    "default_popup": "popup.html",
    "default_title": "Smart Autofill"
  }
}

🧠 sites.json (قاعدة بيانات الحقول)

{
  "example.com": {
    "fields": {
      "email": {
        "selector": "input[name='email'], input[type='email']",
        "type": "input",
        "value": "user@example.com"
      },
      "birthdate": {
        "selector": "input[name='dob'], input[type='date']",
        "type": "date",
        "value": "1990-01-01"
      },
      "gender": {
        "selector": "select[name='gender']",
        "type": "select",
        "value": "M",
        "synonyms": {
          "ذكر": "M",
          "أنثى": "F"
        }
      },
      "terms": {
        "selector": "input[name='terms']",
        "type": "checkbox",
        "value": true
      },
      "cv": {
        "selector": "input[type='file']",
        "type": "file",
        "value": "/files/cv.pdf"
      }
    }
  }
}

📝 content.js

// تحميل بيانات المواقع
async function loadSitesConfig() {
  return new Promise((resolve) => {
    chrome.storage.local.get(["sitesConfig"], (result) => {
      resolve(result.sitesConfig || {});
    });
  });
}

// حفظ بيانات المواقع
async function saveSitesConfig(config) {
  return new Promise((resolve) => {
    chrome.storage.local.set({ sitesConfig: config }, () => resolve());
  });
}

// ملء الحقول تلقائيًا
async function autofill() {
  const config = await loadSitesConfig();
  const hostname = window.location.hostname;
  const siteConfig = config[hostname];
  if (!siteConfig) return;

  for (const fieldName in siteConfig.fields) {
    const field = siteConfig.fields[fieldName];
    const element = document.querySelector(field.selector);
    if (!element) continue;

    switch (field.type) {
      case "input":
      case "date":
        element.value = field.value;
        element.dispatchEvent(new Event("input", { bubbles: true }));
        break;

      case "select":
        element.value = field.value;
        element.dispatchEvent(new Event("change", { bubbles: true }));
        break;

      case "checkbox":
        element.checked = !!field.value;
        element.dispatchEvent(new Event("change", { bubbles: true }));
        break;

      case "radio":
        const radio = document.querySelector(
          `${field.selector}[value="${field.value}"]`
        );
        if (radio) {
          radio.checked = true;
          radio.dispatchEvent(new Event("change", { bubbles: true }));
        }
        break;

      case "textarea":
        element.value = field.value;
        element.dispatchEvent(new Event("input", { bubbles: true }));
        break;

      case "file":
        // رفع ملفات يحتاج تفاعل المستخدم لأسباب أمان
        console.log(
          "📂 حقل رفع ملف موجود. اقترح للمستخدم رفع الملف:",
          field.value
        );
        element.style.border = "2px solid orange";
        element.title = "انقر هنا لرفع: " + field.value;
        break;
    }
  }
}

// 🧩 التقاط الحقول المدخلة يدويًا (وضع التدريب)
function captureInputs() {
  document.addEventListener(
    "change",
    async (e) => {
      const el = e.target;
      const hostname = window.location.hostname;
      const config = await loadSitesConfig();
      if (!config[hostname]) config[hostname] = { fields: {} };

      let type = "input";
      if (el.tagName === "SELECT") type = "select";
      if (el.type === "checkbox") type = "checkbox";
      if (el.type === "radio") type = "radio";
      if (el.tagName === "TEXTAREA") type = "textarea";
      if (el.type === "file") type = "file";

      config[hostname].fields[el.name || el.id || type] = {
        selector: getUniqueSelector(el),
        type,
        value:
          type === "checkbox"
            ? el.checked
            : type === "file"
            ? "يرجى إعادة رفع الملف"
            : el.value
      };

      await saveSitesConfig(config);
      console.log("✅ تم تحديث sites.json:", config);
    },
    true
  );
}

// مساعد للحصول على selector فريد
function getUniqueSelector(el) {
  if (el.id) return `#${el.id}`;
  if (el.name) return `[name="${el.name}"]`;
  return el.tagName.toLowerCase();
}

// شغل الأوتوفيل والتدريب
autofill();
captureInputs();

📌 ملاحظات مهمة

  • حقول الملفات (file upload):
    المتصفح يمنع تعبئة ملفات تلقائيًا لأسباب أمنية (لا يمكن إدخال /files/cv.pdf مباشرة).
    👉 الحل: الإضافة تكتشف الحقل وتعرض للمستخدم تنبيه/اقتراح لرفع ملفه (مثل CV أو صورة).

  • يمكن توسيع هذا لاحقًا بحيث الإضافة تخزن آخر ملف رفعه المستخدم وتعرضه في نافذة popup ليعيد رفعه بسرعة.


هل تحب أن أضيف لك popup.html + background.js بحيث المستخدم من الواجهة يرفع CV مرة واحدة وتخزنه الإضافة وتعرضه له كلما واجه input type=file؟

تعليقات