نموذج تواصل AJAX
حقول التواصل نفسها، تُرسل بـ fetch كـ JSON. يبقى الزائر في الصفحة ويرى حالة قصيرة.
ما الذي تنسخونه
يرسل هذا القالب حقول التواصل نفسها بواسطة fetch، فيبقى الزائر في صفحتكم ويقرأ حالة قصيرة.
يظل للنموذج action وطريقة POST. وإذا لم يعمل JavaScript، ينفّذ المتصفح إرسالًا عاديًا.
يهم هذا المسار الاحتياطي المتصفحات الأقدم ومن يحجبون البرامج النصية. ولستم بحاجة إلى صيانة نموذجين.
يرسل المقتطف الأساسي JSON. ويضبط Content-Type على application/json وAccept على application/json.
النجاح هو القيمة المنطقية success في JSON. وعندما تكون true يعرض المقتطف رسالة الاستجابة، أو شكرًا قصيرًا، ويفرغ النموذج.
وعندما تكون false يعرض المقتطف رسالة الاستجابة. ويكتب Formgong هذه الرسالة بلغة _lang.
JSON وFormData
يجب أن يسرد جسم JSON الحقول التي تريدون إرسالها. ويضمّ المقتطف access_key و_lang وname وemail وphone وmessage وbotcheck.
إذا أزلتم تعليق Turnstile لاحقًا، فسينسخ مسار JSON أيضًا cf-turnstile-response عندما تكون لهذا الحقل قيمة.
يستخدم المقتطف الإضافي FormData بدل JSON. ويضبط المتصفح نوع المحتوى، بما فيه الحد الفاصل. ولا تضبطوا Content-Type بأنفسكم.
يلتقط FormData كل حقل في النموذج، بما فيه رمز Turnstile إذا كانت الأداة داخل النموذج.
يرسل المساران Accept: application/json. ومن دون هذه الترويسة يحصل الإرسال العادي من المتصفح على صفحة الشكر، لا على JSON.
لا ترسلوا جسم JSON وجسم multipart معًا. اختاروا واحدًا. المقتطفان بديلان، وليسا طبقتين.
الرسائل غير المرغوب فيها وTelegram والحدود
أبقوا المصيدة المسماة botcheck فارغة وخارج الشاشة، مع tabindex -1. المصيدة المملوءة تُخزَّن كرسالة غير مرغوب فيها ولا تُسلَّم.
أبقوا أسماء الحقول قصيرة حتى يطبعها Telegram بخط عريض. ولا تعيدوا تسمية email لتصير جملة طويلة.
يبقى مفتاح الوصول في الصفحة. ونقله إلى سر في الخادم لا يجعل النموذج أكثر أمانًا، وهذا المقتطف بلا خادم.
في الخطة المجانية يصل Telegram فورًا، ويكون البريد ملخصًا يوميًا. ويحتفظ صندوق الوارد بالطلبات مدة 30 يومًا.
تشمل الخطة المجانية 300 طلبًا في الشهر. والرسالة غير المرغوب فيها لا تستهلك واحدًا منها.
هذه المعاينة لا ترسل. أوصلوا المقتطف في موقعكم، ثم أرسلوا اختبارًا من تلك الصفحة.
تشغّل Formgong الخدمة. وللمساعدة في المنتج اكتبوا إلى support@formgong.com.
معاينة
شيفرة النموذج
<form id="fg-ajax" action="https://formgong.com/submit" method="POST" style="position:relative">
<input type="hidden" name="access_key" value="fk_your_access_key">
<input type="hidden" name="_lang" value="ar">
<label>الاسم <input type="text" name="name" autocomplete="name" required></label>
<label>البريد الإلكتروني <input type="email" name="email" autocomplete="email" required></label>
<label>الهاتف <input type="tel" name="phone" autocomplete="tel"></label>
<label>الرسالة <textarea name="message" required></textarea></label>
<div aria-hidden="true" style="position:absolute;inset-inline-start:0;top:0;width:1px;height:1px;overflow:hidden;clip-path:inset(50%)">
<label>اترك هذا الحقل فارغًا <input type="text" name="botcheck" tabindex="-1" autocomplete="off"></label>
</div>
<!--
اختياري. فعّلوا Turnstile لهذا النموذج، ثم أزيلوا علامات التعليق والصقوا مفتاح الموقع.
<script src="https://challenges.cloudflare.com/turnstile/v0/api.js" async defer></script>
<div class="cf-turnstile" data-sitekey="YOUR_TURNSTILE_SITE_KEY" data-language="ar"></div>
-->
<button type="submit">إرسال</button>
<p data-status role="status"></p>
</form>
<script>
(function () {
var form = document.getElementById("fg-ajax");
if (!form) return;
var status = form.querySelector("[data-status]");
form.addEventListener("submit", function (event) {
event.preventDefault();
var data = {
access_key: form.access_key.value,
_lang: form._lang.value,
name: form.name.value,
email: form.email.value,
phone: form.phone.value,
message: form.message.value,
botcheck: form.botcheck.value
};
var token = form.querySelector('[name="cf-turnstile-response"]');
if (token && token.value) data["cf-turnstile-response"] = token.value;
var body = JSON.stringify(data);
fetch("https://formgong.com/submit", {
method: "POST",
headers: { "Content-Type": "application/json", Accept: "application/json" },
body: body
}).then(function (res) { return res.json(); }).then(function (result) {
if (status) status.textContent = result && result.success ? (result.message || "تم الإرسال. شكرًا لك!") : ((result && result.message) || "تعذّر الإرسال. يرجى المحاولة مرة أخرى.");
if (result && result.success) form.reset();
}).catch(function () {
if (status) status.textContent = "تعذّر الإرسال. يرجى المحاولة مرة أخرى.";
});
});
})();
</script>النموذج نفسه بـ FormData بدل JSON
<form id="fg-ajax" action="https://formgong.com/submit" method="POST" style="position:relative">
<input type="hidden" name="access_key" value="fk_your_access_key">
<input type="hidden" name="_lang" value="ar">
<label>الاسم <input type="text" name="name" autocomplete="name" required></label>
<label>البريد الإلكتروني <input type="email" name="email" autocomplete="email" required></label>
<label>الهاتف <input type="tel" name="phone" autocomplete="tel"></label>
<label>الرسالة <textarea name="message" required></textarea></label>
<div aria-hidden="true" style="position:absolute;inset-inline-start:0;top:0;width:1px;height:1px;overflow:hidden;clip-path:inset(50%)">
<label>اترك هذا الحقل فارغًا <input type="text" name="botcheck" tabindex="-1" autocomplete="off"></label>
</div>
<!--
اختياري. فعّلوا Turnstile لهذا النموذج، ثم أزيلوا علامات التعليق والصقوا مفتاح الموقع.
<script src="https://challenges.cloudflare.com/turnstile/v0/api.js" async defer></script>
<div class="cf-turnstile" data-sitekey="YOUR_TURNSTILE_SITE_KEY" data-language="ar"></div>
-->
<button type="submit">إرسال</button>
<p data-status role="status"></p>
</form>
<script>
(function () {
var form = document.getElementById("fg-ajax");
if (!form) return;
var status = form.querySelector("[data-status]");
form.addEventListener("submit", function (event) {
event.preventDefault();
var body = new FormData(form);
fetch("https://formgong.com/submit", {
method: "POST",
headers: { Accept: "application/json" },
body: body
}).then(function (res) { return res.json(); }).then(function (result) {
if (status) status.textContent = result && result.success ? (result.message || "تم الإرسال. شكرًا لك!") : ((result && result.message) || "تعذّر الإرسال. يرجى المحاولة مرة أخرى.");
if (result && result.success) form.reset();
}).catch(function () {
if (status) status.textContent = "تعذّر الإرسال. يرجى المحاولة مرة أخرى.";
});
});
})();
</script>أسئلة وأجوبة
لماذا ما زال للنموذج عنوان URL للإجراء؟
حتى يعمل الإرسال عندما يكون JavaScript متوقفًا. ولا يستدعي البرنامج النصي preventDefault إلا عندما يعمل.
هل ترسلون JSON أم FormData؟
كلاهما صالح. JSON يصرّح بكل حقل. وFormData أقصر عندما تضيفون حقول إدخال لاحقًا، لأنه يقرأ النموذج.
يبقى سطر الحالة فارغًا. ما الذي تعذّر؟
تحققوا من أن Accept يساوي application/json، ومن أن مفتاح الوصول يطابق نموذجًا تملكونه، ومن أن الصفحة تُقدَّم عبر http أو https، لا كملف محلي.
هل يمكن لهذا النموذج رفع ملف؟
ليس في هذا القالب. تحتاج حقول الملفات إلى تفعيل المرفقات وإلى رمز Turnstile صالح. استخدموا وثائق لوحة التحكم لهذا الإعداد.