الخطوة 6: تصدير المهام إلى نظام الملفات

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

  • كيفية الحصول على إشارة إلى ملف في نظام الملفات الخارجي
  • كيفية الكتابة في نظام الملفات

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

تصدير المهام

تضيف هذه الخطوة زر تصدير إلى التطبيق. وعند النقر عليه، يتم حفظ عناصر المهام الحالية في ملف ملف نصي يختار المستخدمه. إذا كان الملف متوفّرًا، سيتم استبداله. بخلاف ذلك، يتم إنشاء ملف جديد.

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

يمكن طلب أذونات نظام الملفات كسلسلة للوصول للقراءة فقط، أو كعنصر يحتوي على خصائص إضافية. على سبيل المثال:

// Read only
"permissions": ["fileSystem"]

// Read and write
"permissions": [{"fileSystem": ["write"]}]

// Read, write, autocomplate previous input, and select folder directories instead of files
"permissions": [{"fileSystem": ["write", "retainEntries", "directory"]}]

يجب أن يكون لديك إذن بالقراءة والكتابة. في manifest.json، اطلب إذن {fileSystem: [ "write" ] }:

"permissions": [
  "storage", 
  "alarms", 
  "notifications", 
  "webview",
  "<all_urls>", 
  { "fileSystem": ["write"] } 
],

تعديل عرض HTML

في index.html، أضِف زر التصدير إلى القرص ورمز div يعرض فيه التطبيق رسالة حالة:

<footer id="info">
  <button id="toggleAlarm">Activate alarm</button>
  <button id="exportToDisk">Export to disk</button>
  <div id="status"></div>
  ...
</footer>

في index.html أيضًا، حمِّل النص البرمجي export.js:

...
<script src="js/alarms.js"></script>
<script src="js/export.js"></script>

إنشاء نص تصدير

أنشئ ملف JavaScript جديدًا باسم export.js باستخدام الرمز البرمجي أدناه. احفظه في مجلد js.

(function() {

  var dbName = 'todos-vanillajs';

  var savedFileEntry, fileDisplayPath;

  function getTodosAsText(callback) {
  }

  function exportToFileEntry(fileEntry) {
  }

  function doExportToDisk() {
  }

  document.getElementById('exportToDisk').addEventListener('click', doExportToDisk);

})();

في الوقت الحالي، لا يحتوي export.js إلا على مستمع نقرات على زر التصدير إلى القرص وعناصر نائبة لسمّات getTodosAsText() وexportToFileEntry وdoExportToDisk().

الحصول على عناصر المهام كنص

عدِّل getTodosAsText() لكي يقرأ المهام من chrome.storage.local وينشئ تمثيلاً ليقولها:

function getTodosAsText(callback) {
  chrome.storage.local.get(dbName, function(storedData) {
    var text = '';

    if ( storedData[dbName].todos ) {
      storedData[dbName].todos.forEach(function(todo) {
          text += '- ';
          if ( todo.completed ) {
            text += '[DONE] ';
          }
          text += todo.title;
          text += '\n';
        }, '');
    }

    callback(text);

  }.bind(this));
}

اختيار ملف

استبدِل doExportToDisk() بـ chrome.fileSystem.chooseEntry() للسماح للمستخدم باختيار ملف:

function doExportToDisk() {

  if (savedFileEntry) {

    exportToFileEntry(savedFileEntry);

  } else {

    chrome.fileSystem.chooseEntry( {
      type: 'saveFile',
      suggestedName: 'todos.txt',
      accepts: [ { description: 'Text files (*.txt)',
                   extensions: ['txt']} ],
      acceptsAllTypes: true
    }, exportToFileEntry);

  }
}

المعلّمة الأولى chrome.fileSystem.chooseEntry() هي عنصر خيارات. المعلّمة الثانية هي طريقة ردّ اتصال.

إذا سبق أن تم حفظ FileEntry، استخدِمه بدلاً من ذلك عند الاتصال بـ exportToFileEntry(). تتوفّر ملف مراجع طوال مدة العنصر الذي يمثّل FileEntry. يربط هذا المثال FileEntry بنوافذ التطبيق حتى تتمكّن لغة JavaScript من الكتابة في الملف المحدّد بدون أي تفاعل من المستخدم ما دامت نافذة التطبيق مفتوحة.

استخدام FileEntry لكتابة عناصر المهام إلى القرص

عدِّل exportToFileEntry() لحفظ المهام كنص من خلال FileEntry Web API:

function exportToFileEntry(fileEntry) {
  savedFileEntry = fileEntry;

  var status = document.getElementById('status');

  // Use this to get a file path appropriate for displaying
  chrome.fileSystem.getDisplayPath(fileEntry, function(path) {
    fileDisplayPath = path;
    status.innerText = 'Exporting to '+path;
  });

  getTodosAsText( function(contents) {

    fileEntry.createWriter(function(fileWriter) {

      var truncated = false;
      var blob = new Blob([contents]);

      fileWriter.onwriteend = function(e) {
        if (!truncated) {
          truncated = true;
          // You need to explicitly set the file size to truncate
          // any content that might have been there before
          this.truncate(blob.size);
          return;
        }
        status.innerText = 'Export to '+fileDisplayPath+' completed';
      };

      fileWriter.onerror = function(e) {
        status.innerText = 'Export failed: '+e.toString();
      };

      fileWriter.write(blob);

    });
  });
}

يحصل chrome.fileSystem.getDisplayPath() على مسار ملف قابل للعرض يتم عرضه في الحالة div.

استخدِم fileEntry.createWriter() لإنشاء عنصر FileWriter. يمكن بعد ذلك لـ fileWriter.write() كتابة Blob في نظام الملفات. استخدِم fileWriter.onwriteend() وfileWriter.onerror() لتعديل الحالة div.

لمزيد من المعلومات عن FileEntry، يمكنك قراءة مقالة استكشاف واجهات برمجة التطبيقات FileSystem على HTML5Rocks، أو الاطّلاع على FileEntry docs على MDN.

الاحتفاظ بعناصر FileEntry

متقدّمة: لا يمكن الاحتفاظ بعناصر FileEntry إلى أجل غير مسمى. على تطبيقك أن يطلب من المستخدم اختيار ملف في كل مرة يتم فيها تشغيل التطبيق. إذا تم فرض إعادة تشغيل تطبيقك بسبب تعطُّل أثناء التشغيل أو تحديث، يمكنك استخدام restoreEntry() لاستعادة FileEntry.

يمكنك تجربة حفظ رقم التعريف الذي تعرضه دالة retainEntry() واستعادته عند إعادة تشغيل التطبيق. (ملاحظة: أضِف أداة معالجة إلى الحدث onRestarted في صفحة الخلفية).

تشغيل تطبيق "قوائم المهام" المكتمل

لقد أكملت الخطوة 6. أعِد تحميل تطبيقك وأضِف بعض المهام. انقر على التصدير إلى القرص لتصدير ملفاتك المُهمّة إلى ملف txt.

تطبيق Todo مع المهام التي تم تصديرها

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

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

هل أنت مستعد للمتابعة إلى الخطوة التالية؟ انتقِل إلى الخطوة 7: نشر تطبيقك ».