תגית contenteditable – ישומים פרקטיים

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

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

את תגית ה contenteditable פשוט מוסיפים לאלמנט ביחד עם הערך true. כך למשל קוד ה html הבא:

<p contenteditable="true">הנה תראו, לחצו על הטקסט הזה ושנו אותו</p>

יניב את התוצאה הזו:

הנה תראו, לחצו על הטקסט הזה ושנו אותו

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

<ul class="testzone" contenteditable="true">
	<li>אלמנט ראשון</li>
	<li>השתמשו באנטר כדי להוסיף אלמנטים</li>
</ul>
  • אלמנט ראשון
  • השתמשו באנטר כדי להוסיף אלמנטים

התגית contenteditable היא תגית מורישה, זה אומר שאם נרצה להכיל מצב עריכה על מאמר מלא במקום להוסיף לכל אלמנט p (פיסקה) את התגית הרלוונטית, אפשר יהיה להוסיף את התגית הזו פעם אחת באלמנט העוטף את כל המאמר ובכך לאפשר עריכה של הטקסט בתוכו.

<div class="testzone" contenteditable="true">
	<p>הנה איזור המשחקים אפשר להוסיף פה פסקאות ללא גבול בעזרת אנטר</p>		
</div>

הנה איזור המשחקים אפשר להוסיף פה פסקאות ללא גבול בעזרת אנטר

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

ישומים פרקטיים

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

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

לצורך שמירת הנתונים, אני אשתמש בזיכרון של הדפדפן בעזרת מנגנון ה localStorage, המנגנון הזה נתמך באקספלורר 8 ומעלה, בפיירפוקס 3.5 ומעלה ובכרום / ספארי מגירסה 4 ומעלה. לגירסאות קודמות יותר, יש כלים שונים ומי שמעוניין לשבור את הראש על תאימות אחורה ברכותי.

לצורך הדוגמא ניצור מסמך html חדש שמכיל אך ורק אובייקט ol (רשימה ממוספרת) ונכניס לתוכו שני אלמנטים התחלתיים.

<ol id="tasks" contenteditable="true" onblur="savedata()">
	<li>משימה ראשונה</li>
	<li>משימה שניה</li>
</ol>

כפי שניתן לראות, שייכתי פונקציה בשם savedata לאירוע blur – שזה אירוע שבו הפוקוס עוזב את האלמנט – למשל, ברגע שהקלקנו עם העכבר אל מחוץ לאיזור העריכה או לחצנו על כפתור ה tab.

var tasks = document.getElementById('tasks');
function savedata() {		
  localStorage.setItem('mytasks', tasks.innerHTML);	 
}; 
if (localStorage.getItem('mytasks')) {
 tasks.innerHTML = localStorage.getItem('mytasks');
}

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

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

אפשר לשחק עם דוגמה פעילה כאן, וכמובן הנה הקוד המלא:

<!DOCTYPE>
<html>
<head>
	<title>Tasks</title>	
</head>
<body>
	<ol id="tasks" contenteditable="true" onblur="savedata()">
		<li>משימה ראשונה</li>
		<li>משימה שניה</li>
	</ol>
	<script>	
		var tasks = document.getElementById('tasks');
		function savedata() {		
		  localStorage.setItem('mytasks', tasks.innerHTML);	 
		}; 
		if (localStorage.getItem('mytasks')) {
		 tasks.innerHTML = localStorage.getItem('mytasks');
		}
	</script>	
</body>
</html>

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

אבל מה קורה אם אנחנו כן רוצים לשמור את המידע הזה על שרת מרוחק? במקרה שכזה, נזדקק גם ל ajax על מנת לעדכן את המידע על השרת. את התוכן של savedata מהדוגמא הקודמת נחליף בשליחת מידע באמצעות post אל קובץ php שיושב על השרת שלנו. קובץ ה php יחזיק את הפונקציונאליות הרצויה (שמירה למסד נתונים, שמירה לקובץ טקסט, החלפת מילים או כל דבר אחר שתרצו). בנוסף, קובץ האפליקציה כבר לא יוכל להיות עמוד html פשוט כפי שהיה בדוגמא הקודמת ונזדקק לקובץ php שידע למשוך את המידע שאוכסן על השרת.

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

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

כתיבת תגובה

האימייל לא יוצג באתר. שדות החובה מסומנים *