[עמוד ראשי]   [נושא קודם]
טפסים


השימוש בטפסי HTML הוא בסיסי כמעט לכל תוכניות ה-web, בין אם הן מיושמות עם CGI, JS או קומבינציה של שניהם. במודל ה-CGI, טופס עם קלט המידע שהוא מכיל נטען לשרת ה-web כולו בפעם אחת. הדגש הוא בתהליך עבור קבוצה שלמה של קלט מידע ובאופן יצירת דף web דינמי חדש כתגובה. עם JS, מודל התכנות הוא שונה. בתוכניות JS, הדגש הוא לא בטעינת הטופס ובתהליך אלא ב- event handling.
הטופס וכל האלמנטים של הקלט שבתוכו בעלי event handlers ש-JS יכולה להשתמש בהם על מנת להגיב לפעולות המשתמש בתוך הטופס. אם המשתמש מקליק על checkbox, לדוגמא, תוכנית JS יכולה לקבל הודעה דרך event handler ויכולה להגיב ע"י שינוי הערך המוצג בתוך אלמנטים אחרים של הטופס.

בתוכניות CGI, טופס HTML אינו שימושי אלא אם כן הוא בעל כפתור Submit. ב- JS, כפתור Submit אינו הכרחי. ב- JS, טופס יכול להיות בעל מספר כלשהו של כפתורי לחיצה עם event handler שמבצעים מספר כלשהו של פעולות כאשר מקליקים.
פעולות אפשריות שכפתורים כאלו יכולים להפעיל: החלפת תמונה אחת באחרת, שימוש בתכונה location על מנת לטעון ולהציג דף web חדש, פתיחת חלון דפדפן חדש, יצירת מסמך HTML חדש באופן דינמי בחלון אחר או frame. ב- JS, event handler יכולה אפילו לגרום לטופס להיטען.
event handler הינו כמעט תמיד האלמנט המרכזי בכל תוכנית מעניינת של JS. ה- event handlers השימושיים ביותר הם אלו שמשתמשים בהם עם טפסים או עם אלמנטים של טופס.
1. אובייקט ה- Form
אובייקט Form של JS מציג טופס HTML. טפסים תמיד נמצאים כאלמנטים של המערך [ ]forms, שהוא תכונה של האובייקט Document. טפסים מופיעים במערך זה באותו סדר שהם מופיעים במסמך.
לכן, [0]document.forms מתייחס לטופס הראשון במסמך. ניתן להתייחס לטופס האחרון במסמך כך:
document.forms[document.forms.length-1]
התכונה המעניינת ביותר של אובייקט ה- Form הוא המערך [ ]elements, אשר מכיל אובייקטים של JS אשר מייצגים אלמנטים שונים של קלט הטופס. האלמנטים מופיעים במערך באותו הסדר שהם מופיעים במסמך, כך ש- [document.forms[1].elements[2 מתייחס לאלמנט השלישי של הטופס השני במסמך של החלון הנוכחי.
התכונות הנוספות של אובייקט ה-Form פחות חשובות והן: action, encoding, method, ן- target. הן מתאימות בדיוק לתכונות: ACTION, ENCODING, METHOD , TARGET של תווית ה- <FORM>. תכונות אלו משמשות לשליטה בטעינת המידע לשרת ה-web ולמקום שמוצגות התוצאות, לכן הן שימושיות רק כאשר הטופס נטען לתסריט ה- CGI.
תכונות אלו הן מחרוזות read/write, כך שתוכנית JS יכולה לקבוע את ערכיהן באופן דינמי במטרה לשנות את דרך טעינת הטופס.

אובייקט ה- Form תומך בשתי מתודות : ()submit, ו- ()reset, אשר משרתות את אותה מטרה. קריאה למתודה ()submit שווה בדיוק להקלקה של המשתמש על כפתור ה- submit, בעוד שקריאה ל- ()reset קובעת את האלמנטים של הטופס, בדיוק כמו שהמשתמש היה מקליק על כפתור ה- reset.
אובייקט ה-Form מספק את ה- onSubmit event handler על מנת לגלות טעינת טופס ואת onReset לגלות קביעה מחדש של הטופס (reset). ה- handler: onSubmit נקרא רק לפני סיום פעולת הטעינה. הוא יכול לבטל את הטעינה ע"י החזרת false. זה מספק הזדמנות לתוכנית JS לבדוק שגיאות בקלט המשתמש על מנת למנוע אי השלמת טעינה או נתון לא חוקי על פני הרשת לתוכנית CGI.
ה-onReset event handler דומה ל-onSubmit. הוא נקרא רק לפני סיום פעולת ה-reset, ויכול למנוע את הקביעה מחדש של האלמנטים של הטופס ע"י החזרת ערך false. זה מאפשר לתוכנית JS לבקש אישור של ה-reset, שיכול להיות רעיון טוב כשהטופס ארוך או מלא בפרטים.
ניתן לבקש זאת כך:
<FORM onReset="return confirm('Really erase ALL data and start over?')">
2. האלמנטים של האובייקט Form
תאור וארועים סוג התכונה תווית HTML אובייקט
כפתור לחיצה. onClick. "button" <INPUT TYPE = button> Button
כפתור מאורך ללא התנהגות של כפתורי radio. OnClick. "checkbox" <INPUT TYPE = checkbox> Checkbox
שדה קלט של הכנסת שם של הקובץ להטעין לשרת ה-web. OnChange. "file" <INPUT TYPE=file> FileUpload
נתונים הטעונים בטופס אך אינם ניראים למשתמש. אין event handler. "hidden" <INPUT TYPE = hidden> Hidden
פריט בודד של אובייקט ה-Select . ה-event handlaers הם על אובייקט ה-Select, ולא על אובייקטי Option אינדיבידואליים. אין <OPTION> Option
שדה קלט עבור סיסמת הכניסה-התווים אינם ניראים. OnChange. "password" <INPUT TYPE = password> Password
כפתור מאורך עם התנהגות של radio – רק אחד נבחר בכל פעם. OnClick. "radio" <INPUT TYPE = radio> Radio
כפתור נלחץ אשר טוען מחדש טופס. OnClick. "reset" <INPUT TYPE = reset> Reset
רשימה או תפריט "מושלך מטה" שבו פריט אחד יכול להבחר. OnChange. "select-one" <SELECT> Select
רשימה של טופס אשר מספר פריטים יכולים להבחר. OnChange. "select-multiple" <SELECT MULTIPLE> Select
כפתור נלחץ שטוען טופס. OnClick. "submit" <INPUT TYPE = submit> Submit
שדה כניסה של שורת טקסט בודדת.onChange "text" <INPUT TYPE = text> Text
שדה כניסה של טקסט מרובה שורות. onChange "textarea" <TEXTAREA> Textarea


הפרטים המדויקים של האלמנטים של האובייקט Form יכולים להימצא בדפי ההתייחסות המתאימים. ישנם מספר מאפיינים שכל האלמנטים של האובייקט Form חולקים. הם מגדירים event handlers הנקראים כשהמשתמש פועל עם האלמנטים. החשוב ביותר שבדר"כ נקרא הוא onClick או onChange, תלוי בסוג האובייקט. ה-event handlers העיקריים נתמכים ע"י כל אחד מהאלמנטים המוזכרים בעמודה הרביעית של הטבלה. בנוסף להם, כל האלמנטים של הטופס בעלי onblur : handlers ו-onfocus. כמו כן, חלק מהאלמנטים תומכים ב-handlers אחרים, כמו onkeypress ו-onmousedown.

לכל אלמנט יש תכונת type שמגדירה את סוג האלמנט. העמודה השלישית בטבלה מגדירה את הערך של תכונה זו לכל אובייקט. מערך ה- [ ]elements מכיל סוגים שונים של אלמנטים. תכונת ה- type מאפשרת לעשות לולאה דרך המערך [ ]elements ולפעול על האובייקטים מסוג Form שהוא מכיל בדרכים שתלויות בסוגם.

כמו כן כל אובייקט element בעל תכונת form. זהו למעשה reference לאובייקט Form שמכיל את האלמנטים. תכונה זו מספקת דרך שימושית לאובייקט element של הטופס להתייחס לאובייקט element אחר של הטופס בתוך ה- event handlers שלו. בתוך event handler של אלמנט הטופס, מילת המפתח this מתייחסת לאובייקט האלמנט בעצמו. כלומר, this.form תמיד מתייחס לאובייקט מאותה משפחה באותו הטופס ע"י ביטוי כזה:
this.form.elements[4]
3. נתינת שם ל-Forms והאלמנטים של Form
לכל אלמנט form יש תכונת NAME שחייבת להיקבע בתווית ה-HTML שלו אם הטופס יטען לתסריט CGI. לתווית ה- <FORM> בעצמה יש תכונת NAME שניתן לקבוע. אין לה שום קשר לטעינת הטופס. היא קיימת לנוחות תכנות ב-JS.
אם תכונת ה- NAME מוגדרת בתווית <FORM>, כאשר אובייקט ה- Form נוצר, היא מאוכסנת כאלמנט במערך [ ]forms של האובייקט Document, כרגיל, והיא גם מאוכסנת בתכונה האישית של אובייקט ה-Document. השם של הגדרת התכונה החדשה הזו הוא הערך של תכונת ה-NAME.
ניתן להגדיר טופס ע"י HTML כך:
<FORM NAME = "questionnaire">
	....
</FORM>
		
ואז ניתן להתייחס לטופס זה כך:
document. Questionnaire
וע"י ציון המערך:
document.forms[2]
יש לשים לב שתוויות HTML כמו: <IMG>, <APPLET>, <EMBED> ואחרות גם בעלות תכונת NAME שעובדת כמו תכונת ה-NAME של <FORM>, אך עם טפסים, סגנון זה של נתינת שם הוא צעד קדימה, מכיוון שכל האלמנטים המוכלים בטופס הינם בעלי תכונת NAME. כאשר נותנים לאלמנט טופס תכונת NAME, יוצרים תכונה חדשה של אובייקט ה- Form אשר מתיחסת לאלמנט הזה. השם של תכונה זו הוא הערך של התכונה, לכן ניתן להתיחס לאלמנט בעל שם "zipcode" בטופס בעל השם "address" כך:
document.address.zipcode
עבור שמות שנבחרו בצורה סבירה, סגנון זה יותר אלגנטי מהאחר, ומסתמך על המערך:
document.forms[1].elements[4]
תכנות CGI דורש שקבוצת Checkbox ואלמנטים של radio בטופס HTML יהיו בעלי שם זהה. לדוגמא, אם טופס מכיל מספר כפתורי Radio אשר מאפשרים למשתמש להצביע על שרתי ה- web המועדפים, כל אחד מכפתורים אלו יוכל לקבל את השם: "favorite".
ערך התכונה של אחד הכפתורים יוכל להיות : "nn", בעוד שה-VALUE של אחר יוכל להיות: "ie". כאשר הטופס נטען, מחרוזת כמו:
"favorite=opera" נשלחת לציין את בחירת המשתמש. שימוש באותו שם למספר אלמנטים הוא לא בעיה במקרה זה מכיוון שרק אחד מהאלמנטים יכול להבחר בנקודת זמן, כך שרק ערך אחד יכול להטען עם השם הזה.

כאשר יותר מאלמנט אחד בטופס בעל תכונת NAME, JS ממקמת את האלמנטים האלו בתוך מערך בעל שם מוגדר. כך שאם האובייקטים Radio בדוגמא הם חלק מהטופס "questionnaire" ניתן להתיחס אליהם ע"י הביטויים הבאים:
document.Questionnaire.favorite[0]
document.Questionnaire.favorite[1]
		
4. ערכי אלמנט ה-Form
בנוסף לתכונה name, כל אלמנט form בעל תכונה value. כאשר טופס נטען, נתוני קלט המשתמש מועברים לשרת ה-web בפורמט של זוגות שם-ערך. התכונות name ו-value מגדירות את השם שתחתיו יועבר כל נתון מידעי. התכונה value היא מחרוזת read/write עבור כל אובייקט של הטופס.
הערך ההתחלתי של התכונה בדר"כ מוגדר, באופן לוגי מספיק, ע"י התכונה VALUE של התווית HTML אשר מגדירה את אלמנט הטופס. עבור מספר אובייקטים, הערך ההתחלתי שלה מוגדר בדרכים אחרות.

אלמנטים אחרים של הטופס משתמשים בתכונה value בדרכים שונות, חלקן יותר אינטואיטיביות מאחרות. עבור האובייקטים Text ו- Textarea, התכונה value היא המחרוזת המוכלת בשדה הקלט. קביעת תכונה זו עבור אחד מאובייקטים אלו משנה את הטקסט ששדה הקלט הציג. עבור האובייקטים Button, Reset , Submit התכונה value היא הטקסט שמוצג ע"י הכפתורים הנלחצים. למרות שהתכונה היא read/write, שינויה אינו משנה את הטקסט המופיע בכפתור. כמו כן, ה- value של האובייקטים Button ו- Reset למעשה אף פעם לא נטען עם הטופס המכיל את האובייקט.

התכונה value עבור האובייקטים Checkbox ו- Radio היא גם מעט טריקית. מאחר ואובייקטים אלו מציגים כפתורים מוארכים בטופס HTML, ניתן לצפות שהתכונה value תציין ע"י ערך בוליאני את מצבו אם הכפתור נבדק או לא. זה מתבצע למעשה, ע"י התכונה checked של אוביקטים אלו. התכונה value, כמו תמיד, היא ערך המחרוזת שנטענה עם הטופס, אם האובייקטים Checkbox ו- Radio נבדקו כאשר הטופס נטען.

אובייקט ה- Select הוא גם כן מקרה יוצא דופן. הוא מציג רשימה או תפריט drop-down של אפשרויות ומאפשר למשתמש לבחור אחד או יותר מהן. אפשרויות אלו מוגדרות ע"י תוויות <OPTION> מופרדות. כתוצאה, אובייקט ה- Select אינו בעל תכונת value. זוהי חריגה מהחוק שלכל אובייקט אלמנט של טופס יש תכונה ע"י שם זה.

האובייקטים Select ו- Option

אובייקטים אלו שונים במספר דרכים מאובייקטי אלמנט של טופס אחרים. ראשית, אובייקט ה- Option הוא לא לבדו אלמנט של טופס- זהו אוביקט המוכל ע"י האובייקט Select. האובייקט Select הוא היחיד המכיל אובייקט אחר. הם מוכלים במערך [ ]options, כך שניתן להתייחס לאובייקטים Option ע"י ביטוי ארוך, כמו:
document.forms[0].elements[1].options[2]
שנית, האובייקטים מסוג Option יכולים להיווצר באופן דינמי בזמן ריצה. האובייקטים מסוג Option נוצרים ע"י פונקצית הבנאי ()Option ויכולים להתווסף למערך [ ]options של אוביקט Select ע"י הצבה פשוטה.
לתכונת ה- [ ]options יש מספר התנהגויות מיוחדות, אם מפחיתים את הערך של option.length, אפשרויות נמחקות מסוף הרשימה או מהתפריט שהוצג ע"י אובייקט ה- Select. באופן דומה, אם קובעים את אחת מהכניסות של המערך [ ]options ל- null, אפשרות זו נמחקת מהרשימה והאלמנטים שאחריה במערך מוזזים על מנת למלא את המקום שהתפנה.
דוגמא
הדוגמא הבאה מציגה טופס HTML המכיל את כל האלמנטים של טופס.
<FORM NAME = "everything">      <!-- A one-of-everything HTML form… -->
<TABLE BORDER CELLPADDING = 5>  <!-- … In a big HTML table. -->
  <TR>
    <TD>Username:<BR>
      [1]<INPUT TYPE = text  NAME = "username" SIZE = 15> 
    </TD>
    <TD>Password:<BR>
      [2]<INPUT  TYPE = password  NAME = "password" SIZE = 15>
    </TD>
    <TD ROWSPAN = 4> Input Event[3]<BR>
      <TEXTAREA  NAME = "textarea"  ROWS = 20  COLS=28></TEXTAREA>
    </TD>
    <TD ROWSPAN = 4  ALIGN = center  VALIGN = center>
      [9]<INPUT  TYPE = button  VALUE = "Clear"  NAME = "clearbutton"<BR>
      [10]<INPUT  TYPE = submit  NAME = "submitbutton"  VALUE = "Submit"><BR>
      [11]<INPUT  TYPE = reset  NAME = "resetbutton"  VALUE = "Reset">
    </TD>
  </TR>
  <TR>
    <TD COLSPAN = 2>Filename: 
      [4]<INPUT TYPE = file  NAME = "file"  SIZE =15>
    </TD>
  </TR>
  <TR>
    <TD>My Coputer Peripheral:<BR>
      [5]<INPUT  TYPE = checkbox  NAME = "peripherals"  VALUE = "modem">28.8K Modem<BR>
      [5]<INPUT  TYPE = checkbox  NAME = "peripherals"  VALUE = "printer">Printer<BR>
      [5]<INPUT  TYPE = checkbox  NAME = "peripherals"  VALUE = "tape">Tape  Backup
    </TD>
    <TD>My Web Browser:<BR>
      [6]<INPUT TYPE = radio  NAME = "browser"  VALUE = "nn">Netscape  Navigator<BR>
      [6]<INPUT TYPE = radio  NAME = "browser"  VALUE = "ie">Internet Explorer<BR>
      [6]<INPUT TYPE = radio  NAME = "browser"  VALUE = "other">Other<BR>
    </TD>
  </TR>
  <TR>
    <TD>My Hobbies:[7]<BR>
      <SELECT  multiple  NAME = "hobbies"  SIZE = 4>
        <OPTION VALUE = "programming">Hacking JavaScript
        <OPTION VALUE = "surfing">Surfing the Web
        <OPTION VALUE = "caffeine">Drinking Coffee
        <OPTION VALUE = "annoying">Annoying my Friends
      </SELECT>
    </TD>
    <TD align = center valign = Center>My Favorite Color:<BR>[8]
      <SELECT  NAME = "color">
        <OPTION VALUE = "red">Red
        <OPTION VALUE = "blue">Blue
        <OPTION VALUE = "violet">Violet
        <OPTION VALUE = "green">Green
        <OPTION VALUE = "white">White
        <OPTION VALUE = "peach">Peach
      </SELECT>
    </TD>
  </TR>
</TABLE>
</FORM>

<DIV ALIGN = center>    <! - - Another table—the key to the one above. - - >
<TABLE BORDER = 4  BGCOLOR = pink  CELLSPACING = 1 CELLPADDING = 4>           
  <TR>
    <TD ALIGN = center><B>Form Elements</B></TD>
    <TD>[1] Text</TD>  <TD>[2] Password</TD>  
    <TD>[3] Textarea</TD>
    <TD>[4]FileUpload</TD>
    <TD>[5]Checkbox</TD>
  </TR>
  <TR>
    <TD>[6] Radio</TD> 
    <TD>[7]Select (list)</TD>
    <TD>[8] Select (menu) </TD>
    <TD>[9] Button</TD>
    <TD>[10] Submit</TD> 
    <TD>[11] Reset</TD>
  </TR>
</TABLE>
</DIV>

<SCRIPT LANGUAGE = "JavaScript1.1">

// This generic function appends details of an event to the big Textarea
// element in the form above. It will be called from various event handlers.
function report(element,event)
{
  var t = element.form.textarea;
  var elmtname = element.name;
  if((element.type = = "select-one") || (element.type = = "select-multiple"))
  {
    value = " ";
    for(var i = 0; i<element.options.length; i++)
    if(element.options[i].selected)
    value += element.options[i].value + " ";
  }
  else if(element.type = = "textarea")  
      value = "…";
     else  value = element.value;
  var msg = event + ": " + elmtname + ' (' + value + ')\n';
  t.value = t.value + msg; 
}

// This function adds a bunch of event handlers to every element in a form.
// It dosen't bother checking to see if the element supports the event handlers, 
// It just adds them all. Note that the event handlers call report() above.
function addhandlers(f)
{
  var click_handler = new Function("report(this, 'Click')");
  var change_handler = new Function("report(this, 'Change)");
  var focus_handler = new Function("report(this, 'Focus)");
  var blur_handler = new Function("report(this, 'Blur)");
  var select_handler = new Function("report(this, 'Select)");
  for(var i = 0; i<f.elements.length; i++)
  {
    var e = f.elements[i];
    e.onclick = click_handler;
    e.onchange = change_handler;
    e.onfocus = focus_handler;
    e.onblue = blur_handler;
    e.onselect = select_handler;
  }
  
  // special case handlers for the buttons:
  f.clearbutton.onclick = 
  new Function("this.form.textarea.value = ' '; report(this,'Click');");
  f.submitbutton.onclick = 
  new Function (report(this,'Click'); return false");
  f.resetbutton.onclick = 
  new Function("this.form.reset(); report(this,'Click'); return false");
}

// Activate our form by adding all possible event handlers!
Addhandlers(document.everything);
</SCRIPT>
דוגמא

דוגמא המסכמת את הנושאים והרעיונות שדנו בהם במהלך הפרק : בדוגמא נראה שימוש באירוע onSubmit הגורם לביצוע בדיקת תקינות /ולידציה של הקלט, כאשר נוכל להודיע למשתמש באם נעשה נסיון של העברת המידע (לחיצה על כפתור submit) כאשר חלק מהנתונים אינם או אינם נכונים.
<SCRIPT id=verifyForm>    
  
  //this function returns true if the string contains only spaces
  function isblank(s)
  { for(var i=0; i < s.length ; i ++)  
    {    
      var c = s.charAt(i);      
      if((c != ' ') && (c != '\n') && (c != '\t'))      
        return false; 
    }     
        return true;
  } 
   
   function verify(f)
   { 
    var msg; 
    var empty_fields = "";  
    var errors = "";
    if( isblank(f.firstname.value) )  
      {empty_fields+="  First name is not filled \n"};
    if( isblank(f.lastname.value) )  
      {empty_fields+="  Last name is not filled \n"};
    if( isblank(f.address.value) )  
      {empty_fields+="  Address is not filled \n"};
    if( isblank(f.zip.value) )  
      {empty_fields+="  Zip code is not filled \n"};
    else  {if ( isNaN(f.zip.value) ){errors+=" Zip code must be a number \n"};};
    if( isblank(f.phonenumber.value) )  
      {empty_fields+="  Phone number is not filled \n"};
    else  { if ( isNaN(f.phonenumber.value) )  {errors+=" Phone number must be a number \n"} };
    if(empty_fields=="" && errors=="") return true
    else msg = "The form was not submmited because of the following error(s):\n";
    msg += empty_fields + errors ;
    alert(msg );
    return false
  }
</SCRIPT>

<FORM onSubmit="return verify(this)">
  First Name: <INPUT Type=text Name="firstname"><br>
  Last Name: <INPUT Type=text Name="lastname"><br>
  Address: <br>
  <TEXTAREA Name="address" Rows=3 Cols=30></TEXTAREA><br>
  Zip Code: <INPUT Type=text Name="zip"><br>
  Phone Number: <INPUT Type=text Name="phonenumber"><br>
  <INPUT type=submit>
</FORM>    
First Name:
Last Name:
Address:

Zip Code:
Phone Number: