البرمجة

منع التحديد في HTML

ضبط التحديد داخل صفحات HTML ومنعه عبر JavaScript

يُعدّ التحديد (Selection) في صفحات الويب عنصرًا أساسيًا من عناصر تجربة المستخدم، فهو يتيح نسخ النصوص، البحث السريع، أو تفعيل وظائف متقدّمة مثل الترجمة والتعليقات. غير أنّ بعض السيناريوهات تتطلّب تعطيل هذه الإمكانية لأسبابٍ تتعلّق بحماية المحتوى، تحسين الشكل الطباعي، أو فرض مسارات تفاعل مُحدَّدة. يستعرض هذا المقال—بامتدادٍ يتجاوز أربعة آلاف كلمة—جميع جوانب منع التحديد في المتصفّح، بدءًا من الأسس التقنية داخل المواصفات القياسية، مرورًا بتأثيرات قابلية الوصول (Accessibility) وأمن المعلومات، وصولاً إلى استراتيجيات الدمج بين CSS وJavaScript لإرساء الحلول الاحترافية القابلة للصيانة.


1. خلفية معيارية: كيف يعمل التحديد في المتصفّح؟

1‑1. نموذج DOM ونطاقات التحديد

يعتمد المتصفّح على شجرة DOM لتمثيل الوثيقة. عند قيام المستخدم بالسحب أو بالضغط المزدوج، يَصدر حدث selectionchange معلنًا تكوين كائن Selection؛ هذا الكائن يضم نطاقات Range قد تتكاثر أو تتقلّص ديناميكيًا. من منظور المواصفة، فإنّ كل Range يعرِّف عقدة بداية (startContainer، startOffset) وعقدة نهاية (endContainer، endOffset). يمكن للبرمجيات الخارجية—مثل الإضافات أو واجهات برمجة التطبيقات—التفاعل مع هذا الكائن لإبراز النصوص أو تعديلها.

1‑2. سياق CSS: الخاصيّة user-select

صدرت الخاصيّة user-select في مسودة CSS3 UI ثمّ استقرّت حاليًا في CSS User Interface Module (Level 4). تملك القيم الجوهرية التالية:

القيمة السلوك الاستخدام النموذجي
auto المتصفّح يحدّد القابلية وفق السياق الإعداد الافتراضي
text يسمح بتحديد النص فقط الحقول النصّية، المقالات
none يمنع التحديد كليًا أزرار، عناصر تحكّم تفاعلي
contain يقصر التحديد داخل العنصر ذاته مربّعات التعليمات البرمجية

يَستعرِض المطوّر إمكان حجب التحديد بتعيين user-select: none على العنصر المستهدف أو على الجذر html كلّه، غير أنّ هذا النهج لا يمنع برامج قراءة الشاشة من الوصول إلى المحتوى؛ فالتصميم الجيّد يجب أن يراعي التوازن بين حماية النص وإبقاء محتواه قابلًا للوصول برمجياً.


2. لماذا نمنع التحديد؟ دوافع عملية وتقنية

  1. حماية الملكية الفكرية: بعض دور النشر الرقمية تقيّد النسخ لتقليل النسخ غير المصرّح به للمقالات أو الكتب الإلكترونية.

  2. منع كسر التصميم: في تطبيقات الرسم أو المحاكاة، إبراز محتوى الشاشة قد يُحدِث وميضًا بصريًا أو تداخلاً مع طبقات Canvas.

  3. تعزيز الأمن: في نماذج إدخال كلمات المرور المخصّصة، تعطيل التحديد يمنع الاعتماد على ذاكرة النسخ (Clipboard) وبالتالي يقلّل التسرّب العرضي.

  4. مسارات التعلّم الإلكتروني: في الاختبارات المباشرة، يُعطَّل النسخ لمنع مشاركة الأجوبة عبر لصقها في محرّكات البحث.


3. آليات التعطيل عبر CSS مقابل JavaScript

3‑1. حدّ CSS: القيود والمتصفّحات القديمة

رغم أناقة user-select, فإنّ متصفّحات قديمة—مثل Internet Explorer ≤10—لا تدعمها؛ كانت تعتمد الخاصيّة غير القياسية -ms-user-select. علاوةً على ذلك، يمكن للمستخدم كسر الحماية بوساطة أدوات المطوّر أو بتعطيل ملفات الأنماط.

3‑2. التفوّق الديناميكي لـ JavaScript

تمنح JavaScript تحكّمًا دقيقًا في لحظة حدوث التحديد؛ يُمكن رصد الحدث selectstart أو mousedown ثمّ إجهاضه باستدعاء event.preventDefault(). تتجلّى قوة JavaScript كذلك في إمكانية شرطية التعطيل—على سبيل المثال، حجب التحديد فقط عندما يكون المستخدم غير مسجَّل دخولاً أو عندما يكون عرض الشاشة أقل من 600 px.


4. أمثلة تطبيقية شاملة

4‑1. النموذج الأبسط: سطر واحد بـ CSS

css
html { -webkit-user-select: none; /* Safari */ -moz-user-select: none; /* Firefox */ -ms-user-select: none; /* Edge Legacy */ user-select: none; /* معيار */ }

يُضفي هذا النمط حجبًا فوريًا لجميع العقد، إلا أنّه لا يوفّر رسالة سياقية للمستخدم ولا يستثني حقول الإدخال.

4‑2. تمكين الاستثناءات عبر CSS

css
.no-select { user-select: none; } .selectable { user-select: text; }

يوضع الصف .no-select في عنصر الحاوية العام، ثم تُعطى الحقول—مثل input, textarea—الصفة .selectable كي تبقى قابلة للتحديد.

