السبت، 8 يونيو 2013
11:04 ص

شرح الأجاكس Ajax من الصفر إلى الإحتراف - دورة كاملة


كما كنت قد وعدتكم من قبل عند وصول صفحة الفيسبوك الخاصة بنا إلى 1000 لايك سأقوم بوضع دورة كاملة فى الأجاكس فى تدوينة واحدة، وها أنا الآن أفي بوعدي لكم بمنحكم تلك التدوينة التي أتمنى أن تنال إعجابكم -بإذن الله-، وكالعادة سأقسم التدوينة إلى دروس، أترككم مع تلك الدروس.
-الدرس الأول:
ما هي الأجاكس؟ .. ببساطة الأجاكس ليست لغة برمجة، إنما الأجاكس عبارة عن تقنية تقوم بشيء معين، ونستخدم فيها أكثر من لغة أهمها لغة JavaScript ، لكن ما وظيفة تلك التقنية؟
عندما يكون بموقعك رابط إلى صفحة داخلية للموقع، يتم إعادة تحميل الـHeader و الـFooter والقائمة الجانبية مع أنهم لا يتغيرون ! فعندئذِ يرسل المتصفح Request للسيرفر لطلب الصفحة، ويرجع Response من السيرفر للمتصفح فيقوم بإعادة تحميل الـResponse، لكنه يرسل الصفحات كاملة، حيث أنك لطلب صفحة داخلية بموقعك؛ يتطلب ذلك إعادة تحميل الصفحة بكامل حتى الأجزاء الثابتة بها، وطبعًا تلك مشكلة كبيرة للمواقع ذات عدد زوار هائل.
وظيفة الأجاكس هي أن تقوم بتقسيم الصفحات إلى أجزاء Slices، وعند عمل Request من المتصفح، نقوم بعمل Request لجزء معين فقط يتم تحميله فى مكان معين فى شيفرة HTML؛ لذلك لن يتم إعادة تحميل الصفحة بكاملها، بل سيتم تحميل جزء معين فقط مع ثبات وجود الصفحة.
تُعطي أيضًا تقنية الأجاكس مظهرًا جميلاً للموقع.

- الدرس الثاني:
سنقوم بالبدء فى كتابة الشيفرة، سنقوم أولاً بصنع Button وفى الحدث Onclick سنقوم بوضع اسم دالة سنقوم بإنشاءها عبر JavaScript، سنسمي تلك الدالة getInfo()، لذلك ستكون شيفرة هذا الـButton كالتالي:
<button onclick="getInfo()"> Get Details </button>
ثم الآن سنقوم بإنشاء Div يحمل ID يسمّى Jax، وذلك الـDiv هو المكان الذي سيعرض فى الجزء المحدد الذي سنقوم بعمل Request له.
<div id="Jax">
</div>
الآن قمنا بأول خطوتين عبر لغة HTML، سنقوم الآن بالخطوة الثالثة وهي إنشاء دالة عبر JavaScript كما فى الشيفرة التالية:
<script type="text/javascript">
function getInfo(){

}
</script>
الآن قمنا بالتجهيز للعمل، سنقوم بعد ذلك بالعمل على دالة getInfo.

