שלב 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 מכיל רק פונקציות listener שבלחצן ייצוא לדיסק ו-stubs עבור 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, קראו את המאמר היכרות עם ממשקי ה-API של מערכת הקבצים ב-HTML5Rocks, או עיינו ב-FileEntry docs ב-MDN.

מתמידים של אובייקטים של FileEntry

הגדרה מתקדמת: אי אפשר לשמור FileEntry אובייקטים ללא הגבלת זמן. בכל פעם שהאפליקציה מופעלת, האפליקציה צריכה לבקש מהמשתמש לבחור קובץ. אם האפליקציה נאלצה להפעיל מחדש את האפליקציה עקב קריסה או עדכון של זמן ריצה, תוכלו להשתמש ב-restoreEntry() כדי לשחזר FileEntry.

תוכלו להתנסות על ידי שמירת המזהה שהוחזר על ידי retainEntry() ושחזור שלו בהפעלה מחדש של האפליקציה. (רמז: כדאי להוסיף האזנה לאירוע של onRestarted בדף הרקע.)

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

סיימת את שלב 6! טוענים מחדש את האפליקציה ומוסיפים משימות לביצוע. לוחצים על Export to disk כדי לייצא את המשימות לקובץ txt.

אפליקציית Todo עם רשימת המשימות שיוצאו

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

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

מוכנים להמשיך לשלב הבא? עבור אל שלב 7 - פרסום האפליקציה שלך »