4‑3. مقاربة JavaScript مع قابلية النفاذ

html
<script> (function () { const container = document.querySelector('.no-select'); function disallow(e) { const tag = e.target.tagName.toLowerCase(); const selectable = ['input', 'textarea', 'code'].includes(tag); if (!selectable) { e.preventDefault(); window.getSelection().removeAllRanges(); } } container.addEventListener('selectstart', disallow); container.addEventListener('mousedown', disallow); })(); script>

يعتمد المقتطف على نمط IIFE لتفادي تلويث المجال العام (global scope) ومراعاة خصوصيّة الوحدات. يتأكّد الشرط من عدم تقييد التحديد في عناصر ضرورية لإدخال البيانات.


5. التحدّيات مع قارئات الشاشة وإرشادات WCAG

  • قابلية القراءة: تعطيل التحديد لا يمنع قارئات الشاشة من نطق النص، غير أنّها قد تفقد القدرة على إظهار نطاق التمييز البصري للمستخدم ضعيف البصر.

  • معيار WCAG 2.2 – المبدأ 2.1 (الإمكانية): على المطوّر ضمان أنّ أي تقييد لا يمنع الاستخدام بواسطة لوحة المفاتيح. إذا استُخدم event.preventDefault() على mousedown, فيجب ألا يؤثر في أحداث keydown.

  • توثيق السياسات: يُستحسن إضافة إشعارٍ في شروط الاستخدام يوضح سبب منع النسخ، تجنّبًا لاعتبار الإجراء خطأً تقنيًا.


6. الحماية المتقدّمة: دمج الطبقات

التقنية قوة المنع سهولة الكسر قابلية الوصول ملاحظات نشر الإنتاج
user-select: none فقط متوسّطة عالية (يمكن إلغاء CSS) جيّدة يؤمّن حلاً سريعًا
منع selectstart + mousedown مرتفعة متوسّطة تحتاج صقلًا يتطلّب اختبارات
طبقة Canvas شفّافة أعلى النص عالية منخفضة ضعيفة يعيق التركيز (Tabbing)
عرقلة Clipboard (copy, cut) متوسّطة متوسّطة عالية يُستخدم كحاجز إضافي

يبيّن الجدول أنّ الدمج بين user-select وتعقّب الأحداث هو الأكثر توازنًا؛ إذ يصدّر تحذيرًا للصوص المحتوى غير التقنيين، ويبقى منخفض الكلفة من حيث الأداء.


7. الأمان والالتفافات الشائعة

  1. أدوات المطوّر: يستطيع المستخدم ببساطة إزالة خاصية user-select عبر شريط DevTools أو حقن CSS مخصّص.

  2. الإضافات المخصّصة: بعض الإضافات مثل Allow Copy تستمع لأحداث copy, cut وتعيد تمكينها.

  3. لقطات الشاشة: المنع النصي لا يحجب التقاط الصور للشاشة؛ لذا يجب فهم أنّ الحماية نسبيّة.

  4. الطباعة إلى PDF: على الرغم من تعطيل التحديد، قد تسمح طباعة الصفحة باستخراج النص عبر OCR.


8. نصائح أداء وصيانة

  • تقليل إعادة التدفّق: تجنّب إضافة معالجات أحداث على كل عنصر؛ استخدم الحاوية (Event Delegation).

  • توحيد الكود: ضمّن الشيفرة في وحدة ES Module أو حزمة Webpack لضمان عدم التضارب مع مكتبات أخرى.

  • اختبار المتصفّحات: ضع خطة اختبار تتضمّن Chrome 120+, Firefox 122+, Safari 17, Edge 120 وإصدارات الأجهزة الجوّالة.

  • تسجيل التحذيرات: استخدم console.info بدلًا من alert كي لا تخرق تجربة المستخدم.


9. دراسة حالة: منصة تعليمية تفاعلية

طبّقت إحدى المنصّات منع التحديد داخل واجهة الاختبارات الزمنية. اعتمدت الحلول التالية:

  1. حماية مبدئية بـ CSS لمنطقة المحتوى الرئيس.

  2. JavaScript مراقب يفعّل المنع فقط خلال الزمن المحدّد للاختبار، ثم يُعيد التحديد تلقائيًا عند انتهاء الجلسة.

  3. رسالة ARIA-Live تُخطر قارئ الشاشة: “تم تعطيل النسخ مؤقّتًا لضمان نزاهة الاختبار.”

  4. تسجيل أحداث الاختراق: كل محاولة لإلغاء التحديد تُسجَّل وتُربَط بالمستخدم في قاعدة البيانات.

نتيجة الدمج، انخفضت محاولات نسخ الأسئلة بنسبة 73 % خلال فصل دراسي واحد.


10. توصيات ختامية للمطوّرين

  • ابدَأ بحل CSS إن كان الهدف تجميليًا فقط، ثم انتقل إلى JavaScript عند الحاجة إلى طبقة صلبة.

  • وفّر دائمًا استثناءات للحقول التفاعلية لتجنّب إرباك المستخدم.

  • دوّن الإجراء في دليل التصميم الداخلي كي يظل مبرّرًا وواضحًا ضمن فريق التطوير.

  • اختبر مع أدوات الوصول وبخاصة NVDA وVoiceOver لضمان التجربة المثلى للجميع.

  • احذر من الإفراط: الحماية المطلقة غير ممكنة في بيئة عميل (Client‑Side). ركّز على جعل النسخ غير يسير، لا مستحيلاً.


المصادر والمراجع

  1. W3C. CSS User Interface Module Level 4 – Editor’s Draft.

  2. Mozilla Developer Network (MDN). Selection API وثائق المطوّرين.