الخطوة 5: إضافة صور من الويب

في هذه الخطوة، ستتعلم ما يلي:

  • كيفية تحميل الموارد من خارج تطبيقك وإضافتها إلى نموذج العناصر في المستند (DOM) من خلال XHR وObjectURLs

الوقت المقدَّر لإكمال هذه الخطوة: 20 دقيقة.
لمعاينة ما ستكمله في هذه الخطوة، انتقِل إلى أسفل هذه الصفحة ↓.

كيفية تأثير سياسة أمان المحتوى على استخدام الموارد الخارجية

يفرض النظام الأساسي لتطبيقات Chrome على تطبيقك الامتثال الكامل لسياسات أمان المحتوى (CSP). لا يمكنك تحميل موارد DOM مباشرةً، مثل الصور والخطوط وCSS من خارج حزمة تطبيقات Chrome.

إذا كنت تريد عرض صورة خارجية في تطبيقك، عليك طلبها من خلال XMLHttpRequest، وتحويلها إلى فقاعة صغيرة، وإنشاء ObjectURL. يمكن إضافة ObjectURL هذا إلى نموذج كائن المستند (DOM) لأنّه يشير إلى عنصر في الذاكرة في سياق التطبيق.

عرض صور مصغّرة لعناصر المهام

لنبدأ في تغيير تطبيقنا للبحث عن عناوين URL للصور في أحد عناصر المهام. إذا كان عنوان URL يبدو مثل صورة (على سبيل المثال، ينتهي بـ .png أو .jpg أو .svg أو .gif)، طبِّق العملية المذكورة أعلاه لعرض صورة مصغّرة بجانب عنوان URL.

تحديث الأذونات

في أحد تطبيقات Chrome، يمكنك إجراء استدعاءات XMLHttpRequest لأي عنوان URL طالما أنك تحدد نطاقه في البيان. بما أنّك لن تعرف مسبقًا عنوان URL للصورة التي سيكتبها المستخدم، اطلب الإذن لتقديم طلبات إلى "<all_urls>".

في manifest.json، اطلب الإذن "":

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

إنشاء عناوين ObjectURLs ومحوها

في 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;
};

تحتفظ ObjectURLs بذاكرة التخزين، ولذلك إذا لم تعد بحاجة إلى 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.

لمزيد من المعلومات

للحصول على معلومات أكثر تفصيلاً حول بعض واجهات برمجة التطبيقات التي تم تقديمها في هذه الخطوة، يُرجى الرجوع إلى:

هل أنت جاهز للمتابعة إلى الخطوة التالية؟ الانتقال إلى الخطوة 6 - تصدير المهام إلى نظام الملفات »