- الدرس الثالث:
الآن بداخل دالة getInfo سنقوم بإنشاء متغير ليصح هذا المتغير فيما بعد كائن Object، كائن يرث من XMLHttpRequest لنقوم بالبدء فى تلك المهمة، لكن للأسف XMLHttpRquest هي للمتصفحات الحديثة، أما متصفحات مثل Internet Explorer قد لا تعمل معها هذا الكلاس، لذلك سنقوم بوضع شرط بسيط، فإذا كان المتصفح لديه XMLHttpRquest إذًا سيقوم الكائن بالإشتقاق منه، أما إذا كان لم يكن موجودًا، فسيرث من آخر وهو ActivXObject، لذلك سنقوم بكتابة الشيفرة التالية:
<script type="text/javascript">
function getInfo(){
var xmlhttp;
if(window.XMLHttpRequest)
xmlhttp = new XMLHttpRequest();
else
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
}
</script>
ثم بعد تلك السطور، سنقوم بكتابة شيفرة، لن أقوم بشرحها الآن، لكن سأقوم بشرحها فى بعض النقاط المتقدمة:
xmlhttp.onreadystatechange = function(){
if(xhtmlhttp.readyState == 4 & xmlhttp.status == 200)
document.getElementById("Jax").innerHTML = xmlhttp.responseText;
}
نلاحظ أننا فى الشيفرة السابقة كتبنا اسم الـID الذي سنستخدمه فى وضع البيانات، وهو Jax.
ثم الآن سنقوم بإستخدام دالتين، الأولى Open وظيفتها أخذ طريقة إرسال البيانات -إن كانت POST أو GET- والثانية لوضع اسم الملف الذي سنأخذ منه مخرجات HTML التي سيتم تضمينها فى صفحتنا الحالية، والثالث سنضع له قيمة TRUE لجعل الشيفرة غير متزامنة، ومعني غير متزامنة أى عندما يقوم المتصفح بعمل الـRequest قد تقوم بأنت بالقيام ببعض عمليات JavaScript خلال هذا الطلب، قد تكون تلك العمليات، عملية طلب أخرى، لذلك عند وضعك TRUE تمكنك من القيام ببعمل تلك العمليات أثناء الـRequest، لكن عند وضع FALSE سيقف تنفيذ أى شيفرات JavaScript حتى يتم رجوع الـResponse.
والدالة الثانية هي دالة الإرسال Send إلى شيفرة HTML، ولا نقوم بأدخال بارامترات فيه إلا إذا كانت وسيلة الإرسال المحددة فى دالة Open عن طريق POST، وسنعرف طريقة إرجاع البيانات بالطريقتين POST و GET -إن شاء الله-.
xmlhttp.open("GET","info.php",TRUE);
xmlhttp.send();
الآن، أنت قمت بالتجهيز ليتم تلك العملية بنجاح ! .. قم بإنشاء ملف info.php، وقم بوضع شيفرة PHP أو HTML بداخلها،
ثم الآن قم بتشغيل صفحتك التى وضعت قمت بتلك الخطوات بداخلها، ستجد زرًا، إضفط عليه، سيقوم بعرض البيانات المستخرجة من ملف info.php الذي قمت بكتابته.

- الدرس الرابع:
قد تحتاج في تلك الطريقة مثلاً أن تقوم بطلب ID معين يتم إرساله إلى صفحة info.php لتسترج شيء معين من قاعدة البيانات يحمل هذا الـID ومن ثم طباعته فى الصفحة التي تعمل عليها، لذلك سنتعرف على طريقة إرسال بيانات لصفحة info.php إذا كانت الطريقة GET أو POST.
أولاً سنتعرف على كيفية إرسال البيانات إلى صفحة info.php إذا كانت طريقة الإرسال GET.
فى تلك الحالة يجب أن نقوم بكتابة علامة إستفهام بجانب info.php فى دالة Open ثم سيتم إرسال البيانات بشكل طبيعي جدًا عبر كتابة المتغير ثم علامة يساوى ثم قيمته بجوار info.php فى دالة Open، وإذا أردت إضافة متغير آخر يمكنك عبر إضافة & ثم اسم المتغير ثم علامة يساوى ثم قيمته، كما فى المثال التالي:
xmlhttp.open("GET","info.php?id=10&name=ahmedessam",TRUE);
xmlhttp.send();
الآن فى ملف info.php يمكنك عبر PHP طباعة تلك المتغيرات عبر تلك السطور:
<?php
echo $_GET['id']."<br>";
echo $_GET['name'];
?>
الآن إذا قمت بإستعراض الصفحة التي تعمل عليها وقمت بالضغط على الزر، سيعرض لك رقم 10 وأسفله اسم ahmedessam.
لكن هل الطريقة POST تستخدم نفس تلك الطريقة؟
بالطبع لا، ففى الطريقة POST نقوم فقط بوضع اسم الملف الذي سنأخذ منه البينات كما هو info.php فقط، ثم سنقوم بإستخدام دالة أخري مهمة، ثم سنقوم بوضع المتغيرات وقيمها التى نريد إرسالها عن طريق دالة Send.
xmlhttp.open("POST","info.php", TRUE);
xmlhttp.SetRequestHeader("Conect-Type","application/x-www-form-urlencoded");
xhttp.send("id=10&name=ahmedessam");
طبعًأ دالة SetRequestHeader هي للتوضيح أننا سنقوم بإستخدام Form، وهي دالة ثابتة الشكل هكذا عن إستخدامنا طريقة POST، والآن إذا قمت بفتح الصفحة التى تعمل عليها وعند الضغط على الزر سيخرج نفس النتيجة السابقة.

- الدرس الخامس:
تحدثنا عن عن البارامتر الثالث فى دالة open التي أعطيناها قيمة TRUE، نسيت أن أذكر أن قيمة هذا البارامتر يجب أن تكون TRUE فى حالة إستخدام خاصية Onreadystatechange والتي موجودة فى الشيفرة التي ذكرت اننى سأتركها قليلاً.
تلك الشيفرة:
xmlhttp.onreadystatechange = function(){
if(xhtmlhttp.readyState == 4 & xmlhttp.status == 200)
document.getElementById("Jax").innerHTML = xmlhttp.responseText;
}
تلك الخاصية مسئولة عن التعامل مع الـResponse الذي يأتي من السيرفر، وتلك الخاصية هي عبارة عن دالة، أو بمعني أصح نقوم نحن بصنع دالة فيها، ولكن ما الشروط الموجودة فى تلك الدالة؟
أولاً سنقوم بتفصيل الخواص التي قمنا بمقارنتها بداخل تلك الجملة، خاصية readyState، وهي خاصية تأخذ قيم من 1 إلى 4 فقط وهي تتغير طوال فترة عمل الـRequest.
إذا كانت قيمتها 1: إذا تم الإتصال بالسيرفر.
إذا كانت قيمتها 2: تم إستقبال الـRequest فى السيرفر.
إذا كانت قيمتها 3: جاري معالجة الـRequest.
إذا كانت قيمتها 4: تم الإنتهاء من الـRequest والـResponse الآن جاهز.
وهو ما قمنا بمقارنته فى الجملة الشرطية، حيث نستطيع إعادة ترجمة الشرط الأول كالتالي: إذا تم الإنتهاء من الـRequest والـResponse الآن جاهز، و (الشرط الثاني) ستقوم بالقيام بالسطر الذي يليه، لكن ما هو الشرط الثاني؟
يجب لفهم الشرط الثاني فهم خاصية status أولاً، فتلك الخاصية تأخذ قيمتين فقط لا ثالث لهم، إما 200 أو 404، إذا كانت 200 معناه أن الصفحة أو البيانات التى طلبتها موجودة وجاهزة، أما 404 معناها أن الصفحة او البيانات التى طلبتها غير موجودة.
إذًا فى هذا الشرط نقول: إذا كان تم الإنتهاء من الـRequest و الـResponse جاهز، و البيانات المطلوبة موجودة وسليمة إذا ستقوم بتنفيذ هذا السطر:
document.getElementById("Jax").innerHTML = xmlhttp.responseText;
وهذا السطر أعتقد واضح جدًا، يقوم بأخذ العنصر الذي يحمل الـID المسمّى بـJax، ثم تتقوم خاصية innderHTML والتي وظيفتها إضافة شيفرة HTML بوضع responseText بداخل هذا العنصر، وخاصية responseText هذه يكون مخزن بها نص الـHTML الذي يخرج من السيرفر.
الآن يمكنك عبر خاصية readystate القيام بعملية أكثرذكاءًا ! كما بالشيفرة التالية:
xmlhttp.onreadystatechange = function(){
if(xhtmlhttp.readyState == 1)
document.getElementById("Jax").innerHTML = "جاري الإتصال بالسيرفر";
else if(xhtmlhttp.readyState == 2)
document.getElementById("Jax").innerHTML = "تم إستقبال الطلب";
else if(xhtmlhttp.readyState == 3)
document.getElementById("Jax").innerHTML = "جاري معالجة الطلب";

if(xhtmlhttp.readyState == 4 & xmlhttp.status == 200)
document.getElementById("Jax").innerHTML = xmlhttp.responseText;
}
هل علمت وظيفة تلك الشيفرة الآن؟ .. إذا كنت لا تعلم وظيفتها فأنت بحاجة إلى الصعود قليلاً للتعرف على خاصية readyState التى قمت بشرحها قبل قليل.
لكن حقيقة تلك الشيفرة لن تعمل معك اصلاً إذا كنت على السيرفر المحلي، والسبب فى ذلك ان الـRequest يكون سريع جدًا على السيرفر المحلي، لكن لن يظهر هذا الكلام إلا عند وضع تلك الصفحات على الإنترنت.

- الدرس السادس:
ماذا إذا قمت بوضع البارامتر الثالث فى دالة Open بقيمة False ، هنا ستكون الدالة متزامنة ولذلك سيتم إيقاف أى REquest آخر وتنفيذ Request واحد فقط وهو الحالي، لكن فى تلك الحالة لن تحتاج إلى خاصية onreadystatechange ابدًا، بل سنقوم بحذفها، ثم سنقوم بإعطاء امر ادخال شيفرة HTML بعد دالة send كما بالشيفرة التالية:
<script type="text/javascript">
function getInfo(){
var xmlhttp;
if(window.XMLHttpRequest)
xmlhttp = new XMLHttpRequest();
else
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");

xmlhttp.open("GET","info.php?id=10&name=ahmedessam",FALSE);
xmlhttp.send();
document.getElementById("Jax").innerHTML = xmlhttp.responseText;
}
</script>
ملاحظة: السيرفر إذا كان عليه ضغط، قد يصبح موقعك Hanged بسبب تلك الطريقة.
ملاحظة: إذا كنت وضعت فى البارامتر الثاني فى دالة Open ملف إمتداده XML ، فيمكنك تغيير خاصية responseText بخاصية أخري مسؤولة عن مخرجات XML تُسمّى responseXML.

- الدرس السابع:
يمكنك جعل الدالة عمومية أكثر، وذلك عبر إضافة بارامترات لدالة getInfo، سأقوم بوضع مثال مباشر وعليك أن تقوم بإستنتاج ما حدث:
<script type="text/javascript">
function getInfo(page,id){
var xmlhttp;
if(window.XMLHttpRequest)
xmlhttp = new XMLHttpRequest();
else
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");

xmlhttp.onreadystatechange = function(){
if(xhtmlhttp.readyState == 4 & xmlhttp.status == 200)
document.getElementById(id).innerHTML = xmlhttp.responseText;
}

xmlhttp.open("GET",page,TRUE);
xmlhttp.send();
}
</script>
هل تعلم ما حدث؟! .. ألم تعلم حتى الآن؟؟! .. حسنًا سأبسّط عليك الموضوع، حيث أننا سنقوم بتغيير شيفرة الـButton إلى التالي:
<button onclick="getInfo('info.php','Jax')"> Get Details </button>
هل علمت الآن؟ .. نعم لقد جعلنا الدالة أكثر ديناميكية، حيث أنك عند إستدعاء الدالة ستقوم بتحديد الملف الذي تريد منه البيانات، وأيضًا ID المكان الذي تريد وضع المخرجات فيه ! أليس رائعًا؟!
تحسبًا أيضًا لمشاكل ميكروسوفت الغبية، سنقوم بتطوير الشيفرة؛ وذلك لأن ميكروسوفت لديها ثلاثة إصدارات للـRequest لذلك سنقوم بوضع شرط لضمان عمل الشيفرة.
<script type="text/javascript">
function getInfo(page,id){
var xmlhttp;
if(window.XMLHttpRequest)
xmlhttp = new XMLHttpRequest();
else{
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
if(!xmlhttp)
xmlhttp = new ActiveXObject("Mmxl2.XMLHTTP.3.0");

if(!xmlhttp)
xmlhttp = new ActiveXObject("Mmxl2.XMLHTTP.6.0");

} xmlhttp.onreadystatechange = function(){
if(xhtmlhttp.readyState == 4 & xmlhttp.status == 200)
document.getElementById(id).innerHTML = xmlhttp.responseText;
}
xmlhttp.open("GET",page,TRUE);
xmlhttp.send();
}
</script>

ماذا إذا كنت تريد إضافة صورة Waiting مثلاً لإنتظار الطلب؟ .. إذا كنت قد فهمت جميع الخطوات السابقة ستفهم كيفية القيام بذلك، ولكني سأقوم بوضع الشيفرة التي ستقوم بإضافتها إلى الصفحة الكاملة:
if(xhtmlhttp.readyState < 4){
document.getElementById(id).innerHTML = "<img src='wait.gif' />";
}
ملاحظة: لإنهاء الـRequest لأي سبب من الأسباب تستطيع ذلك عبر الدالة abort.


المزيد من المواضيع:

3 التعليقات:

  1. هنا:
    =======================
    xmlhttp.open("GET","info.php", TRUE);
    xmlhttp.SetRequestHeader("Conect-Type","application/x-www-form-urlencoded");
    xhttp.send("id=10&name=ahmedessam");
    =======================

    أعتقد أنك تقصد POST وليس GET (في الدالة الأولى).

    ردحذف
    الردود
    1. نعم، كان مجرد خطأ وتم التعديل .. شكرًا لك :)

      حذف
  2. يا سلام على الموضوع
    بارك الله فيك أخي موضوع مفيد

    ردحذف