سيتوفر auxclick قريبًا في الإصدار 55 من Chrome

متى لا تُصنَّف النقرة على أنّها click؟ بالنسبة لمطور ويب يعمل على واجهة مستخدم معقّدة، فهذا ليس سؤالاً فلسفيًا مجردًا. إذا كنت تنفِّذ سلوكًا مخصصًا لإدخال الماوس، من الضروري أن تضع نية المستخدم في الاعتبار. على سبيل المثال، إذا نقر أحد المستخدمين على رابط به الزر الأوسط للماوس، فمن المنطقي أن نفترض أنه يريد فتح علامة تبويب جديدة تعرض محتويات هذا الرابط. إذا نقر أحد المستخدمين بزر الماوس الأوسط على عنصر عشوائي في واجهة المستخدم، فقد تحتاج إلى الافتراض أن ذلك كان غير مقصود، وتجاهُل هذا الإدخال، بينما يُتوقّع أن تؤدي النقرة على الزر الأساسي إلى ظهور استجابة من واجهة المستخدم.

إذا كان الأمر مرهقًا بعض الشيء، قد يكون من الممكن وضع نماذج لهذه التفاعلات الدقيقة من خلال أداة معالجة واحدة لحدث click. عليك التحقّق بشكل واضح من السمة button في MouseEvent، لمعرفة ما إذا تم ضبطها على 0 التي تمثّل الزر الأساسي، مقارنةً بالزرّ الأساسي، إذ تمثّل 1 عادةً الزر الأوسط، وهكذا. مع ذلك، لا يتحقّق الكثير من المطوّرين بشكل صريح من السمة button، ما يؤدي إلى إنشاء رمز يعالج جميع click بشكل متطابق، بغض النظر عن الزر الذي تم الضغط عليه.

بدءًا من Chrome 55، يتم تنشيط نوع جديد من MouseEvent، يُسمى auxclick، استجابةً لأي نقرات تتم باستخدام زر غير أساسي. ويصاحب هذا الحدث الجديد تغيير مطابق في سلوك حدث click، ولن يتم تنشيطه إلا عند الضغط على زر الماوس الأساسي. نأمل أن تسهّل هذه التغييرات على مطوّري الويب كتابة معالِجات الأحداث التي تستجيب لنوع النقرات التي يهتمون بها فقط، بدون الحاجة إلى التحقّق من السمة MouseEvent.button على وجه التحديد.

تقليل النتائج الموجبة الخاطئة

كما ذكرنا سابقًا، كان أحد دافعي إنشاء auxclick هو تجنُّب نشر معالِجات click المخصّصة التي تتجاهل عن طريق الخطأ سلوك "النقر الأوسط لفتح علامة تبويب". على سبيل المثال، لنفترض أنّك كتبت معالِج أحداث click يستخدم History API لإعادة كتابة شريط المواقع الجغرافية وتنفيذ عمليات التنقّل المخصّصة في صفحة واحدة. قد يبدو شيئًا مثل:

document.querySelector('#my-link').addEventListener('click', event => {
    event.preventDefault();
    // ...call history.pushState(), use client-side rendering, etc....
});

قد يعمل المنطق المخصّص على النحو المنشود عند تشغيله باستخدام زر أساسي بالماوس، ولكن إذا تم تشغيل هذا الرمز عند النقر على الزر الأوسط، فهي في الواقع نتيجة موجبة خاطئة. قبل السلوك الجديد، كان ينتهي بك الأمر بمنع الإجراء الافتراضي المتمثل في فتح علامة تبويب جديدة، والتي تتعارض مع توقعات المستخدم. يمكنك التحقق بشكل واضح من event.button === 0 في بداية المعالج، وعدم تنفيذ الرمز إلا في حال كان الأمر هكذا، فمن السهل نسيانه أو عدم إدراكك أبدًا أنّ تنفيذه ضروريًا.

قم بتشغيل التعليمة البرمجية التي تحتاجها فقط

في المقابل، هناك عدد أقل من النتائج الموجبة الخاطئة، وهو أنّه لن يتم تنفيذ استدعاءات auxclick إلا عند النقر على زر ماوس غير أساسي. إذا كان لديك رمز برمجي يتطلّب مثلاً حساب عنوان URL مقصود ملائم قبل فتح علامة تبويب جديدة، يمكنك رصد الاستجابة auxclick وتضمين هذا المنطق في معاودة الاتصال. ولن يتحمّل أي عبء إضافي للتشغيل عند النقر فوق زر الماوس الأساسي.

التوافق مع المتصفِّحات

لا يتم تنفيذ هذا السلوك الجديد حاليًا إلا في الإصدار 55 من Chrome. كما ورد في الاقتراح الأولي، نقدِّر الملاحظات (الإيجابية والسلبية) من منتدى مطوّري الويب. يُعد الإبلاغ عن مشكلة GitHub أفضل طريقة لمشاركة تلك الملاحظات مع الأشخاص الذين يعملون على عملية التوحيد.

في الوقت الحالي، ليس على المطوّرين الانتظار إلى أن تصبح auxclick متاحة على نطاق واسع لاتّباع بعض أفضل الممارسات المتعلّقة بالتعامل مع أحداث الماوس. إذا خصّصت الوقت الكافي للتحقّق من قيمة السمة MouseEvent.button في بداية معالج أحداث click، يمكنك التأكّد من اتّخاذ الإجراء المناسب. سيتعامل النمط التالي مع النقرات الأساسية والإضافية بشكل مختلف، سواء كان هناك دعم أصلي لـ auxclick أم لا:

function handlePrimaryClick(event) {
    // ...code to handle the primary button click...
}

function handleAuxClick(event) {
    // ...code to handle the auxiliary button click….
}

document.querySelector('#my-link').addEventListener('click', event => {
    if (event.button === 0) {
    return handlePrimaryClick(event);
    }


    // This provides fallback behavior in browsers without auxclick.
    return handleAuxClick(event);
});

// Explicitly listen for auxclick in browsers that support it.
document.querySelector('#my-link').addEventListener('auxclick', handleAuxClick);