الخطوة 4: فتح الروابط الخارجية باستخدام WebView

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

  • كيفية عرض محتوى الويب الخارجي داخل تطبيقك بطريقة آمنة ووضع الحماية.

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

التعرّف على علامة WebView

تحتاج بعض التطبيقات إلى تقديم محتوى ويب خارجي إلى المستخدم مباشرة مع الاحتفاظ به داخل تجربة التطبيق. على سبيل المثال، قد يرغب مُجمِّع الأخبار في تضمين الأخبار من مواقع إلكترونية خارجية مع تضمين جميع تنسيقات الموقع الأصلي وصوره وسلوكه. لهذه الاستخدامات وغيرها، تشتمل تطبيقات Chrome على علامة HTML مخصّصة تُسمى webview.

تطبيق Todo باستخدام WebView

تنفيذ علامة WebView

عليك تحديث تطبيق Todo للبحث عن عناوين URL في نص عنصر المهام وإنشاء رابط تشعّبي. وعند النقر على الرابط، يتم فتح نافذة جديدة لتطبيق Chrome (وليس علامة تبويب متصفّح) مع عرض WebView يعرض المحتوى.

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

في manifest.json، يمكنك طلب إذن webview:

"permissions": [
  "storage",
  "alarms",
  "notifications",
  "webview"
],

إنشاء صفحة أداة تضمين WebView

أنشئ ملفًا جديدًا في جذر مجلد المشروع وحدِّد اسمه webview.html. هذا الملف عبارة عن صفحة ويب أساسية تحتوي على علامة <webview> واحدة:

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
</head>
<body>
  <webview style="width: 100%; height: 100%;"></webview>
</body>
</html>

تحليل عناوين URL في عناصر المهام

في نهاية controller.js، أضِف طريقة جديدة تُسمى _parseForURLs():

  Controller.prototype._getCurrentPage = function () {
    return document.location.hash.split('/')[1];
  };

  Controller.prototype._parseForURLs = function (text) {
    var re = /(https?:\/\/[^\s"<>,]+)/g;
    return text.replace(re, '<a href="$1" data-src="$1">$1</a>');
  };

  // Export to window
  window.app.Controller = Controller;
})(window);

عند العثور على سلسلة تبدأ بـ "http://" أو "https://"، يتم إنشاء علامة ارتساء HTML للالتفاف حول عنوان URL.

ابحث عن showAll() في controller.js. عدِّل showAll() لتحليل الروابط باستخدام الطريقة _parseForURLs() التي تمت إضافتها سابقًا:

/**
 * 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.view.show(data);
    this.$todoList.innerHTML = this._parseForURLs(this.view.show(data));
  }.bind(this));
};

نفِّذ الإجراء نفسه مع showActive() وshowCompleted():

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

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

وأخيرًا، أضِف السمة _parseForURLs() إلى السمة editItem():

Controller.prototype.editItem = function (id, label) {
  ...
  var onSaveHandler = function () {
    ...
      // Instead of re-rendering the whole view just update
      // this piece of it
      label.innerHTML = value;
      label.innerHTML = this._parseForURLs(value);
    ...
  }.bind(this);
  ...
}

لا تزال في editItem()، أصلح الرمز بحيث يستخدم innerText للتصنيف بدلاً من innerHTML للتصنيف:

Controller.prototype.editItem = function (id, label) {
  ...
  // Get the innerHTML of the label instead of requesting the data from the
  // Get the innerText of the label instead of requesting the data from the
  // ORM. If this were a real DB this would save a lot of time and would avoid
  // a spinner gif.
  input.value = label.innerHTML;
  input.value = label.innerText;
  ...
}

فتح نافذة جديدة تحتوي على WebView

أضِف طريقة _doShowUrl() إلى controller.js. تؤدي هذه الطريقة إلى فتح نافذة جديدة لتطبيق Chrome من خلال chrome.app.window.create() باستخدام webview.html كمصدر النافذة:

  Controller.prototype._parseForURLs = function (text) {
    var re = /(https?:\/\/[^\s"<>,]+)/g;
    return text.replace(re, '<a href="$1" data-src="$1">$1</a>');
  };

  Controller.prototype._doShowUrl = function(e) {
    // only applies to elements with data-src attributes
    if (!e.target.hasAttribute('data-src')) {
      return;
    }
    e.preventDefault();
    var url = e.target.getAttribute('data-src');
    chrome.app.window.create(
     'webview.html',
     {hidden: true},   // only show window when webview is configured
     function(appWin) {
       appWin.contentWindow.addEventListener('DOMContentLoaded',
         function(e) {
           // when window is loaded, set webview source
           var webview = appWin.contentWindow.
                document.querySelector('webview');
           webview.src = url;
           // now we can show it:
           appWin.show();
         }
       );
     });
  };

  // Export to window
  window.app.Controller = Controller;
})(window);

في طلب معاودة الاتصال chrome.app.window.create()، لاحظ كيفية ضبط عنوان URL لملف WebView من خلال سمة العلامة src.

أخيرًا، أضِف أداة معالجة حدث نقر داخل الدالة الإنشائية Controller لاستدعاء doShowUrl() عندما ينقر أحد المستخدمين على رابط:

function Controller(model, view) {
  ...
  this.router = new Router();
  this.router.init();

  this.$todoList.addEventListener('click', this._doShowUrl);

  window.addEventListener('load', function () {
    this._updateFilterState();
  }.bind(this));
  ...
}

تشغيل تطبيق Todo المكتمل

لقد انتهيت من الخطوة 4! إذا أعدت تحميل تطبيقك وأضفت عنصر مهام بعنوان URL كامل يبدأ بـ http:// أو https:// ، من المفترض أن يظهر لك على النحو التالي:

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

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

هل أنت جاهز للمتابعة إلى الخطوة التالية؟ الانتقال إلى الخطوة 5: إضافة صور من الويب »