هذا الجزء الثاني من درس كتابة مكونات الأجاكس في لغة Javascript ضمن سلسلة الأجاكس بسهولة، ذكرنا في الدرس الماضي بداية معرفة كتابة مكونات الأجاكس وعن كائن XMLHttpRequest وتضمينه في متغير requester والتأكد من تفعيله في كائن ActiveX (لمستخدمي متصفح الإسكبلورر).

في الجزء الثاني من الدرس سنتعرف على بقية مكونات الأجاكس عن طريق كائن XMLHttpRequest نفسه حيث يحتوي على الطرق methods التي نريد إستخدامها.

الإتصال بالخادم

للإتصال بالخادم Server وإسترجاع المعلومات منه، يجب إستخدام طريقتين في كائن XMLHttpRequest وهما open و send.

طريقة open تقوم بعمل الإتصال وتأخذ خاصيتين مطلوبتين مع خاصية ثالثة إختيارية، الخاصية الأولى هي نوع الطلب التي تريد إرساله وتتكون من قيم مثل (GET, POST, DELETE, … )، أما الخاصية الثانية وهي مسار الطلب (مثل file.php أو file.xml على سبيل المثال).

نأتي بعدها للخاصية الثالثة الإختيارية المنطقية والتي تحدد حالة الطلب بسمتين وهما المتزامنة asynchronously (تحمل القيمة true) والغير متزامنة synchronously (تحمل القيمة false)، ما الفرق بين السمتين؟

في حال إستخدام السمة الغير متزامنة synchronously فإن تطبيق الاجاكس سيمنع أي تفاعل آخر للغة Javascript وتجميد المتصفح إلى الإنتهاء من إستدعاء البيانات من الخادم، أما السمة المتزامنة asynchronously تقوم بعمل الإستدعاء في بطريقة غير ملاحظة وهذا يضمن إمكانية التفاعل مع المستخدم دون حدوث الأشياء المذكورة في السمة الغير متزامنة، أي الأفضل إستخدام السمة المتزامنة.

ما شرحناه في الأعلى يمكن رؤيته في شفرة Javascript هذه:

requester.open("GET", "/query.php", true);

بعد الإتصال بإستخدام طريقة open أي فتح الطلب، تأتي بعدها طريقة send وهي إرسال الطلب إلى الخادم والتي تنشط الإتصال بإستخدام خواص مساعدة وتستخدم حقل مكون من المتغيرات المراد إرفاقها في الطلب وخاصة في حال إستخدام طلب من نوع POST، مثال إضافي على إستخدام طريقة send:

requester.open("POST", "/query.php", true);
requester.send("name=ahmed&email=example@example.com");

ويمكن إستخدام طريقة setRequestHeader في تحديد شفرة البيانات أو رأس الطلب، تتكون من من حقلين رأس الطلب وقيمته، مثال إفتراضي:

setRequestHeader(header, value)

تعدد رؤوس الطلب، أبرز القيمة المستخدمة في هذه الطريقة هي تحديد Content-Type ، لاحظ الشفرة المتكونة مما كتبناه في الأعلى إضافةً إلى تحديد رأس الطلب:

requester.setRequestHeader("Content-Type",
"application/x-www-form-urlencoded");
requester.open("POST", "/query.php", true);
requester.send("name=ahmed&email=example@example.com");

في المثال السابق رأس الطلب Content-Type أما قيمته فهي “application/x-www-form-urlencoded” وتستخدم في تشفير البيانات المستدعاه مثل الإسم والبريد الإلكتروني وغيره، هذه الطريقة مطلوبة في متصفح Opera وبالتحديد إستخدام Content-Type لطلب من نوع POST. أما بقية المتصفحات فالطريقة غير مطلوبة.

الآن سنحتاج إلى خواص أخرى بعد ما ذكرنا خاصية open و send ، وهي تعبر عن اللحظة التي يتم فيها إستدعاء البيانات من الخادم، سنتعرف على خاصية readyState والتي تمثل حالة إتصال الكائن في الوقت الحالي، ويمكن أن تأخذ أي من هذه القيم:

  • 0 – (uninitialized – غير مشغل)
  • 1 – (loading – تحميل)
  • 2 – (loaded – محمّل)
  • 3 – (interactive – تفاعلي)
  • 4 – (complete –  مكتمل)

نستطيع رؤية تغييرات خاصية readyState عن طريق حدث onreadystatechangeHandler، سنحتاجه في فحص نتائج الإتصال وستكون خاصية readyState ضمن هذا الحدث، تستطيع تعريف الحدث بإنشاء دالة مجهولة لتنفيذ بقية الخطوات:

requester.onreadystatechange = function() {
 // فحص قيمة خاصية readyState، إذا إكتمل الإتصال نجري بقية الطلب
 if(requester.readyState == 4) {
 ...
 }
}

