הכלים של jQuery

אוסף הכלים של jQuery הוא פונקציות שימושיות במיוחד לאובייקטים של jQuery ומערכים.

במאמרים הקודמים דנו בלא מעט דברים – התחלנו בסינטקס הבסיסי של jQuery, המשכנו דרך סלקטורים של jQuery ואירועים של jQuery וכמובן פירטנו על כל הפונקציות המרתקות של jQuery – אפקטים, אנימציות, שינויי css ושינויי תכונות (attributes). שני המאמרים האחרונים עסקו בפונקציות traversing שהן פונקציות שמאפשרות לנו לעדן את הבחירה הראשונית עם הסלקטורים.

בשלב זה, שהוא יותר מתקדם, אין מנוס מלעבור לשימוש במונחים של אובייקטים ומערכים. לא צריך להבהל, בסך הכל השתמשנו עד עכשיו באובייקטים רק שלא קראנו להם כך. במאמר הזה רוב הפונקציות הן פונקציות עזר שנועדו לטפל במערכים ובמערכים של אובייקטים ולפיכך צריך להכיר את המונחים האלו.

כאשר אנו משתמשים בסלקטור שהוא לא id, כמו לדוגמא סלקטור של אלמנט:


$('p')

אנו מקבלים בחזרה אובייקט כלשהו. הרי $ זו בסך הכל פונקציה, לא וודו שחור כלשהו. האובייקט המוחזר כולל את כל הפסקאות בדף האינטרנט. כשלכל פסקה יש את התוכן שלה, האירועים שלה והתכונות שלה. בעצם, התוצאה המתקבלת היא מערך אובייקטים. וכאן אנו נכנסים לעולם המופלא של jQuery ואובייקטים.

רוב מפתחי הרשת מכירים את JavaScript כשפה פרוצדורלית. אך ניתן לעבוד עם JavaScript גם כשפת תוכנה מונחית עצמים (OOP). נכון, לעומת שפות OOP טהורות יותר כמו AS3 או אפילו PHP, שפת JavaScript נראית די אומללה בלי encapsulation ותכונות נוספות. אבל jQuery מתייחס אל JavaScript כשפה מונחית עצמים וכך גם הוא כתוב. מעכשיו, כשאני כותב על אובייקט תחשבו שאני מתייחס לאלמנט שהוא בסך הכל אובייקט עם תכונות ומתודות. כשאני מדבר על מערך אובייקטים תחשבו שאני מתייחס לסלקטור שבוחר יותר מאלמנט אחד, כמו $('p').

איטרציה בין אובייקטים

כאשר אני בוחר יותר מאובייקט אחד, נוצר צורך לעבור בין האובייקטים השונים. כלומר לעשות לולאה. jQuery מאפשרת לנו עם פונקצית each לעשות את זה די בקלות. בדוגמא אני אעבור בין כל האובייקטים שבחרתי עם הסלקטורים ואכתוב את ה-innerHTML שלהם כמשתנה ואדפיס אותו לשורת התוצאה:

  • פריט ראשון
  • פריט שני
  • פריט שלישי
  • פריט רביעי
  • פריט חמישי

שורת התוצאה:

וכך זה נראה:


$('#myButton1').click(function () {
var oExample = $('#example1 li'); //כאן לשם הפשטות אני מגדיר את האובייקט שלי
jQuery.each(oExample, function(){ //פונקצית האיטרציה, היא מקבל דוגמא ופונקצית קולבק
$('#resultParagraph').append($(this).text()); //הפונקציה עצמה שמקבלת את הטקסט וכותבת אותו לפסקת התוצאה. הפונקציה הזו רצה 5 פעמים כמספר האובייקטים במערך
});

בואו ונעבור על הסינטקס. באופן עקרוני אנחנו נדרשים להעביר דרך each שני דברים. ראשית את מערך האלמנטים שלנו (או את האלמנט) ושנית את ה-callback אותה פונקציה שרצה על כל אלמנט. אותה פונקצית callback היא חשובה כי אפשר להעביר דרכה 2 פרמטרים: הראשון הוא מקומו במערך האובייקטים (i) והשני הוא האובייקט עצמו. וכך אנחנו לא חייבים להשתמש בפקודת this. שימו לב לדוגמא הבאה שבה אני מדפיס את המקום במערך בנוסף לטקסט:

  • פריט ראשון
  • פריט שני
  • פריט שלישי
  • פריט רביעי
  • פריט חמישי

שורת התוצאה:

ככה הקוד נראה, התוספת היחידה היא i ו-object. שימו לב שעל מנת להשתמש בפונקצית text או כל פונקצית jQuery אחרת אני נאלץ להשתמש בפונקצית $ ש"ממירה" את האובייקט חזרה לאובייקט jQuery.


$('#myButton2').click(function () {
var oExample2 = $('#example2 li'); //הגדרת אובייקט
jQuery.each(oExample2, function(i,object){ //פונקצית האיטרציה כמו הדוגמא הקודמת. שימו לב שפונקצית הקולבק מעבירה שני פרמטרים, מיקום במערך ואת האובייקט
$('#resultParagraph2').append( //כאן אני מוסיף את הטקסט
i+". "+$(object).text()); //מחרוזת שמורכבת ממספר סידורי  ומתכונת הטקסט של האובייקט
});
});

הורשה

זוהי פונקציה המתאימה לאובייקטים בלבד והיא בעצם extend המוכרת משפות אחרות. בואו ונניח שיש לנו שני אובייקטים:


var oSettings = { validate: false, limit: 5, name: "foo" };
var oOptions = { validate: true, name: "bar" };

אם אני רוצה ש-oSettings יירש את oOptions, אין דבר פשוט מזה ב-jQuery. הקוד הבא מבצע את ההורשה ומדפיס את אובייקט oSettings החדש:

שורת התוצאה:

וככה זה נראה, די פשוט וחוסך זמן.


$('#myButton3').click(function () {
var oSettings = { validate: false, limit: 5, name: "foo" };
var oOptions = { validate: true, name: "bar" };
jQuery.extend(oSettings, oOptions);

jQuery.each(oSettings, function(property,value){ 
$('#resultParagraph3').append( 
"
"+property+" : "+value); }); });

סינון מערכים

jQuery מציעה פונקצית grep נהדרת לסינון מערכים שהיא די דומה לפונקצית filter שלמדנו במאמרים הקודמים. נניח שיש לי מערך מסוים (לא אובייקט) ואני רוצה להסיר ממנו איברים מסוים. אני יכול לעשות זאת עם לולאה רגילה או פשוט עם פונקצית grep שלתוכה אני מעביר את המערך שאני רוצה לפלטר ואת הפילטר. הפונקציה מחזירה לי מערך מסונן.

לשם הדוגמא, בואו ונניח מערך בן 10 מספרים מ-1 עד 10 ואני רוצה להוריד ממנו את איברים 1-3 ו-10. לחצו על הכפתור כדי לראות את התוצאה:

לעשות את זה זה פשוט מאד, ממש כמו פונקצית פילטר שדנו עליה בפרוטרוט במאמר על Traversing


arr = [1,2,3,4,5,6,7,8,9,10];
$('#myButton4').click(function () {
arr = jQuery.grep(arr, function(i){
return (i>3 && i<9);
});
alert(arr);
});

המרת מערכים

מדובר בעצם בפונקציה שהיא דומה מאד ל-each רק שהיא למערכים ולא לאובייקטים (בעצם: לולאה עם סינטקס טיפה יותר פשוט). היא עוברת דרך כל מערך שניתן לה ותוכל להמיר אותו או לבצע כל פעולה שהיא. שם הפונקציה הוא map ואפשר להשתמש בה גם על אובייקטים של jQuery.

בואו ונניח שיש לנו את המערך הקודם מ1-10 ואני רוצה להוסיף לו את התחילית A.

ככה הקוד נראה, פשוט ביותר והרבה יותר אלגנטי. שוב, שימו לב שאפשר להעביר בפונקצית map גם אובייקטים של jQuery מה שנותן גמישות עצומה בשינוי מערך של אובייקטי DOM אם ממש רוצים.


arr = [1,2,3,4,5,6,7,8,9,10];
$('#myButton5').click(function () {
arr = jQuery.map(arr, function(i, member){
return ("A" + member);
});
alert(arr);
});

פונקצית חיפוש במערך

פונקצית inArray האולטרא שימושית מחפשת מחרוזת טקסט מסוימת במערך. הסינטקס שלה כל כך פשוט שזה מצחיק, היא מקבל את המערך ואת המחרוזת שאנו רוצים למצוא. דוגמא תבהיר את העניין בקלות. נניח שיש לי מערך של שמות:


arrOfNames = ["david", "moshe", "ran", "omri", "yael"];

ואני רוצה לדעת מה המיקום של 'omri' על מנת לדעת את זה אני פשוט אריץ את inArray ואכניס לתוכה את המחרוזת שאני רוצה (במקרה הזה 'omri') ואת המערך. הנה, נסו את הדוגמא הבאה:

וכך זה נראה:


arrOfNames = ["david", "moshe", "ran", "omri", "yael"];
$('#myButton6').click(function () {
result = jQuery.inArray("omri", arrOfNames);
alert("Omri is at "+result);
});

מיזוג מערכים

jQuery מאפשרת לנו למזג שני מערכים בקלות יחסית באמצעות פונקצית jQuery.merge שמקבלת שני פרמטרים – את המערך הראשון ואת המערך השני. היא מחזירה לנו מערך שלישי וממוזג. למעט דוגמא אין מה לומר על הפונקציה החביבה הזו. לצורך הדוגמא יש לי שני מערכים:


arrOfNames = ["david", "moshe", "ran", "omri", "yael"];
arrOfNumbers = [1,2,3,4,5,6,7,8,9,10];

לחיצה על הכפתור תפעיל את פונקצית המיזוג:

וכך זה נראה:


arrOfNames = ["david", "moshe", "ran", "omri", "yael"];
arrOfNumbers = [1,2,3,4,5,6,7,8,9,10];

$('#myButton7').click(function () {
result = jQuery.merge(arrOfNumbers, arrOfNames);
alert(result);
});

אובייקט למערך

ב-jQuery יש לנו אפשרות להמיר אובייקט של jQuery למערך של אלמנטים של HTML. הפונקציה שעושה את זה נקראת toArray. לשם הדגמה אני אצור רשימה של ארבע פרטים.

  • פריט ראשון
  • פריט שני
  • פריט שלישי
  • פריט רביעי

על מנת לקבל אובייקט של jQuery שמכיל את כל ה-li שברשימה, עלי לבחור את ה-li של הרשימה עם ה-id שנתתי לה באמצעות jQuery.


var Olist = $('#example12 li');
var alist = Olist.toArray();
var itemNumberOne = alist[0];


אם אני אפעיל את פונקצית toArray על כל ה-li, יווצר לי מהאובייקט הזה מערך של כל האלמנטים li. את האיבר הראשון מערך הזה אני אוכל להציג כתוצאת alert.

והנה הקוד המלא:


var Olist = $('#example12 li');
var alist = Olist.toArray();
var itemNumberOne = alist[0];
$('#myButton12').click(function () {
alert(itemNumberOne.innerHTML);
});

סילוק אובייקטים כפולים

אם יש לנו מערך של אובייקטים של jQuery (לא מספרים או מחרוזות אלא ממש מערך DOM Objects) ויש ביניהם כמה כפולים אנו יכולים לסלק אותם עם פונקצית jQuery.unique שמקבלת את המערך. כיוון שזו פונקציה מאד פשוטה מחד גיסא ומאידך גיסא בקושי יוצא להשתמש בה, אני לא הולך לתת לה כאן דוגמא.

בדיקת מערך

פונקציה שמחזירה true אם מה שאנחנו מכניסים אליה הוא מערך. ולראיה:

והנה הקוד, אין צורך להכביר מילים כאן:


arrOfNames = ["david", "moshe", "ran", "omri", "yael"];

$('#myButton8').click(function () {
result = jQuery.isArray(arrOfNames);
alert(result);
});

בדיקת פונקציה

פונקצית isFunction דומה במאה אחוז לפונקציה הקודמת של בדיקת מערך רק שהיא בודקת אם מדובר בפונקציה. אין יותר מדי מה לומר על הפונקציה הזו שגם היא מחזירה true או false.

בדיקת אובייקטים

ל-jQuery יש שתי פונקציות לבדיקת אובייקטים. פונקצית isEmptyObject מחזירה true אם מדובר באובייקט שאין לו תכונות או מתודות כלל. (אובייקט ריק לחלוטין). פונקצית isPlainObject מחזירה true אם מדובר באובייקט JavaScript ליטרלי או אובייקט לא ליטרלי (כזה שיוצרים אותו עם new).

פונקציה ריקה

לעתים יש צורך בכתיבת פונקציה שלא עושה שום דבר:


function({});

פונקצית noop(); עושה את אותו הדבר, אבל יש חסכון (קטן) בזכרון.

פונקצית גיזום

לפעמים יש לנו מחרוזת שיש רווחים לפניה או אחריה. בשביל זה יש לנו את פונקצית jQuery.trim שלתוכה אנו מעבירים את המחרוזת שאנו רוצים לגזום והיא גוזמת את הרווח הריק לפני ואחרי המחרוזת. שימו לב לדוגמא הבאה. המחרוזת המקורית היא " אינטרנט":


string ="      אינטרנט";
$('#myButton9').click(function () {
result = jQuery.trim(string);
alert(result);
});

פונקצית פרוקסי

מדובר באחת הפונקציות השימושיות ביותר שיש ב-jQuery. זוהי פונקציה המאפשרת לשנות את הקונטקסט בתוך פונקציה אחרת ולקבוע אותה לפי הצרכים שלנו. שווה מאד לקרוא היטב את ההסבר ואת הדוגמא על מנת להבין את התפקיד של הפונקציה האולטרא שימושית הזו.

כפי שכל מתכנת JavaScript יודע, תפקיד מילת המפתח this משתנה בהתאם לקונטקסט. אם למשל יש לי אובייקט מסוים:


var app = {
    config: {
        clickMessage: 'Hi!'
    },
    clickHandler: function() {
        alert(this.config.clickMessage);
    }
};

באובייקט זה יש לי מתודה שקל להפעיל אותה ולגרום להודעת alert. אך מה יקרה אם אני ארצה לקשור את המתודה שיש באובייקט החביב שלי לכפתור מסוים?


jQuery('#myButton13').bind('click', app.clickHandler);

המתודה app.clickHandler לא תעבוד. ומדוע? כיוון שה-this שמופיע בה הוא לא this של אובייקט app. הוא ה-this של ה-event! JavaScript כמו כל שפה, משנה את ה-this בהתאם לקונטקסט והקונטקסט פה הוא של אירוע, לא של אובייקט. כך לא רק באובייקט אלא בכל פונקציה שיש בה this. עד עכשיו היינו עושים כל מיני מעקפים כדי להעביר את ההקשר של ה-this. לא עוד. באמצעות שימוש ב-proxy אני יכול להעביר את הקונטקסט אל מתודת האובייקט/פונקציה שלי.

אני נדרש להעביר דרך פונקצית proxy שני פרמטרים. הראשון הוא האובייקט/קונטקסט שאני רוצה להעביר והשני הוא שם המתודה של האובייקט.


jQuery('#myButton13').bind(
    'click',
    jQuery.proxy(app, 'clickHandler')
);

בדיקת דפדפן

בעבר לצורך בדיקת הדפדפן היו 3 פונקציות שונות שבדקו דברים שונים בדפדפן עצמו. החל מגרסה 1.3 של jQuery יש פונקציה אחת שבודקת את הדפדפן ומחזירה לנו מידע חשוב עליו. פונקציה זו היא jQuery.support והיא מחזירה לנו true או false בהתאם לפרמטרים שאנחנו מכניסים לתוכה. ישנם כמה פרמטרים מותרים שאפשר להכניס:

  • boxModel – בדיקה אם הדפדפן מציית ל-boxmodel המקובל של wc3 (ב-IE6 וב-IE7 היא מחזירה false כמובן).
  • cssFloat – בדיקה אם הדפדפן משתמש בstyle.cssFloat על מנת לגשת לערך float.
  • hrefNormalized – בודק אם אובייקט ה-href עובר נורמליזציה (false ב-אינטרנט אקספלורר)
  • htmlSerialize – בודק אם הדפדפן עושה סיריאליזציה לקישורים כאשר אנו משתמשים ב-innerHTML.
  • leadingWhitespace בדיקה אם הדפדפן משמר רווחים בתחילת אובייקטים של HTML (true באינטרנט אקספלורר)
  • noCloneEven – בודק אם הדפדפן משמר את האירועים שהוצמדו לאלמנטים ששוכפלו (cloned) הבדיקה שלילית אם מדובר באינטרנט אקספלורר
  • objectAll – בודק אם getElementsByTagName("*") מחזיר תוצאות (flase באינטרנט אקספלורר).
  • opacity – בדיקה אם יש תמיכה ב-opacity (באינטרנט אקספלורר אין תמיכה כזו).
  • style – בודק אם יש גישה getAttribute("style") – שלילי באינטרנט אקספלורר.
  • tbody – בדיקה אם הדפדפן מרשה לטבלאות להיות בלי tbody. שלילי באינטרנט אקספלורר.

בסופו של דבר, כל הפרמטרים בודקים דבר אחד – האם הדפדפן הוא אינטרנט אקספלורר או לא.

והנה הדוגמא:

וכך זה נראה:


$("#resultParagraph4").html("This frame uses the W3C box model: " +
                jQuery.support.boxModel + "");
});

עד כאן הכלים של jQuery. במאמר הבא אנו דנים בפונקציות הליבה של jQuery שעוסקות במידע ובמתן מידע על אובייקטים של jQuery.

פוסטים נוספים שכדאי לקרוא

פתרונות ומאמרים על פיתוח אינטרנט

יישום של nonce על מנת להגן מפני התקפות injection

בפוסט הקודם הסברתי על hash עם CSP על משאבי inline – שזה נחמד ומעולה אבל פחות ישים בעולם האמיתי שבו בדרך כלל התוכן ה-inline (בין

גלילה לראש העמוד