טפסים
השימוש בטפסי 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>
|
|