שלב 5: הוספת תמונות מהאינטרנט

בשלב הזה תלמדו:

  • איך לטעון משאבים מחוץ לאפליקציה ולהוסיף אותם ל-DOM דרך XHR ו-ObjectURLs.

זמן משוער להשלמת השלב הזה: 20 דקות.
כדי לראות תצוגה מקדימה של מה שתשלימו בשלב הזה, דלגו לתחתית הדף הזה ↓.

איך CSP משפיע על השימוש במשאבים חיצוניים

פלטפורמת אפליקציות Chrome מאלצת את האפליקציה לפעול בתאימות מלאה למדיניות אבטחת התוכן (CSP). לא ניתן לטעון משאבי DOM ישירות כמו תמונות, גופנים ו-CSS מחוץ לאפליקציית Chrome חבילה.

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

הצגת תמונות ממוזערות של משימות לביצוע

בואו נשנה את האפליקציה כדי לחפש כתובות URL של תמונות בפריט לביצוע. אם כתובת האתר נראית כמו תמונה (במקרה מסתיים ב- .png , .jpg , .svg או .gif), החל את התהליך שצוין למעלה כדי להציג תמונה ממוזערת לצד כתובת האתר.

עדכון ההרשאות

באפליקציית Chrome, ניתן לבצע קריאות XMLHttpRequest לכל כתובת URL כל עוד מציינים את הדומיין שלה את המניפסט. מכיוון שלא תוכלו לדעת מראש איזו כתובת URL של תמונה המשתמש יקליד, עליכם לבקש הרשאה לשלוח בקשות אל "<all_urls>".

ב-manifest.json, מבקשים את "" הרשאה:

"permissions": ["storage", "alarms", "notifications",
                "webview", "<all_urls>"],

יצירה וניקוי של כתובות URL של ObjectURL

ב-controller.js, מוסיפים שיטה _createObjectURL() כדי ליצור ObjectURLs מ-blob:

Controller.prototype._createObjectURL = function(blob) {
  var objURL = URL.createObjectURL(blob);
  this.objectURLs = this.objectURLs || [];
  this.objectURLs.push(objURL);
  return objURL;
};

כתובות URL של אובייקטים מחזיקות בזיכרון, ולכן כשאתם לא צריכים יותר את ObjectURL, צריך לבטל אותן. הוספת הפריט ה-method _clearObjectURL() ל-controller.js כדי לטפל בזה:

Controller.prototype._clearObjectURL = function() {
  if (this.objectURLs) {
    this.objectURLs.forEach(function(objURL) {
      URL.revokeObjectURL(objURL);
    });
    this.objectURLs = null;
  }
};

שליחת בקשת XHR

מוסיפים method _requestRemoteImageAndAppend() כדי להפעיל XMLHttpRequest בכתובת URL נתונה של תמונה:

Controller.prototype._requestRemoteImageAndAppend = function(imageUrl, element) {
  var xhr = new XMLHttpRequest();
  xhr.open('GET', imageUrl);
  xhr.responseType = 'blob';
  xhr.onload = function() {
    var img = document.createElement('img');
    img.setAttribute('data-src', imageUrl);
    img.className = 'icon';
    var objURL = this._createObjectURL(xhr.response);
    img.setAttribute('src', objURL);
    element.appendChild(img);
  }.bind(this);
  xhr.send();
};

בטעינת XHR, השיטה הזו יוצרת ObjectURL מהתשובה של XHR ומוסיפה רכיב <img> עם ה-ObjectURL הזה ל-DOM.

ניתוח של כתובות URL של תמונות בפריטי משימות לביצוע

עכשיו צריך להוסיף שיטה _parseForImageURLs() שתמצא את כל הקישורים שעדיין לא עובדו ובודקת אותם תמונות. לכל כתובת URL שנראית כמו תמונה, מריצים את הפקודה _requestRemoteImageAndAppend():

Controller.prototype._parseForImageURLs = function () {
  // remove old blobs to avoid memory leak:
  this._clearObjectURL();
  var links = this.$todoList.querySelectorAll('a[data-src]:not(.thumbnail)');
  var re = /\.(png|jpg|jpeg|svg|gif)$/;
  for (var i = 0; i<links.length; i++) {
    var url = links[i].getAttribute('data-src');
    if (re.test(url)) {
      links[i].classList.add('thumbnail');
      this._requestRemoteImageAndAppend(url, links[i]);
    }
  }
};

עיבוד התמונות הממוזערות ברשימת המשימות לביצוע

ניתן להתקשר עכשיו למספר _parseForImageURLs() מshowAll(), מshowActive() ומshowCompleted():

/**
 * An event to fire on load. Will get all items and display them in the
 * todo-list
 */
Controller.prototype.showAll = function () {
  this.model.read(function (data) {
    this.$todoList.innerHTML = this._parseForURLs(this.view.show(data));
    this._parseForImageURLs();
  }.bind(this));
};

/**
 * Renders all active tasks
 */
Controller.prototype.showActive = function () {
  this.model.read({ completed: 0 }, function (data) {
    this.$todoList.innerHTML = this._parseForURLs(this.view.show(data));
    this._parseForImageURLs();
  }.bind(this));
};

/**
 * Renders all completed tasks
 */
Controller.prototype.showCompleted = function () {
  this.model.read({ completed: 1 }, function (data) {
    this.$todoList.innerHTML = this._parseForURLs(this.view.show(data));
    this._parseForImageURLs();
  }.bind(this));
};

חוזרים על הפעולה עבור editItem():

Controller.prototype.editItem = function (id, label) {
  ...
  var onSaveHandler = function () {
    ...
    if (value.length && !discarding) {
      ...
      label.innerHTML = this._parseForURLs(value);
      this._parseForImageURLs();
    } else if (value.length === 0) {
  ...
}

הגבלת מידות התמונה המוצגות

לסיום, בקטע _bowercomponents/todomvc-common/base.css, מוסיפים כלל CSS שמגביל את הגודל תמונה:

.thumbnail img[data-src] {
  max-width: 100px;
  max-height: 28px;
}

הפעלה של אפליקציית Todo שסיימת

סיימת את שלב 5! טוענים מחדש את האפליקציה ומוסיפים פריט משימות עם כתובת URL לתמונה שמתארחת באינטרנט. במידה מסוימת כתובות URL שאפשר להשתמש בהן: http://goo.gl/nqHMF#.jpg או http://goo.gl/HPBGR#.png.

אפשר לקבל מידע נוסף

למידע מפורט יותר על כמה מממשקי ה-API שהוצגו בשלב הזה, אפשר לעיין במאמרים הבאים:

מוכנים להמשיך לשלב הבא? מעבר אל שלב 6 - ייצוא משימות לביצוע למערכת הקבצים »