في سلسلة فهم شجرة DOM، ناقشنا شجرة DOM وكيفية الوصول والتنقل وإضافة وإزالة وتعديل العقد والعناصر باستخدام وحدة تحكّم أدوات المطوّر.
بإمكاننا إجراء أي تغيير على شجرة DOM حتى هذه اللحظة، من وجهة نظر المستخدم فإنّه ليسَ مفيدًا للغاية لأننا قمنا بتنفيذ التغييرات يدويًّا فقط. سنتعرَّف الآن على الأحداث وربط كل شيء معها لإنشاء مواقع تفاعلية.
ما هي الأحداث؟
الأحداث (event) هي الإجراءات التي تحدث في المتصفّح والتي يبدأها المستخدم أو المتصفّح. فيما يلي عدّة أمثلة عن الأحداث الشائعة التي يمكن أن تحدث على موقع الويب:
- انتهاء الصفحة من التحميل
- نقر المستخدم على زر
- تحويم المستخدم سهم الفأرة فوق قائمة منسدلة
- إرسال المستخدم بياناته
- ضغط المستخدم على أحد مفاتيح لوحة مفاتيحه.
بإمكان المطورين إظهار رسائل للمستخدم للتحقق من صحة بيانات، والاستجابة إلى ضغط زرٍّ، والعديد من الإجراءات الأخرى وذلك عبر برمجة استجابات جافاسكربت على حدث معيّن.
سنتطرق إلى مُعَالِجَاتَ الأحداث ومُسْتمعي الأحداث وكائنات الأحداث. كما سنعرّج لثلاث طرقٍ مختلفة لكتابة التعليمات البرمجيّة للتعامل مع الأحداث، وبعض الأحداث الأكثر شيوعًا. ستتمكّن من تقديم تجربة ويب أكثر تفاعلية للمستخدمين النهائيين، من خلال التعرف على الأحداث.
معالجات الأحداث ومستمعي الأحداث
عندما ينقر المستخدم على زر أو يضغط المفتاح، يتم قدحُ الحدث، ويُسمّى آنذاك حدث النقر click
أو حدث الضغط keypress
على التوالي.
معالج الأحداث (event handler) هو دالَة جافاسكربت تعمل عند وقوع حدثٍ ما.
يقوم مستمع الحدث (event listener) بإرفاق واجهة استجابة لعنصر، ممَّا يسمح لهذا العنصر بالانتظار لإطلاق الحدث المحدّد أو ويكأنه يتنصَّت ويستمع إلى صوت إطلاق ذلك الحدث المتمثِّل بعيار ناري.
هناك ثلاث طرق لإسناد الأحداث إلى العناصر:
- مُعَالِجَات الأحداث المضمّنة (Inline event handlers).
- خاصيات معالج الحدث (Event handler properties).
- مستمعو الأحداث (Event listeners).
سنتعرف على ثلاث الطرق جَمِيعِها للتأكّد من أنك على دراية كاملة بكلِّ طريقة لإطلاق الحدث، ومناقشة إيجابيات وسلبيات كل طريقة.
الخصيّات المضمّنة لمعالج الأحدث
لبدء التعرف على معالجات الأحداث، سننظر أولاً في معالج الحدث المضمَّن (inline event handler9). لنبدأ بمثالٍ بسيط للغاية، يتكون من العنصرين زرٍّ button
وفقرة p
. ونريد من المستخدم أن يضغط على الزر لتغيير محتوى النص في الفقرة.
لنبدأ بصفحة HTML تحتوي على زرٍ. سنشير إلى ملف جافاسكربت وسنضيف الشيفرة البرمجية فيما بعد:
- الملف events.html:
<!DOCTYPE html> <html lang="en-US"> <head> <title>Events</title> </head> <body> <!-- إضافة زر --> <button>Click me</button> <p>Try to change me.</p> </body> <!-- ملف جافاسكربت --> <script src="js/events.js"></script> </html>
سنضيف خاصية على الزر مباشرةً تسمّى onclick
( أي عند النقر، نفِّذ ...). ستكون قيمة خاصيّة هي دالة ننشئها تسمّى changeText()
تمثِّل معالج الحدث.
- الملف events.html:
<!DOCTYPE html> <html lang="en-US"> <head> <title>Events</title> </head> <body> <button onclick="changeText()">Click me</button> <p>Try to change me.</p> </body> <script src="js/events.js"></script> </html>
لننشئ الملف events.js
ضمن المسار js/
. سننشئ الدالة changeText()
التي ستعدّل محتوى النص المتمثِّل بقيمة الخاصية textContent
على عنصر الفقرة p
.
- الملف js/events.js:
// تعديل نصِّ الفقرة عبر هذه الدالّة const changeText = () => { const p = document.querySelector('p'); p.textContent = "I changed because of an inline event handler."; }
عند تحميلك الصفحة events.html
لأول مرة ستبدو كما يلي:
حينما يتمُّ النقر على الزر من قبل المستخدم أو غيره، فإن محتوى نصّ الفقرة سيتغيّير من Try to change me.
إلى I changed because of an inline event handler.
تعدُّ معالجات الأحداث المضمّنة طريقةً مباشرةً لبدء فهم الأحداث، ولكن يجب ألا تستخدم بشكل عام خارج نطاق الاختبار والأغراض التعليميّة.
يمكنك مقارنة معالجات الأحداث المضمَّنة بأنماط CSS المضمَّنة في عنصر HTML. من العمليّ للغاية الحفاظ على ورقة أنماط منفصلة للأصناف بدلًا من إنشاء أنماط مضمّنة في كل عنصر، تمامًا كما هو أكثر جدوى للحفاظ على شيفرات جافاسكربت التي تتم معالجتها بالكامل من خلال ملف منفصل بدلًا من إضافتها إلى كل عنصر.
خاصيات معالج الأحداث
الخطوة التالية، هي الانتقال من معالج الأحداث المضمّنة إلى خاصية معالج الأحداث. يعمل هذا بشكل مشابه جدًّا لمعالج مضمَّن، باستثناء أننا نقوم بتعيين خاصية العنصر في الجافاسكربت بدلًا من خاصية HTML.
سيكون الإعداد هو نفسه هنا، باستثناء أننا لم نعد ندرج onclick="changeText()"
في شيفرة العنصر:
- الملف events.html:
... <body> <button>Click me</button> <p>I will change.</p> </body> ...
ستظلُّ وظيفتنا متشابهة أيضًا، إلا أننا نحتاج الآن إلى الوصول إلى العنصر button
في جافاسكربت. يمكننا ببساطة الوصول إلى الخاصية onclick
مثلما نصل إلى الخاصية style
أو id
أو أي خاصية عنصر أخرى، ثم نقوم بتعيين مرجع للدالة المراد تنفيذها.
- الملف js/events.js:
// الدالة المراد تنفيذها عند وقوع الحدث والتي تعدِّل محتوى الفقرة const changeText = () => { const p = document.querySelector('p'); p.textContent = "I changed because of an event handler property."; } // button إضافة معالج حدث كخاصية للعنصر const button = document.querySelector('button'); button.onclick = changeText;
ملاحظة: لا تتبع معالجات الأحداث عُرْفَ سنام الجمل (camelCase) التي تلتزم بها معظم تعليمات جافاسكربت البرمجية. لاحظ أن الرمز هو onclick
، وليس onClick
.
عند تحميل الصفحة لأول مرة ، سيعرض المتصفح ما يلي:
الآن عند النقر فوق الزر، سيكون له تأثير مماثل كما كان من قبل:
لاحظ بتمريرنا مرجع الدالة المراد تنفيذها إلى الخاصية onclick
، فإننا لا نقوم بتضمين الأقواس، حيث أننا لا نستدعي الدالّة في تلك اللحظة، ولكننا نمرّر مرجعًا إليها.
button.onclick = changeText;
تعدُّ خاصيَّة معالج الأحداث أكثرَ قابليَّةٍ للصيانة من المعالج المضمَّن، إلَّا أنها تعاني عقباتً مماثلة. فمثلاً، محاولةُ تعييِّن عدّة خصائص onclick
منفصلة سيطبق التأثير على آخر محاولة. كما هو موضَّح أدناه.
- الملف js/events.js:
const p = document.querySelector('p'); const button = document.querySelector('button'); const changeText = () => { p.textContent = "Will I change?"; } const alertText = () => { alert('Will I alert?'); } // يمكن تعديل الأحداث button.onclick = changeText; button.onclick = alertText;
في المثال أعلاه، لن تعرض النقرة على الـ button
سوى تنبيه، ولن تغيّر النصّ p
، لأن alert()
هو آخر تعليمة برمجية أضيفت إلى الخاصية.
من خلال فهم كل من معالجات الأحداث المضمّنة وخصائص معالج الأحداث، دعنا ننتقل إلى مستمعي الأحداث.
مستمعي الأحداث
أحدث إضافة إلى معالجات الأحداث في جافاسكربت هي مستمعي الحدث. يراقب مستمع الحدث حدثًا على عنصر. بدلاً من إسناد الحدث مباشرةً إلى خاصيّة في العنصر، سنستخدم التابع addEventListener()
للاستماع للحدث.
يأخذ addEventListener()
معاملين إلزاميين - الحدث الذي يجب الاستماع إليه، ودالَّة ردِّ نداء لتنفيذها عند اطلاق الحدث.
ملف الـ HTML لمستمع الأحداث الخاص بنا هو نفسه في المثال السابق.
- الملف events.html:
... <button>Click me</button> <p>I will change.</p> ...
سنظلّ نستخدم نفس الدالّة changeText()
كما سابقًا ولكن سنربطها مع التابع addEventListener()
على الزر.
- الملف js/events.js:
// الدالة المراد تنفيذها عند وقوع الحدث والتي تعدِّل محتوى الفقرة const changeText = () => { const p = document.querySelector('p'); p.textContent = "I changed because of an event listener."; } // الاستماع لحدث النقر const button = document.querySelector('button'); button.addEventListener('click', changeText);
لاحظ أنه مع أوّل طريقتين، تمّت الإشارة إلى حدث النقر باسم onclick
، ولكن مع مستمعي الأحداث يشار إليه باسم click
. تُسْقَطُ on
من الكلمة لكل مُسْتَمِع حدث. في القسم التالي، سنأخذ المزيد من الأمثلة على أنواع الأحداث الأخرى.
عند إعادة تحميل الصفحة بشيفرة جافاسكربت أعلاه، ستتلقى الخَرْج التالي:
للوهلة الأولى، يبدو مستمعو الأحداث متشابهين جدًا مع خصائص معالج الأحداث، لكن لديهم بعض المزايا. يمكننا تعيين عدّة مستمعين على نفس العنصر، كما هو موضَّح في المثال أدناه.
- الملف js/events.js:
const p = document.querySelector('p'); const button = document.querySelector('button'); const changeText = () => { p.textContent = "Will I change?"; } const alertText = () => { alert('Will I alert?'); } // يمكن إضافة عدة مستمعات إلى الحدث نفسه والعنصر نفسه أيضًا button.addEventListener('click', changeText); button.addEventListener('click', alertText);
سيتمُّ إطلاق الحدثين في المثال أعلاه، ممّا يوفِّر للمستخدم كلًّ من التنبيه والنصِّ المعدّل بعد النقر فوق التنبيه. ستستخدام غالباً دالّات مجهولة (Anonymous functions) بدلاً من مرجع دالّة على مُسْتَمع الحدث. الدالّات المجهولة هي دالّات غير مُسَمَّاة.
// دالة مجهولة يراد تنفيذها عند إطلاق الحدث button.addEventListener('click', () => { p.textContent = "Will I change?"; });
من المُمْكِن أيضًا استخدام دالّة removeEventListener()
لإزالة حدث واحد أو جميع الأحداث من عنصر.
// button من العنصر alert حذف الدالة button.removeEventListener('click', alertText);
يمكنك استخدام addEventListener()
على الكائنين document
و window
.
يُعَدُّ مُسْتَمِعُو الأحداث حاليًا الطريقةَ الأكثرَ شيوعًا والمفضَّلة للتعامل مع الأحداث في جافاسكربت.
الأحداث المشتركة
تعلمّنا عن معالجات الأحداث المضمّنة، وخصائص معالج الأحداث، ومستمعي الأحداث باستخدام حدث النقرات، ولكن هناك العديد من الأحداث في جافاسكربت. سنتطرق لأكثر الأحداث شيوعًا أدناه.
أحداث الفأرة
أحداث الفأرة هي من بين الأحداث الأكثر استخدامًا. تشير إلى الأحداث التي تنطوي على نقر زر الفأرة أو تحريك المؤشر وتحويمه (hovering). تتوافق هذه الأحداث أيضًا مع الإجراء المماثل على جهاز يعمل باللمس.
الحدث | الوصف |
---|---|
click
|
يُطلَق عند الضغط بزر الفأرة أو عند الإفلات على العنصر |
dblclick
|
يُطلَق عندما يتم النقر فوق عنصر مرتين |
mouseenter
|
يُطلَق عندما يدخل المؤشر داخل عنصر |
mouseleave
|
يُطلَق عندما يترك المؤشر عنصرًا |
mousemove
|
يُطلَق في كل مرة يتحرك فيها المؤشر داخل عنصر ما`` |
إن حدث النقر click
هو حدثٌ مركَّب يتألف من الجمع بين حدثين هما mousedown
و mouseup
، ويُطلَق حينَ الضغط على زر الفأرة لأسفل أو رفعه، على التوالي. يؤدي استخدام الحدثين mouseenter
و mouseleave
بالترادف إلى إعادة إنشاء تأثير التحويم الذي يستمر ما دام مؤشر الفأرة على العنصر.
أحداث النموذج
أحداث النموذج form
هي إجراءات تتعلق بالنماذج، مثل عناصر الإدخال input
التي يتم تحديدها أو غير المحددة، والنماذج التي يتم إرسالها.
الحدث | وصف |
---|---|
submit
|
يُطلَق عند إرسال النموذج |
focus
|
يُطلَق عند تلقِي عنصر (مثل المدخلات) التركيز |
blur
|
يُطلَق حينَ يفقد العنصر التركيز |
يتحقق التركيزfoucus عند تحديد عنصر، على سبيل المثال، من خلال النقر بالفأرة أو الانتقال إليه عبر المفتاح TAB
غالبًا ما تستخدم جافاسكربت لإرسال النماذج وإرسال القيم إلى لغة الواجهة الخلفية. تتمثّلُ ميزة استخدام جافاسكربت لإرسال النماذج بأنه لا يتطلب إعادة تحميل الصفحة لإرسال النموذج، ويمكن استخدام جافاسكربت للتحقق من حقول الإدخال المطلوبة.
أحداث لوحة المفاتيح
تُستخدم أحداث لوحة المفاتيح لمعالجة إجراءات لوحة المفاتيح، مثل الضغط على مفتاح ما، ورفع الضغط عن مفتاح، واستمرار ضغط مفتاح.
الحدث | وصف |
---|---|
keydown
|
يُطلَق مرة واحدة عند الضغط على أي مفتاح |
keyup
|
يُطلَق مرة واحدة عندما يتم تحرير (إفلات الضغط) المفتاح المضغوط |
keypress
|
يُطلَق بشكل مستمر أثناء الضغط على المفتاح |
قد يبدو الحدثين keydown
و keypress
متشابهين إلا أنهما لا يتيحان الوصول إلى جميع المفاتيح بالضبط. في حين أنَّ keydown
يقرّ بكل ضغطَة (أي الضغط على أي مفتاح)، يستثني الحدث keypress
المفاتيح التي لا يولد الضغط عليها حرفًا، مثل المفاتيح SHIFT
و DELETE
و ALT
وغيرها.
أحداث لوحة المفاتيح لها خصائص محددة للوصول إلى المفاتيح الفردية.
إذا مُرِّرَ المعامل الأول (الكائن event
) عبر مستمع الحدث، فيمكننا الوصول إلى مزيد من المعلومات حول الإجراء الذي حدث أهمها ثلاثة خصائص تتعلق بكائنات لوحة المفاتيح هي: keycode
و key
و code
.
إذا ضغط المستخدم على المفتاح a
على لوحة المفاتيح، فستظهر الخصائص التالية المتعلقة بهذا المفتاح:
خاصية | وصف | مثال |
---|---|---|
keyCode
|
عدد يتعلق بالمفتاح | 65 |
key
|
يمثل اسم الحرف | a |
code
|
يمثل المفتاح الفعلي الذي يتم الضغط عليه | keyA |
لإظهار كيفية جمع هذه المعلومات عبر وحدة التحكم جافاسكربت، يمكننا كتابة سطور التعليمات البرمجيّة التالية:
// keyCode و key و code التحقق من الخاصيات document.addEventListener('keydown', event => { console.log('key: ' + event.keyCode); console.log('key: ' + event.key); console.log('code: ' + event.code); });
بمجرد ضغط ENTER
في الطرفية، يمكننا آنذاك الضغط على أي مفتاح من لوحة المفاتيح، في هذا المثال، سنضغط a
.
Output keyCode: 65 key: a `code: KeyA`
إنَّ الخاصيَّةَ keyCode
هي عدد يمثلُّ قيمة المفتاح الذي ضُغِطَ بينما تمثِّل خاصيَّةَ key
اسم الحرف، التي يمكن أن تتغيّر - على سبيل المثال، ضغط المفتاح a
مع SHIFT
سيؤدي A
. وتمثِّلُ الخاصيِّةُ code
المفتاح الفيزيائي على لوحة المفاتيح.
لاحظ أنَّ keyCode
في طريقها إلى الزوال ويفضل استخدام code
في مشاريع جديدة.
لمعرفة المزيد، يمكنك عرض القائمة الكاملة للأحداث على شبكة مطوري Mozilla.
كائنات الحدث
يتكون الكائن Event
من الخاصيّات والتوابع التي يمكن لجميع الأحداث الوصول إليها. بالإضافة إلى Event
الكائن العام، كل نوع من أنواع الأحداث له امتدادات خاصة به، مثل KeyboardEvent
و MouseEvent
. سيمرَّر الكائن Event
من خلال دالّة المستمع كمعامل. وعادة ما يكتب باسم event
أو e
. يمكننا الوصول إلى الخاصية code
التابعة للـحدث keydown
لتكرار عناصر تحكم لوحة المفاتيح في لعبة مثلًا.
قم بإنشاء ملف HTML يحوي العنصر <p>
وحملّه في المتصفح.
- الملف event-test-p.html:
<!DOCTYPE html> <html lang="en-US"> <head> <title>Events</title> </head> <body> <p></p> </body> </html>
ثم اكتب شفرة جافاسكربت التالية في طرفية أدوات المطور .
// تمرير حدث إلى مستمع document.addEventListener('keydown', event => { var element = document.querySelector('p'); // إسناد قيمة رموز المفاتيح المراد الضغط عليها إلى متغيرات var a = 'KeyA'; var s = 'KeyS'; var d = 'KeyD'; var w = 'KeyW'; // تحديد الاتجاه لكل مفتاح switch (event.code) { case a: element.textContent = 'Left'; break; case s: element.textContent = 'Down'; break; case d: element.textContent = 'Right'; break; case w: element.textContent = 'Up'; break; } });
عند الضغط على أحد المفاتيح - a
، أو s
، أو d
، أو w
سترى خرجًا مشابهًا لما يلي:
يمكنك الاستمرار في تطوير كيفية استجابة المتصفح للمستخدم حينَ الضغط على هذه المفاتيح، ويمكن إنشاء موقع ويب أكثر ديناميكية.
سنتطرق إلى إحدى خصائص الأحداث الأكثر استخدامًا: الخاصيِّةُ target
. في المثال التالي ، لدينا ثلاثة عناصر div
ضمن قسم واحد section
.
- الملف event-test-div.html:
<!DOCTYPE html> <html lang="en-US"> <head> <title>Events</title> </head> <body> <section> <div id="one">One</div> <div id="two">Two</div> <div id="three">Three</div> </section> </body> </html>
باستخدام event.target
في جافاسكربت ضمن طرفيّة أدوات المطور (Developer Console)، يمكننا وضع مستمع حدث واحد على العنصر section
الخارجي والحصول على العنصر الأكثر تداخلًا.
const section = document.querySelector('section'); // طباعة الهدف المحدَّد section.addEventListener('click', event => { console.log(event.target); });
يؤدي النقر فوق أي عنصر من هذه العناصر إلى إعادة إخراج العنصر المحدد ذي الصلة إلى الطرفية باسـتخدام event.target
. إتاحة وضع مُسْتَمع حَدَث واحد فقط، يُمَكِّنُ من الوصول إلى العديد من العناصر المتداخلة، وهذا في غاية الأهمية.
باستخدام الكائن Event
، يمكننا إعداد استجابات متعلقة بجميع الأحداث، بما في ذلك الأحداث العامة والإضافات الأكثر تحديدًا.
الخلاصة
الأحداث هي الإجراءات التي تحدث على موقع ويب، مثل النقر فوق الفأرة أو تحويم المؤشر أو إرسال نموذج أو تحميل صفحة أو الضغط على مفتاح في لوحة المفاتيح. تصبح جافاسكربت تفاعليًا وديناميكيًا حقًا عندما نتمكن من جعل مواقع الويب تستجيب للإجراءات التي اتخذها المستخدم.
تعلمنا -في هذا الدليل ما هي الأحداث، وأمثلة عن الأحداث الشائعة، والفرق بين معالجات الأحداث ومستمعي الأحداث، وكيفية الوصول إلى الكائن Event
. ستتمكن من إنشاء مواقع وتطبيقات ديناميكية، باستخدام هذه المعلومات. ترجمة - وبتصرف- للمقال Understanding Events in JavaScript لصاحبته Tania Rascia
أفضل التعليقات
انضم إلى النقاش
يمكنك أن تنشر الآن وتسجل لاحقًا. إذا كان لديك حساب، فسجل الدخول الآن لتنشر باسم حسابك.