זהו המאמר האחרון בסדרת המאמרים המסבירים ומלמדים כיצד להשתמש ב-jQuery. במאמר הקודם למדנו על פונקציות הליבה של jQuery ובמאמרים הקודמים למדנו עד כה את כל הפונקציות שאפשר לעשות ב-jQuery ועכשיו נותר לנו רק לעבור על נושא ה-AJAX. למי שלא מכיר (יש כאלו?) AJAX זוהי טכנולוגיה המאפשרת לנו לשלוח מידע לשרת ולקבל מידע ממנו ללא כל צורך בריפרוש הדף. היתרון הגדול שיש ב-AJAX הוא ממשק זורם ונוח ללקוח.
אני מניח שיש לקוראי המאמר ידע מסוים ב-AJAX. אם אין לכם כזה ידע, זו הזדמנות טובה לקרוא את מאמר ההסבר הבסיסי על AJAX.
צד השרת במדריך זה הוא פשוט מאד, כל מה שדף ה-php עושה הוא לקחת את מחרוזת הטקסט שאני שולח לו (אנגלית בלבד ללא מספרים), להפוך אותה באמצעות פקודת reverse ולשלוח אותה חזרה. קוד ה-php הוא:
<?php
if(ctype_alpha($_REQUEST['myName']))
{
$string =$_REQUEST['myName'];
$result = strrev($string);
print $result;
}
else
{
die;
}
?>
דף ה-php נמצא במיקום https://internet-israel.com//internet_files/ajax_example/ajax.php ולשם אני שולח את כל פקודות ה-ajax שלי.
הפונקציה הבסיסית: ajax
עם ajax.$ אנו יכולים בעצם לעשות כמעט כל מה שאנו רוצים מבחינת AJAX. כל מה שהפונקציה הזו מקבלת הוא אובייקט שמכיל את כל הפרטים שאנו צריכים על מנת לבצע את התקשורת בינינו לשרת באמצעות אובייקט ה-xmlhttp. הפונקציה לא מוצמדת לשום אובייקט כמובן והיא רצה באופן עצמאי. האובייקט שהיא מקבל מורכב ממספר פרמטרים שקובעים לאן אנו שולחים את בקשת ה-AJAX, באיזה פורמט, באופן אסינכרוני או סינכרוני וכו'. זה הרבה יותר פשוט ממה שזה נשמע. אני אדגים באמצעות דוגמא פשוטה. כל מה שהדוגמא הזו עושה הוא לשלוח מחרוזת של טקסט פשוטה ביותר בלי התחכמויות בדיוק כמו במדריך ה-AJAX למתחילים. שימו לב להכניס טקסט כלשהו באנגלית בלבד.
תוצאה:
מה שקורה כאן הוא פשוט מאד – ברגע שנלחץ הכפתור משוגרת פונקצית ajax שאליה אני מזין אובייקט בעל 4 תכונות: באיזו מתודה אני שולח (get), לאן אני שולח (המיקום של ה-php), איזה מידע אני שולח (מידע הנלקח מה-input) ואיזו פונקציה אני רוצה שתרוץ במידה ויש הצלחה. וכך זה נראה בקוד:
function executeAJAX1(value) //פונקצית השליחה שמקבל ערך למשלוח
{
$.ajax({
type: "GET",
url: "https://internet-israel.com/internet_files/ajax_example/ajax.php",
data: "myName="+value,
success: function(msg){
$('#result1').append(msg);
}
});
}
$('#myButton1').click(function () { // אירוע קליק פשוט שמפעיל פונקציה שמקבל את הערך של שדה מסוים
var value = $('#example1').val();
executeAJAX1(value);
});
לקוד יש שני חלקים – הפונקציה בתחתית שמכילה את אירוע הקליק שהיא רגילה לחלוטין ומי שעבר על המאמרים הקודמים אמור להבינה לחלוטין ופונקצית ה-ajax שהסינטקס שלה פשוט – כל מה שאני צריך להעביר לתוכה זה אובייקט עם תכונות. אני לא חייב להסתפק ב-4 התכונות האלו כמובן אלא אני יכול לצרף הרבה יותר תכונות. להלן כל התכונות שאפשר להצמיד לאובייקט:
async
תכונה בוליאנית שקובעת אם המידע מועבר בצורה סינכרונית או אסינכרונית. באופן דיפולטיבי AJAX תמיד עובד בצורה אסינכרונית. אם אנו עובדים באופן סינכרוני, אזי הדפדפן 'יקפא' ולא יעבוד עד שהשרת יחזיר תשובה. זה שימושי במידה והמידע שעובר הוא קריטי להמשך הפעילות. הסיכון המשמעותי הוא שאם מדובר באינטרנט אקספלורר, הדפדפן יכול לקפוא עד שתי דקות (!) במידה ויש בעיות לאורך הקו.
דוגמא:
אני שולח את הדוגמא ל-php זהה לחלוטין ל-php הדוגמא שלנו, רק שהוא משהה את התגובה למשך 10 שניות. שימו לב איך במשך 10 שניות אינכם יכולים לבצע שום פעולה אם אתם משתמשים באינטרנט אקספלורר. דפדפנים אחרים מגיבים בצורות שונות.
תוצאה:
function executeAJAX2(value)
{
$.ajax({
type: "GET",
url: "https://internet-israel.com/internet_files/ajax_example/ajax.php",
data: "myName="+value,
async: true,
success: function(msg){
$('#result2').append(msg);
}
});
}
$('#myButton2').click(function () {
var value = $('#example2').val();
executeAJAX2(value);
});
beforeSend
תכונה המאפשרת לנו להריץ פונקציה ממש לפני שהמידע ב-AJAX יוצא לדרך. שימושי מאד לבדיקת אובייקט ה-XMLHttpRequest או ביצוע מניפולציות נוספות שלא חשבנו עליו.
תוצאה:
בדוגמא הזו למשל, הצמדתי ל-request headers איזושהו ערך. אם יש לכם firebug (ומאד כדאי שיהיה לכם), אתם מוזמנים לחטט ב-header ולראות מה עשיתי. איך עושים את זה? מריצים את השאילתא, פותחים את פיירבאג, בוחרים ב-console, לוחצים על השורה שאתם רואים שם ובוחרים ב-headers. כך הקוד נראה:
function executeAJAX3(value)
{
$.ajax({
type: "GET",
url: "https://internet-israel.com/internet_files/ajax_example/ajax.php",
data: "myName="+value,
beforeSend: function(XMLHttpRequest) {XMLHttpRequest.setRequestHeader('Test', 'lalalala')},
success: function(msg){
$('#result3').append(msg);
}
});
}
$('#myButton3').click(function () {
var value = $('#example3').val();
executeAJAX3(value);
});
cache
כמו async גם cache היא תכונה בוליאנית ואפשר להעביר בה false על מנת למנוע מהדפדפן לבצע caching למידע המגיע מהשרת. שימושי מאד בכמה מקרים ולא שימושי כלל.
dataFilter
כמו beforeSend רק ש-dataFilter רצה מייד עם קבלת המידע מהשרת וכך אנחנו יכולים לבדוק את המידע שמתקבל או להריץ עליו פעולות שונות. לפונקציה יש שני פרמטרים: type ו-data. כש-type זה סוג המידע וה-data הוא המידע עצמו.
בדוגמא הבאה, אם השם המתקבל מהשרת הוא ההיפוך של moshe, אני משנה את התוצאה ל-hello, my name is Moshe. נסו להקליד moshe ולראות מה קורה:
תוצאה:
וככה זה נראה:
function executeAJAX4(value)
{
$.ajax({
type: "GET",
url: "https://internet-israel.com/internet_files/ajax_example/ajax.php",
data: "myName="+value,
dataFilter: function(data,type) {if(data=='ehsom'){return 'hello, my name is Moshe'};},
success: function(msg){
$('#result4').append(msg);
}
});
}
$('#myButton4').click(function () {
var value = $('#example4').val();
executeAJAX4(value);
});
dataType
סוג המידע שאנו מצפים לקבל מהשרת. סוג המידע קובע את דרך ההתייחסות שלנו למידע, אנו יכולים להגדיר את ה-dataType באופן הבא:
script – מעריך את המידע כ-javascript ומחזיר אותו כטקסט.
json – מעריך את המידע כאובייקט json ומחזיר אותו כאובייקט JavaScript.
jsonp – יוצר קריאת JSONP.
text – מעריך את המידע כטקסט פשוט.
באופן דיפולטיבי, dataType מוגדר להערכה של המידע המתקבל מהשרת כ-html או xml.
error
פונקציה שרצה במקרה ויש תקלה כלשהי – כלומר השרת אינו מחזיר 200. תקלה נפוצה היא למשל קוד 404 – הדף אינו נמצא. כאן למשל אני כותב כתובת לא נכונה על מנת שהשרת יחזיר לי 404. פונקצית error היא שימושית מאד במקרה זה כיוון שהיא תדפיס לי הודעת שגיאה:
תוצאה:
כך זה נראה, בדיוק כמו success.
function executeAJAX5(value)
{
$.ajax({
type: "GET",
url: "https://internet-israel.com/internet_files/ajax_example/ajax_erroraaa.php",
data: "myName="+value,
error: function () {
$('#result5').append('Malfunction has occoured. please try again later.');
} ,
success: function(msg){
$('#result5').append(msg);
}
});
}
$('#myButton5').click(function () {
var value = $('#example5').val();
executeAJAX5(value);
});
global
תכונה בולינאית שקובעת אם להשאיר את ה-ajax event listeners שנלמד עליהם בהמשך. באופן עקרוני מדובר בפונקציות שבודקות אם יש קריאה ל-AJAX. אם אנו קובעים ש-global הוא false אז הפונקציות לא יעבדו במקרה של בקשת ה-ajax שלנו.
ifModified
גם זו תכונה בוליאנית שקובעת הצלחה של ה-ajax רק וכאשר ה-Last-Modified השתנה (כלומר התגובה השתנתה מהבקשה האחרונה, אם התבצעה כזו).
user/password
במידה ויש צורך ב HTTP access authentication , אפשר להשתמש בתכונuות הזו ולהעביר באמצעותה את הסיסמה ואת שם המשתמש. באופן אישי עוד לא לא יצא לי להתקל באפליקצית רשת שיושבת על שרת production ומשתמשת ב- HTTP access authentication. אבל זה יכול להיות שימושי.
processData
תכונה שאם אני מעביר בה false, אז לא יתבצע עיבוד של המידע למחרוזת טקסט. שימושי אם אתה מקבל בחזרה אובייקט DOMDocuments.
scriptCharset
תכונה חשובה מאד אם אני מעלה מידע ממקור מרוחק, היא מאפשרת לי לקבוע את ה-charset של המידע המתקבל. שימושי מאד במיוחד כאשר יש הבדל בקידודים.
timeout
תכונה שאני יכול להעביר אליה כל מספר על מנת לבצע timeout.
complete
בדומה ל-success, אפשר להעביר כאן פונקציה שרצה בגמר ההצלחה, לאחר ה-success.
אלו כל התכונות של פונקצית ajax. מדובר בפונקציה החשובה ביותר, אם תלמדו אותה, יותר מחצי מהפונקציות כאן יהיו פשוט לא רלוונטיות עבורכן. אני מפרט על שאר הפונקציות בקצרה.
טעינת תוכן מרוחק
אני יכול לקבל מידע לא רק באמצעות ajax אלא באמצעות בקשה לטעון דף אחר ולעשות עם האובייקטים שלו דברים שונים. פונקצית load עושה זאת די בקלות. ראשית אנו בוחרים באמצעות סלקטור את האלמנט שיקבל את התוכן. אחרי כן אנו מכניסים את פונקצית load ובתוכה את ה-url היחסי של הדף ואם אנו רוצים את האלמנטים המבוקשים מתוכו. כך למשל אם אני רוצה את הקישורים שיש בדף הראשי (למשל) יוזרקו לתוך div שיש לו id=myDIV אז אני אשתמש בסינטקס הבא:
$('#myDiv').load(index.html a);
כל הקישורים שיש ב-index.html ייכנסו לדף הראשי! בלי דוגמא אי אפשר… פונקצית load הבאה מכניסה לתוך פסקת התוצאה שלי את כל הקישורים מהתפריט של הדף הראשי!
תוצאה:
שימו לב שאי אפשר לטעון דפים משרת אחר חוץ מזה שבו אנו נמצאים הודות למדיניות same domain policy של JavaScript.
וככה הקוד נראה:
$('#myButton6').click(function () {
$('#result6').load('index.php #sidebar a');
});
מה שיפה בפונקצית load שאני יכול להעביר אליה מידע בפרמטר get או post וכן גם פונקצית callback שתרוץ בגמר ה-load המוצלח. עושים את זה באמצעות הסינטקס הבא: load( url, [data], [callback] )
פונקציות נוספות
במקום להשתמש ב-$.ajax ניתן להשתמש בפונקציות בעלות רמה גבוהה יותר של אבסטרקציה. אני נוטה שלא להשתמש בהן אך הן בהחלט יותר פשוטות ללימוד ולהסבר. אני אעבור על כל אחת מהן בקצרה:
.get
שולח מידע לשרת באמצעות פרמטר get. הפונקציה הזו מקבלת את הפרמטרים הבאים: url שהוא הכתובת שאליה צריכים לשלוח את הבקשה, את המידע (כאובייקט או כמחרוזת טקסט) ופונקצית callback שרצה לאחר הבקשה. והנה הדוגמא המאד מתבקשת:
תוצאה:
הקוד נראה כך. זה בדיוק כמו פונקצית Ajax רק בסינטקס יותר פשוט ופחות אפשרות ל-options.
$('#myButton7').click(function () {
var value = $('#example7').val();
$.get("https://internet-israel.com/internet_files/ajax_example/ajax.php","myName="+value,function(msg){ $('#result7').append(msg)} );
});
.post
בדיוק כמו get, רק שהמידע נשלח במתודת post.
getJSON
בדיוק כמו get רק שהמידע שמתקבל הוא אובייקט JSON (זהה לחלוטין להעברת dataType: json
קביעת default options
באמצעות פונקצית $.ajaxSetup אפשר לקבוע תכונות דיפולטיביות עבור כל פקודות ה-AJAX. הפונקציה הזו מקבל אובייקט מאותו הסוג של הפונקציה ajax. באמצעותה אפשר לגרום גם לפונקציות היותר פשוטות כמו $.get או $.post לקבל תכונות יותר מתקדמות וכמובן ליצור אובייקט בסיסי של הגדרות משותפות לכל פונקציות ה-AJAX בדף.
סיריאליזציה של מידע
אם יש לי טופס, שאני מעוניין לקחת את כל המידע שיש בו, פונקצית serialize מסייעת מאד במקרה הזה. כל מה שאני צריך לעשות זה לבחור את הטופס עם סלקטור ואז לחבר אליו את פונקצית serialize. התוצאה תהיה מחרוזת טקסט שאותה אפשר לשלוח ב-AJAX או אפילו כמשלוח רגיל של טופס. זה יהיה יותר מובן עם דוגמא:
ה-serialize עובד אך ורק עם input שיש להם name. הקוד הוא פשוט ביותר:
$('#myButton8').click(function () {
var serial = $('#myForm').serialize();
alert(serial);
});
ניתן להשתמש גם בפונקצית serializeArray( ) שהיא זהה לחלוטין ל-serialize רק שהיא מחזירה אובייקט JSON ולא מחרוזת טקסט. אובייקט JSON נשמע מפחיד אבל זה אובייקט כמו כל אובייקט שהיתרון המשמעותי שלו הוא שאפשר להעביר איתו אובייקטים לשרת PHP שיודע גם מה לעשות איתם.
סיריאליזציה של אובייקטים
אם אני רוצה לשלוח אובייקט, אין דבר קל מזה עם param – פונקציה מעודכנת של jQuery שעושה סיריאליזציה של אובייקטים.
var myObject = {
a: {
one: 1,
two: 2,
three: 3
},
b: [1,2,3]
};
var recursiveEncoded = $.param(myObject);
$('#myButton9').click(function () {
alert(recursiveEncoded);
});
וזה מה שיוצא, כפתור שעושה alert למחרוזת טקסט שמייצג אובייקט. אם נשלח את האובייקט הזה ל-PHP, הוא ידע מה לעשות איתו.
אירועי AJAX
במקום להגדיר בפונקצית ajax שכבר למדנו איזו פונקציה להריץ במידה ויש success או error, אנו יכולים להשתמש בפונקציות כלליות יותר שנורות כאשר אירוע ה-AJAX המתאים מתבצע. פשוט דרך שונה לעשות את אותו הדבר. דרך השימוש באירועים היא מאד פשוטה – כותבים את הפונקציה המתאימה לאירוע ובתוכה מעבירים את פונקצית ה-callback: הפונקציה שצריכה לרוץ כאשר האירוע קורה. למשל, אירוע AJAX complete שיהיה בדף יגרום להודעה להכתב באלמנט #msg:
$.ajaxComplete(function(event,request, settings){
$("#msg").append("Request Complete. ");
});
זה כמעט זהה לחלוטין לשימוש בתכונה של ajax. להלן כל הפונקציות של האירועים:
ajaxComplete – מתרחש כאשר אירוע AJAX מושלם.
ajaxError – מתרחש כאשר אירוע AJAX נתקל בבעיה (כמו 404)
ajaxSend – מתרחש לפני שנשלח מידע ב-AJAX.
ajaxStart – מתרחש כאשר אירוע AJAX כלשהו מתחיל.
ajaxStop – מתרחש כאשר כל אירועי ה-AJAX מסתיימים.
ajaxSuccess – מתרחש לאחר קבלת קוד 200 מהשרת.
באופן עקרוני, אם משתמשים נכון בפונקצית ajax, כל האירועים שיש פה מיותרים וכן כל הפונקציות שעברתי עליהן לעיל. פונקצית ajax, על שלל התכונות שלה היא כל מה שצריך והיא גם פשוטה מאד לשימוש, במיוחד אם המערכות שלכם כתובות באופן מונחה עצמים ולא פרוצדורלי.
Cross Domain Policy – כפי שציינתי מוקדם יותר, כל קריאות ה-AJAX חייבות להיות בתוך הדומיין שלנו. קריאות AJAX אל דומיין אחר לא יעברו ולא יעבדו. על מנת לעקוף את המגבלות האלו יש צורך בהפעלת פרוקסי בצד השרת או בשימוש ב-JSONP.
AJAX הוא הנושא האחרון שאנו יכולים לעבור עליו במסגרת המדריך. מי שעבר על כל מאמר במדריך וגם תרגל לפי הדוגמאות אמור לדעת jQuery מספיק טוב על מנת להתחיל לעבוד איתה. בהצלחה!