بعد التحقق من إكمال إستدعاء البيانات بإستخدام XMLHttpRequest بعد الإتصال، يجب التحقق من عدم وجود خطأ HTTP مثل خطأ 404 (تعني الصفحة غير موجودة) وذلك عن طريق خاصية status ويجب أن تحتوي على أعداد صحيحة.

قيم status التي سنستخدمها ستكون مثل قيمة 200 والتي تعني أن الطلب منفذ، وأيضاً قيمة 304 والتي تعني أن الطلب غير محول.

يمكنك إستخدام باقي قيم status إذا أردت ذلك، هذه نتيجة النهائية لشرحناه في الأعلى:

requester.onreadystatechange = function () {
 // فحص قيمة خاصية readyState، إذا إكتمل الإتصال نجري بقية الطلب
 if (requester.readyState == 4) {
 // التحقق من قيم حالات HTTP
 if (requester.status == 200 || requester.status == 304) {
 // بقية الشفرة في حال نجاح الطلب
 } else {
 // بقية الشفرة في حال فشل الطلب
 }
 }
}

ملاحظة: يمكنك إستخدام كائن XMLHttpRequest في إتصال واحد فقط، في حال اردت عمل أكثر إسترجاع بيانات جديدة من الخادم يجب إنشاء كائن XMLHttpRequest آخر.

التعامل مع البيانات

هناك طريقتين للتعامل مع البيانات المستدعاه من الخادم، الأولى تستقبل البيانات النصية من نوع HTML وتمثل خاصية موجودة في كائن XMLHttpRequest إسمها responseText، وتستخدم خاصية innerHTML الموجودة في Javascript في إظهار البيانات المستدعاه عن طريق responseText والتي تتيح كتابة النص في عناصر HTML.

الثانية تستقبل البيانات من نوع XML والخاصية التي تمثلها هي responseXML، ويمكن الوصول لعناصر XML بواسطة DOM وطرقها للوصول إلى عناصر هذه المحتويات مثل nameNode ، nodeValue ، getElementById ، getElementsByClassName ، getElementsByTagName وغيرها.

لتكملة المثال الأخير سنستخدم responseText للتعامل مع بيانات من نوع العادي أو HTML:

requester.onreadystatechange = function () {
 // فحص قيمة خاصية readyState، إذا إكتمل الإتصال نجري بقية الطلب
 if (requester.readyState == 4) {
 // التحقق من قيم حالات HTTP
 if (requester.status == 200 || requester.status == 304) {
 document.getElementById('box').innerHTML = requester.responseText;
 } else {
 document.getElementById('box').innerHTML = 'هناك خطأ في طلب إستدعاء البيانات ..';
 }
 }
}

بالنسبة للعنصر الذي حددناه في الشفرة السابقة لإظهار إستجابة طلب البيانات هو box وتم كتابته بشكل إفتراضي على أساس أنه موجود ضمن شفرة HTML للصفحة.

الشفرة كاملة

الآن سنضع الشفرات التي كتبناها بالأعلى، سأضع مثال عملي بسيط في الدرس القادم لتتمكن من فهم الأشياء التي سنكتبها وهو مثال بسيط وليس معقد، رتبت الشفرة لتظهر بشكل منطقي حسب إستخدامي الشخصي:

function ajaxRequest() {
 var requester = false;

 if(window.XMLHttpRequest) {
 requester = new XMLHttpRequest;
 } else if (window.ActiveXObject) {
 requester = new ActiveXObject("Microsoft.XMLHTTP");
 }

 if(requester) {
 requester.onreadystatechange = function() {
 if(requester.readyState == 4 || requester.readyState == "complete") {
 if(requester.status == 200 || requester.status == 304) {
 // ستظهر الإستجابة ضمن عنصر إفتراضي بإسم box
 // على سبيل المثال
 document.getElementById('box').innerHTML = requester.responseText;
 } else {
 document.getElementById('box').innerHTML = 'هناك خطأ في طلب إستدعاء البيانات';
 }
 }
 }

 // ملف query.php كمثال على إستدعاء البيانات من طرف الخادم
 requester.open("GET", "query.php", true);
 requester.send(null);

 }
 }

ترقبوا الدرس القادم وسيكون عملي على ما شرحته في آخر درسين وسيكون تطبيق بسيط عبارة عن عرض للأحداث حسب السنة التي يختارها المستخدم، وسنتعامل مع ملف php في سرد الأحداث وتجهيزها بإستدعائها من قاعدة البيانات وسيكون الدرس الأخير من الجزء الأول من سلسلة الأجاكس بسهولة.

أجزاء أخرى لدرس كتابة الأجاكس في Javascript: