طرائق الأداة وأحداثها
تشحن أداة Caputchin عنصرين مخصّصين، وتتفاعل صفحتك معهما باتّجاهين: تنادي طرائق على العنصر لتقوده، وتنصت لأحداث يبثّها لتتفاعل. هذه الصفحة المرجع الشامل لكلا السطحين.
كل حدث CustomEvent مُرسَل بـ bubbles: true وcomposed: true، فيفلت من DOM الظلّ للأداة وتستطيع الإنصات له مباشرةً على العنصر (أو على أي سلف). البيانات دائمًا على event.detail.
العنصران في لمحة
| العنصر | الغرض | الطرائق |
|---|---|---|
<caputchin-widget> | التحقّق فقط (proof-of-work / خانة اختيار). | start() |
<caputchin-game> | مضيف لعبة، بتحقّق اختياري. | pass()، وfail() |
أداة خانة الاختيار لها start() فقط؛ لا تكشف pass() / fail(). مضيف اللعبة لا start() له (جولته تصير حيّةً عند التركيب لـ inline، أو عند أول فتح حوار لـ modal / fullscreen). كلا العنصرين يبثّان start، وpass، وerror، وdegraded؛ ويبثّ مضيف اللعبة إضافةً dialog-shown وdialog-hidden. التغطية في جدول الأحداث أدناه.
الطرائق
start() (<caputchin-widget> فقط)
يبدأ التحقّق فورًا. غرضه المُطلِق اليدوي: حين يحمل العنصر trigger="manual"، تنادي start() لإطلاق حلّ proof-of-work من إيماءتك الخاصة (مثلًا، عند إرسال نموذجك) بدل خانة الاختيار المدمجة. مع المُطلِقَين الافتراضيين auto / click يوصّل العنصر تفعيله الخاص، فلا تناديه.
const widget = document.querySelector("caputchin-widget");
widget.start();مضيف اللعبة لا start() له. انظر الوضع اليدوي للشرح الكامل لقيادته بنفسك.
pass(payload) (<caputchin-game> فقط)
يطلق بوّابة التحقّق: نجح الزائر. يصحّ فقط حين trigger="manual"؛ ونداؤه على لعبة غير يدوية يبثّ error برمز invalid-call. أول pass() يصرف ويقفل الحُكم؛ والنداءات اللاحقة تُتجاهَل بصمت (جولة واحدة لكل جلسة).
const widget = document.querySelector("caputchin-game");
widget.pass({ trace: roundRecord });حقل payload | النوع | المعنى |
|---|---|---|
trace | string | سجلّ الجولة المعتم الذي تنتجه لعبتك. على جولة محكومة يعيد الخادم تشغيله لاشتقاق الحُكم الموثوق؛ وعلى مفتاح غير محكوم أو لعبة-فقط يُقبَل كما هو. مرّر سلسلة فارغة إن لم يكن لتفاعلك سجلّ لإعادة تشغيله. |
لا حقل score على هذه الطريقة، البوّابة هي إعادة تشغيل الخادم لـ trace، لا نتيجة يدّعيها العميل. (score يظهر فعلًا على حدث pass، وهو الأداة تبلّغك، لا أنت تبلّغ الأداة.)
نداء pass() قبل أن تبدأ الجولة (modal / fullscreen، الحوار لم يُفتَح بعد) يبثّ error برمز invalid-call. على مفتاح لعبة-فقط (لا sitekey) لا بوّابة لتطلقها، فـ pass() ببساطة يبثّ حدث pass بـ token: null.
fail(payload?) (<caputchin-game> فقط)
يجهض الجولة: خسارة قاطعة. يصحّ فقط حين trigger="manual" (وإلا invalid-call). اختياري، جولة غير منتهية تُعامَل كغير ناجحة على أي حال. يجهض التحقّق الجاري (فحصا proof-of-work والرصد) ويُظهر حدث error برمز game-error-relayed.
widget.fail({ code: "out-of-moves", message: "no moves left" });حقل payload | النوع | المعنى |
|---|---|---|
code | string (اختياري) | رمزك التشخيصي؛ يُظهَر كـ originalCode لحدث error. الافتراضي game-failed. |
message | string (اختياري) | سبب مقروء للبشر. |
الأحداث
أنصِت بـ addEventListener(type, handler). كل حمولة تقيم على event.detail.
| الحدث | يبثّه | event.detail | يطلق حين |
|---|---|---|---|
start | كلاهما | { gameId: string | null } | يبدأ التحقّق (تلقائيًّا عند التركيب، أو عند التفعيل، أو عبر start()). gameId مضبوط لجولة لعبة، وnull للأداة العادية. |
pass | كلاهما | { token: string | null, score: number | null, durationMs: number | null } | يُطلَق التحقّق. token هو الرمز المغلَّف لإرساله إلى خادمك الخلفي؛ null على مفتاح لعبة-فقط (لا sitekey). |
error | كلاهما | { code, message, severity, originalCode? } | أي شيء من تنبيه إعداد حميد إلى فشل صلب. انظر حدث error. |
degraded | كلاهما | { reason: "timeout" | "network" | "http" | "malformed" } | تعذّر على الأداة حلّ المقاس / المظهر / اللغة الذين أعددتهم في الوقت المناسب، فعرضت بقيمها الافتراضية المضمَّنة. ليس خطأً. انظر حدث degraded. |
dialog-shown | <caputchin-game> | { layout: "modal" | "fullscreen" } | يُفتَح حوار لعبة تراكبيّ (برمجيًّا أو بأول نقرة). |
dialog-hidden | <caputchin-game> | { layout: "modal" | "fullscreen" } | يُغلَق حوار لعبة تراكبيّ (برمجيًّا، أو بـ Escape، أو بنقرة الخلفية). |
حدث pass والرمز
حدث pass إشارتك إلى أن التحقّق نجح، لكنه ليس قرار الثقة. قرار الثقة هو تأكيد خادمك الخلفي لـ detail.token. تحقّق دائمًا من الرمز على خادمك الخلفي؛ لا تمنح وصولًا عن حدث الواجهة وحده أبدًا. في نموذج، تحقن الأداة أيضًا الرمز كحقل caputchin-token كي يحمله POST نموذج عاديّ. score وdurationMs على هذا الحدث تحليلات يبلّغها العميل وقد تكون null؛ لا تعاملها كإشارة ثقة أبدًا.
حدث error
يحمل حدث error رمز code ثابتًا، وmessage بشريًّا، وseverity، وأحيانًا originalCode. لكل رمز خطورة افتراضية ثابتة كي ترشّح تنبيهات "بقي يعمل" من فشل "انكسر فعلًا" دون ترميز جدول رمز-إلى-خطورة، اقرأ detail.severity فقط. مجموعة الرموز الكاملة:
code | severity | المعنى |
|---|---|---|
invalid-config | warn | سمة أو تركيبة رفضتها الأداة؛ تتدهور برشاقة وتبقى تعمل. |
invalid-call | warn | طريقة نوديت حين لم تصحّ (مثلًا pass() على لعبة غير يدوية، أو قبل بدء الجولة). |
verification-failed | error | فشل فحص proof-of-work أو الرصد (أو صرف الرمز)؛ لا رمز صدر. |
game-load-failed | error | تعذّر حلّ حزمة اللعبة، أو تحميلها، أو تسجيلها. |
gate-unavailable | error | أعاد الخادم رفضًا موثوقًا عند الإقلاع (مفتاح محكوم تعذّر عليه تقديم لعبة صالحة). |
game-error-relayed | error | خطأ ظهر من داخل اللعبة (مُرحَّلًا من الإطار، أو من fail() يدويّ). |
detail.originalCode موجود حين يكون code العام تعميمًا لسبب داخليّ أخصّ (مثلًا، فشل تحميل إطار مُرحَّل كـ game-load-failed يحمل iframe-load-failed / iframe-script-blocked / game-not-registered الخام في originalCode). استخدم code للتفرّع وoriginalCode للتشخيص فقط.
حدث degraded
عند التركيب تجري الأداة نداءً قصيرًا واحدًا إلى Caputchin كي تحلّ المقاس والمظهر واللغة الذين أعددتهم (ولـ لعبة سوق، بصمتها المفضّلة). إن فشل ذلك النداء أو تأخّر كثيرًا، لا تتوقّف الأداة ولا تنكسر: تعرض بالقيم المخبوزة في الحزمة وتبثّ degraded كي لا يكون الرجوع إلى الافتراضي صامتًا أبدًا. تبقى الأداة عاملةً بالكامل بعد حدث degraded، فقط العرض المحلول قد يختلف عمّا أعددته (قد تظهر لعبة بمقاسها الافتراضي، أو خانة الاختيار بمظهرها الافتراضي). تعيد الأداة محاولة الحلّ البطيء قبل أن ترجع إلى الافتراضي، فـdegraded يعني أن المحاولات استُنفدت، لا أن محاولةً واحدةً كانت بطيئة.
detail.reason يخبرك لماذا رجع الحلّ إلى الافتراضي، كي تظهره في قياساتك الخاصّة:
reason | المعنى |
|---|---|
timeout | لم يجب الحلّ ضمن ميزانيّته الزمنيّة (الخدمة بطيئة أو غير قابلة للوصول). |
network | فشل الطلب نفسه (دون اتّصال، أو DNS، أو محجوب، أو إعادة تعيين الاتّصال). |
http | أجابت الخدمة بحالة خطأ. |
malformed | أجابت الخدمة، لكن الجسم لم يكن صالحًا. |
degraded إشعار، لا فشل، فهو عمدًا ليس حدث error: حلّ بطيء لا ينبغي أن يطلق المعالِجات التي تصلها لأعطال حقيقيّة. أنصت له فقط إن أردت أن ترصد العروض المتدهورة، مثلًا لتنبّه حين يرى زوّارك عرضًا افتراضيًّا.
الإنصات، عمليًّا
const widget = document.querySelector("caputchin-game");
const onPass = (e) => {
// send e.detail.token to your backend to verify
};
const onError = (e) => {
if (e.detail.severity === "error") {
console.error(e.detail.code, e.detail.message);
}
};
widget.addEventListener("pass", onPass);
widget.addEventListener("error", onError);
// Clean up when you tear down your view:
widget.removeEventListener("pass", onPass);
widget.removeEventListener("error", onError);هذه CustomEvent أصيلة من DOM، ففي React تربطها بـ ref وaddEventListener (لا خصائص JSX onPass)؛ أمثلة الواجهة تعرض التوصيل الخاص بكل إطار عمل. ولأن كل حدث يطفو ومركَّب، تستطيع أيضًا التفويض من عنصر حاوية بدل ربط كل أداة منفردةً.
انظر أيضًا
- أضف الأداة: سمات الإعداد التي تضبطها في التركيب (جانب المُدخَل لهذا الجانب المُخرَج).
- قُد التحقّق بنفسك بالوضع اليدوي: الدرس الذي يستخدم
start()/pass()/fail(). - تحقّق على خادمك الخلفي: ماذا تفعل برمز حدث
pass. - أمثلة الواجهة: توصيل هذه الأحداث في React، وVue، وJS عاديّ.