ขั้นตอนที่ 5: เพิ่มรูปภาพจากเว็บ

ในขั้นตอนนี้ คุณจะได้เรียนรู้เกี่ยวกับสิ่งต่อไปนี้

  • วิธีโหลดทรัพยากรจากภายนอกแอปและเพิ่มลงใน DOM ผ่าน XHR และ ObjectURL

เวลาโดยประมาณในการทำขั้นตอนนี้คือ 20 นาที
หากต้องการดูตัวอย่างสิ่งที่คุณจะทำในขั้นตอนนี้ ให้เลื่อนลงไปที่ด้านล่างของหน้านี้ ↓

CSP ส่งผลต่อการใช้ทรัพยากรภายนอกอย่างไร

แพลตฟอร์มแอป Chrome จะบังคับให้แอปของคุณปฏิบัติตามนโยบายรักษาความปลอดภัยเนื้อหา (CSP) โดยสมบูรณ์ คุณไม่สามารถโหลดทรัพยากร DOM เช่น รูปภาพ แบบอักษร และ CSS จากภายนอกแอป Chrome ได้โดยตรง ใหม่

หากต้องการแสดงรูปภาพภายนอกในแอป คุณจะต้องส่งคำขอผ่าน XMLHttpRequest เปลี่ยนรูปแบบเป็น Blob แล้วสร้าง ObjectURL สามารถเพิ่ม ObjectURL นี้ลงใน DOM เพราะอ้างถึงรายการในหน่วยความจำในบริบทของแอป

แสดงภาพขนาดย่อของรายการสิ่งที่ต้องทำ

มาเปลี่ยนแอปให้มองหา URL รูปภาพในรายการสิ่งที่ต้องทำกัน หาก URL ดูเหมือนรูปภาพ (สำหรับ ตัวอย่างเช่น ลงท้ายด้วย .png, .jpg, .svg หรือ .gif) ให้ใช้กระบวนการที่กล่าวไว้ข้างต้นเพื่อแสดง รูปภาพขนาดย่อที่อยู่ถัดจาก URL

อัปเดตสิทธิ์

ในแอป Chrome คุณสามารถเรียก XMLHttpRequest ไปยัง URL ใดก็ได้ตราบใดที่คุณระบุโดเมนของ URL นั้นใน ไฟล์ Manifest เนื่องจากคุณไม่ทราบล่วงหน้าว่าผู้ใช้จะพิมพ์ URL รูปภาพใด คุณจึงควรขออนุญาต ส่งคำขอไปยัง "<all_urls>"

ใน manifest.json ให้พิมพ์ "" สิทธิ์:

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

สร้างและล้าง ObjectURL

ใน controller.js ให้เพิ่มเมธอด _createObjectURL() เพื่อสร้าง ObjectURL จาก Blob

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

ObjectURL จะเก็บหน่วยความจำอยู่ ดังนั้นเมื่อคุณไม่จำเป็นต้องใช้ ObjectURL แล้ว คุณควรเพิกถอนคำขอเหล่านั้น เพิ่มรายการนี้ _clearObjectURL() ไปยัง controller.js เพื่อจัดการกับ:

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

ส่งคำขอ XHR

เพิ่มเมธอด _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 - ส่งออกสิ่งที่ต้องทำไปยังระบบไฟล์ »