שלב 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() כדי לאפשר למשתמשים לבחור file:

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

כדי ליצור אובייקט FileWriter צריך להשתמש ב-fileEntry.createWriter(). אחר כך תהיה לfileWriter.write() אפשרות לכתוב Blob למערכת הקבצים. כדי לעדכן, צריך להשתמש ב-fileWriter.onwriteend() וב-fileWriter.onerror() הסטטוס div.

למידע נוסף על FileEntry, אפשר לקרוא את המאמר התנסות בממשקי ה-API של FileSystem ב-HTML5Rocks, או עיון ב-FileEntry docs ב-MDN.

אובייקטים של FileEntry לאורך זמן

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

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

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

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

אפליקציית המשימות שצריך לייצא

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

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

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