Have an account? Sign in
Login  Register  Facebook
This Page is Under Construction! - If You Want To Help Please Send your CV - Advanced Web Core (BETA)
[Edit] تعين معالجات الأحداث بإستخدام دوال خاصة بذلك
الطريقة الأولى التي عرضناها لمعالجة الأحداث تتميز بالبساطة أما الطريقة التي سنعرضها الآن فتتميز بأنها أكثر مرونة و تتيح إمكانيات أكثر .هذه الطريقة تقوم على أساس إستخدام دوال معينه لإضافة لمعالجة الأحداث لكن المشكلة في أن الإنترنت إكسبلورر له دوال تختلف عن بقية المتصفحات .سنعرف دوال الإثنين و نعرف كيف نجعل الكود صالح لكل المتصفحات . addEventListener(نوع الحدث, الدالة المعالجة, true أو false)

دالة addEventListener تستخدم لمعالجة الأحداث في كل المتصفحات تقريبا ماعدا إنترنت إكسبلورر و تقبل ثلاث بارمترات.

نوع الحدث :نوع الحدث الذي تريد أن تعمل الدالة عند حدوثه مثل "click" كنت تريد أن تنفذ الدالة عند ضغط كلك.

الدالة المعالجة:و هي الدالة التي ستنفذ عند وقوع الحدث.

البرامتر الأخير يكون عبارة عن true أو false سنجعله الآن false و سنتحدث عن الفارق في الدرس التالي . و لنفهم بالمثال كيف تستخدم الدالة .
مثال 1
<html>
  
  <head>
  
  </head>
  
  <body>
   <input type="button" id="link" value="click here">

  </body>
    <script type='text/javascript'>
   
   
  var para = document.getElementById("link");
      
para.addEventListener("click", eventHandler, false);
      
para.addEventListener("click", otherEventHandler, false);
      
function eventHandler(event) {
alert("لقد ضغطت على " + this.nodeName);
}
      
function otherEventHandler(event) {
alert("نوع هذا الحدث كان " + event.type );
}
      
    </script>
</html>

Try it yourself »Click on the "Try it yourself" button to see how it works

يتضح من المثال أن addEventListener تستخدم كـ method للنقطة التي نعين لها الحدث .كما يتبين أيضا ميزة من مميزات هذه الطريقة و هي أنه يمكن بسهولة تعيين أكثر من دالة لنفس الحدث في حين أنه إذا أردنا عمل ذلك بالطريقة الأولى فإنه يكون موضوعا معقدا إلى حد ما. كما أيضا يتضح من السطر
alert("لقد ضغطت على " + this.nodeName);
أن الدالة التي تعين للحدث تعتبر داخل الكائن الذي يمثل النقطة التي يحدث لها الحدث و لذا يظهر لك في الصندوق الأول INPUT. البرامتر event فهو يمرر فيه تلقائيا كائن له عدد من الخصائص مثل type و التي تعرف من خلالها نوع الحدث و له خواص أخرى سنتحدث عنها و عنه لاحقا . الدالة المقابلة لـ addEventListener في الإنترنت إكسبلورر هي attachEvent و تقبل متغيرين فقط الأول نوع الحدث(يكتب نوع الحدث بشكل مختلف فبدلا من "click" يكتب "onclick" و الثاني الدالة المعالجة.

removeEventListener(نوع الحدث, المعالج, true أو flase)

تأخذ نفس البرامتر التي تأخذها addEventListener لكن تقوم بالعكس فهي .تزيل مراقبة الحدث كما يوضح المثال:
مثال
<html>
  
  <head>
  
  </head>
  
  <body>
   <input type="button" id="link" value="click here">

  </body>
    <script type='text/javascript'>
   
   
  var link = document.getElementById("link");
      
link.addEventListener("click", selfRemovingEvent, false);
      
function selfRemovingEvent(event) {
  
alert("يتم مراقبة الحدث مرة واحدة ثم إلغاء المراقبة");
  
this.removeEventListener(event.type, selfRemovingEvent,false);
}     
    </script>
</html>

Try it yourself »Click on the "Try it yourself" button to see how it works

عندما تضغط على الزر للمرة الأولى سيظهر لك صندوق alert,لكن إذا ضغطت ثانية لن يظهر الصندق لأن المراقبة يكون قد تم إزالتها من خلال دالة removeEventListener.

الدالة المقابلة في الإنترنت إكسبلورر هي detachEvent و تقبل نفس البرامترز التي تقبلها attachEvent .

الكائن Event

في كل المتصفحات بإستثناء إنترنت إكسبلورر يمرر تلقائيا للدالة كبرامتر أما في إنترنت إكسبلور فهو يكون خاصية لـ window ,و لكي يكون الكود متوافق مع المتصفحات كلها يمكنك كتابته هكذا:
function handler(event) {
event = event || window.event;
}
و الكائن event له خصائص و دوال تختلف بإختلاف الحدث لكن هناك عدد منها عم أهمهم: الخصائص:

type:نوع الحدث مثل "click" او "load".

target:سنستخدمه في معرفة العنصر الذي حدث له الحدث مثلا العنصر الذي تم الضغط عليه يختلف إنترنت إكسبلورر حيث تستخدم srcElemen . الدوال :

preventDefault():لمنع التصرف الإفتراضي من الحدوث بمعنى أنه إن كنت تضغط على لينك لا يفتح الصفحة التي كان من المفترض انه سيفتحها .

و في إنترنت أكسبلورر يكون البديل event.returnValue = false;. مثال:
مثال
<html>
<head>
    

</head>
<body>


<a href="http://www.google.com">Click here</a>


</body>
  <script type="text/javascript">
var a = document.getElementsByTagName("a")[0];
   
a.addEventListener("click", whatNode, false);

    function whatNode(event) {

alert("Target is : " + event.target);
       
event.preventDefault();
}

</script>

</html>

Try it yourself »Click on the "Try it yourself" button to see how it works

كيفية العثور على الأحداث.

أنظر إلى الشكل التالي .

هو عبارة عن ناتج كود الهيتميل هذا مع بعض الإستايل شيت.
<html>
<head>
    <style type="text/css">
        body, div, p {
padding: 10px;
border: 2px solid blue;
}
a{
 position: absolute;
left: 200px
}
    </style>

</head>
<body>
body
<div>
    div
<p>
 p
<a href="http://www.google.com">Click</a>
</p>
</div>
</body>
<html/>
عند قيامك بالضغط على اللينك Click فأنت أيضا تضغط داخل الصندوق p أي تضغط على الفقرة .و أيضا تضغط دخال الـ div و داخل الـ body , و بالطبع داخل document . بمعنى أنك عندما تضغط على عنصر فأنت أيضا تضغط على أباء هذا العنصر و أباء أبائه.

إذا كان هناك دالة ستعمل عند الضغط على اللينك aو دالة تعمل عند الضغط على p و دالة ستعمل عند الضغط على div و دالة ستعمل عند الضغط على body و دالة ستعمل عند الضغط على document.عند الضغط على اللينك أي دالة ستنفذ أولا ؟؟

ستعرف ذلك بفهم كيف يعثر المتصفح على الأحداث يتم ذلك من خلال ثلاث مراحل(three phases) يبدأ اولا من الخارج من الأب الأكبر document يبحث عن الأحداث و ينفس الدوال المعينه لها حتى يصل إلى أصغر إبن حدث له الحدث و تسمى هذه المرحلة بالـ Capturing و عند وصوله للإبن الأصغر الوصول يعتبر المرحلة الثانية و بعد الوصول يبدأ في مرحلة ثالثه Bubbling و هي أنه يبدأ ثانية من الإبن الأصغر و ينتقل منه إلى الأب حتى الأب الأكبر document يبحث عن الأحداث و ينفذها ثانية و ربما أفضل طريقة لتوضيح المفهوم تكون من خلال الأمثلة.

قبل أن نأخذ أمثلة سنذكر بعض الأشياء.

البرامتر الثالث للدالة addEventListener يحدد المرحلة التي ستنفذ فيها الدالة هل في Capturing أم Bubbling. عند وضعه true فإنه سيتم تنفيذ الدالة عند الوصول للعنصر في مرحلة الـCapturing الأولى.

أما عند وضعه false فإنه سيتم تنفيذ الدالة عند العثور عليه في مرحلة الـ Bubbling الثانية. عند معالجة الأحداث بالطريقة الأولى التي ذكرناها في أول الفصل فإنه يتم تنفيذ الدالة في مرحلة Bubbling ,و أيضا إنترنت أكسبلورر لا يدعم إلا التنفيذ في مرحلة الـBubbling .

eventPhase :خاصية من خواص الكائن event و تعرف من خلالها المرحلة التي فيها المتصفح في بحثه عن الأحداث إن كانت قيمته1 تكون المرحلة capturing و ان كانت 2 تكون المرحلة الثانية الوصول للعنصر و إن كانت 3 تكون المرحلة الثالثة bubbling مثال
مثال
<html>
<head>
    <style type="text/css">
        body, div, p {
padding: 10px;
border: 2px solid blue;
}
a{
 position: absolute;
left: 200px
}
    </style>

</head>
<body>
body
<div>
    div
<p>
 p
<a href="http://www.google.com">Click</a>
</p>
</div>
</body>
<script type="text/javascript">
   var div = document.getElementsByTagName("div")[0];
var p = document.getElementsByTagName("p")[0];
var a = document.getElementsByTagName("a")[0];
   //on Bubbling
   document.addEventListener("click", whatNode, false);
document.body.addEventListener("click", whatNode, false);
div.addEventListener("click", whatNode, false);
p.addEventListener("click", whatNode, false);
a.addEventListener("click", whatNode, false);
  //on Capturing
document.addEventListener("click", whatNode, true);
document.body.addEventListener("click", whatNode, true);
div.addEventListener("click", whatNode, true);
p.addEventListener("click", whatNode, true);
a.addEventListener("click", whatNode, true);

    function whatNode(event) {

alert(this.nodeName+' '+"phase: " + event.eventPhase);
       
event.preventDefault();
}

</script>

</html>

Try it yourself »Click on the "Try it yourself" button to see how it works

في هذا الكود :
  • من السطر 1 حتى 24 أنشأنا صفحة الهيتميل التي عرضناها في أول الدرس.
  • من السطر 26 لـ28 وصلنا إلى جميع عناصر الصفحة
  • من السطر 30 حتى 34 أضفنا معالجات دوال لكل عنصر ستلاحظ في مرحلة الـBubbling.
  • من السطر 36 حتى 40أضفنا معالجات دوال لكل عنصر ستلاحظ في مرحلة الـCapturing .
  • بداية من السطر 42 عرفنا دالة whatNode التي ستعمل عند حدوث الحدث و هي تظهر إسم العنصر الذي تنفذ دالته و المرحلة التي فيها البحث (eventPhase)
إذا ضغطت على اللينك click ستظهر الرسائل بهذا الترتيب:
#document phase: 1
BODY phase: 1
DIV phase: 1
P phase: 1
A phase: 2
A phase: 2
P phase: 3
DIV phase: 3
BODY phase: 3
#document phase: 3
حيث ستبدأ المرحلة الأولى الـCapturing من الخارج للداخل و لأننا و سيتم تنفيذ معالجات الأحداث التي لها القيمة true في البرمتر الثالث ثم عندما نصل لأصغر عنصر حدث له حدث الضغط و هو اللينك نصبح إنتقالنا للمرحلة 2 و يعود البحث ثانية من الداخل إلى الخارج في المرحلة الثالثة الـBubbling و تنفذ فيها معالجات الأحداث التي لها القيمة false في البرامتر الثالث . إذا قمت بالضغط على div فإن هذه الرسائل فقط ستظهر:
#document phase: 1
BODY phase: 1
DIV phase: 2
DIV phase: 2
BODY phase: 3
#document phase: 3
فكما قلنا أن الضغط على عنصر يؤثر على العناصر الأباء له و أباء الأباء.

stopPropagation()

هذه الدالة من دوال (methods) الكائن event ,ووظيفتها أنها توقف البحث عن الأحداث كما بالمثال التالي حيث سنعدل دالة whatNode بحيث أن البحث عن الأحداث و تنفيذ الدوال بالتالي سيتوقف عند الوصول للـ div .
function whatNode(event) {
if (this.nodeName === "DIV") {
event.stopPropagation();
}
console.log(this.nodeName, "phase: " + event.eventPhase);
event.preventDefault();
}
و من فهم كيف يتم تنفيذ الأحداث يمكننا الإستفادة من ذلك في بعض التطبيقات مثلا يمكنك إضافة دالة ما تعمل عند الضغط على أي لينك فبدلا من أن تحدد معالجات الأحداث له بإستخدام whlie بهذه الطريقة :
var allLinks = document.getElementsByTagName("a");
var i = allLinks.length; (continues on next page)
172 The JavaScript Pocket Guide
while (i--) {
allLinks[i].addEventListener("click", somethingSpecial,false);
}
function somethingSpecial(event) {
alert(this.href);
event.preventDefault();
}
يمكننا أن نفعل نفس الشيء بطريقة أبسط هكذا
document.addEventListener("click", delegatedSomethingSpecial,true);
function delegatedSomethingSpecial(event) {
if (event.target.nodeName === "A") {
alert(event.target.href);
event.preventDefault();
و ميزة هذه الطريقة الثانية إذا أضيفت لينكات جديدة للصفحة من خلال الجافا سكريبت أو أجاكس(ajax) فإنه أيضا ستعمل الدالة عند الضغط عليهم و تسمى الطريقة الثانية بالـevent delegation.
December 17, 2011