projects/booket

changeset 10:20902b548d9f

Add Netscape bookmark file import function
author Guido Berhoerster <guido+booket@berhoerster.name>
date Wed Sep 17 19:55:26 2014 +0200 (2014-09-17)
parents 19900803f7d0
children ef5d75bcac5e
files booket.html booket.js
line diff
     1.1 --- a/booket.html	Sun Sep 14 23:14:02 2014 +0200
     1.2 +++ b/booket.html	Wed Sep 17 19:55:26 2014 +0200
     1.3 @@ -85,6 +85,10 @@
     1.4          <dd>Save bookmark file</dd>
     1.5          <dt><kbd>Prefix</kbd>+<kbd>a</kbd></dt>
     1.6          <dd>Focus bookmark editor</dd>
     1.7 +        <dt><kbd>Prefix</kbd>+<kbd>e</kbd></dt>
     1.8 +        <dd>Select bookmark file to import</dd>
     1.9 +        <dt><kbd>Prefix</kbd>+<kbd>m</kbd></dt>
    1.10 +        <dd>Import selected file</dd>
    1.11          <dt><kbd>Prefix</kbd>+<kbd>f</kbd></dt>
    1.12          <dd>Focus search field</dd>
    1.13        </dl>
    1.14 @@ -108,6 +112,15 @@
    1.15          accesskey="s">Save&#8230;</button>
    1.16        </fieldset>
    1.17      </form>
    1.18 +
    1.19 +    <form id="import-form">
    1.20 +      <fieldset>
    1.21 +        <legend>Import Bookmarks</legend>
    1.22 +        <label accesskey="e">File <input type="file" accept="text/html"
    1.23 +        required="required" name="file"></input></label>
    1.24 +        <button type="submit" name="import-file" accesskey="m">Import</button>
    1.25 +      </fieldset>
    1.26 +    </form>
    1.27    </section>
    1.28  
    1.29    <main>
     2.1 --- a/booket.js	Sun Sep 14 23:14:02 2014 +0200
     2.2 +++ b/booket.js	Wed Sep 17 19:55:26 2014 +0200
     2.3 @@ -454,6 +454,8 @@
     2.4      ObservableMixin.call(this);
     2.5  
     2.6      this.unsavedChanges = false;
     2.7 +    this.loadFileReader = null;
     2.8 +    this.importFileReader= null;
     2.9      this._bookmarks = new StringMap();
    2.10      this._tagCount = new StringMap();
    2.11      this._filterTags = new StringSet();
    2.12 @@ -723,17 +725,70 @@
    2.13      this.unsavedChanges = false;
    2.14  };
    2.15  
    2.16 +BookmarkModel.prototype.parseImportedBookmarks = function (data) {
    2.17 +    var bookmarkDoc;
    2.18 +    var bookmarkElements;
    2.19 +    var i;
    2.20 +    var url;
    2.21 +    var title;
    2.22 +    var favicon;
    2.23 +    var tags;
    2.24 +    var ctime;
    2.25 +    var mtime;
    2.26 +    var bookmarks = [];
    2.27 +
    2.28 +    bookmarkDoc = document.implementation.createHTMLDocument();
    2.29 +    bookmarkDoc.open();
    2.30 +    bookmarkDoc.write(data);
    2.31 +    bookmarkDoc.close();
    2.32 +
    2.33 +    // create a temporary list of valid bookmarks
    2.34 +    bookmarkElements = bookmarkDoc.querySelectorAll('dt > a[href]');
    2.35 +    for (i = 0; i < bookmarkElements.length; i++) {
    2.36 +        url = bookmarkElements[i].href;
    2.37 +        if (url !== '') {
    2.38 +            title = bookmarkElements[i].textContent;
    2.39 +            favicon = bookmarkElements[i].getAttribute('icon');
    2.40 +            tags = ((tags = bookmarkElements[i].getAttribute('tags')) !==
    2.41 +                null) ? tags.split(',') : [];
    2.42 +            ctime = !isNaN(ctime =
    2.43 +                parseInt(bookmarkElements[i].getAttribute('add_date'), 10)) ?
    2.44 +                ctime * 1000 : undefined;
    2.45 +            mtime = !isNaN(mtime =
    2.46 +                parseInt(bookmarkElements[i].getAttribute('last_modified'),
    2.47 +                10)) ?  mtime * 1000 : undefined;
    2.48 +            bookmarks.push(new Bookmark(url, title, favicon, tags, ctime, mtime));
    2.49 +        }
    2.50 +    }
    2.51 +
    2.52 +    // add each bookmark to the model ordered by the last modification time
    2.53 +    this.add(bookmarks.sort(function (bookmark1, bookmark2) {
    2.54 +        return bookmark1.ctime - bookmark2.ctime;
    2.55 +    }));
    2.56 +
    2.57 +    this.unsavedChanges = false;
    2.58 +};
    2.59 +
    2.60  BookmarkModel.prototype.loadFile = function (bookmarkFile) {
    2.61 -    var bookmarkFileReader;
    2.62 -
    2.63      // delete all existing bookmarks first
    2.64      this.delete(this._bookmarks.keys());
    2.65      this.unsavedChanges = false;
    2.66  
    2.67 -    bookmarkFileReader = new FileReader();
    2.68 -    bookmarkFileReader.addEventListener('error', this);
    2.69 -    bookmarkFileReader.addEventListener('load', this);
    2.70 -    bookmarkFileReader.readAsText(bookmarkFile);
    2.71 +    this.loadFileReader = new FileReader();
    2.72 +    this.loadFileReader.addEventListener('error', this);
    2.73 +    this.loadFileReader.addEventListener('load', this);
    2.74 +    this.loadFileReader.readAsText(bookmarkFile);
    2.75 +};
    2.76 +
    2.77 +BookmarkModel.prototype.importFile = function (bookmarkFile) {
    2.78 +    // delete all existing bookmarks first
    2.79 +    this.delete(this._bookmarks.keys());
    2.80 +    this.unsavedChanges = false;
    2.81 +
    2.82 +    this.importFileReader = new FileReader();
    2.83 +    this.importFileReader.addEventListener('error', this);
    2.84 +    this.importFileReader.addEventListener('load', this);
    2.85 +    this.importFileReader.readAsText(bookmarkFile);
    2.86  };
    2.87  
    2.88  BookmarkModel.prototype.saveFile = function () {
    2.89 @@ -754,7 +809,13 @@
    2.90  
    2.91  BookmarkModel.prototype.handleEvent = function (e) {
    2.92      if (e.type === 'load') {
    2.93 -        this.parseLoadedBookmarks(e.target.result);
    2.94 +        if (e.target === this.loadFileReader) {
    2.95 +            this.parseLoadedBookmarks(e.target.result);
    2.96 +            this.loadFileReader = null;
    2.97 +        } else if (e.target === this.importFileReader) {
    2.98 +            this.parseImportedBookmarks(e.target.result);
    2.99 +            this.importFileReader = null;
   2.100 +        }
   2.101      } else if (e.type === 'error') {
   2.102          this.notify('load-file-error', e.target.error.message);
   2.103      }
   2.104 @@ -886,6 +947,7 @@
   2.105  var ActionsView = function () {
   2.106      var saveFormElement;
   2.107      var loadFormElement;
   2.108 +    var importFormElement;
   2.109      var newNode;
   2.110  
   2.111      ObservableMixin.call(this);
   2.112 @@ -899,6 +961,9 @@
   2.113      loadFormElement = document.querySelector('form#load-form');
   2.114      loadFormElement.addEventListener('submit', this);
   2.115  
   2.116 +    importFormElement = document.querySelector('form#import-form');
   2.117 +    importFormElement.addEventListener('submit', this);
   2.118 +
   2.119      // create new editor form from template
   2.120      newNode = document.importNode(
   2.121          document.querySelector('#bookmark-editor-template').content, true);
   2.122 @@ -1003,6 +1068,12 @@
   2.123  
   2.124              this.notify('load-file', e.target.file.files[0]);
   2.125              e.target.reset();
   2.126 +        } else if (e.target.id === 'import-form') {
   2.127 +            e.preventDefault();
   2.128 +            e.target.blur();
   2.129 +
   2.130 +            this.notify('import-file', e.target.file.files[0]);
   2.131 +            e.target.reset();
   2.132          } else if (e.target.classList.contains('bookmark-editor-form')) {
   2.133              e.preventDefault();
   2.134              e.target.blur();
   2.135 @@ -1452,6 +1523,7 @@
   2.136      this.actionsView.addObserver('save-file',
   2.137          this.bookmarkModel.saveFile.bind(this.bookmarkModel));
   2.138      this.actionsView.addObserver('load-file', this.onLoadFile.bind(this));
   2.139 +    this.actionsView.addObserver('import-file', this.onImportFile.bind(this));
   2.140      this.actionsView.addObserver('save-bookmark',
   2.141          this.onSaveBookmark.bind(this));
   2.142      this.bookmarkView.addObserver('edit-bookmark',
   2.143 @@ -1530,6 +1602,17 @@
   2.144      this.bookmarkModel.loadFile(bookmarkFile);
   2.145  };
   2.146  
   2.147 +BooketController.prototype.onImportFile = function (bookmarkFile) {
   2.148 +    if (this.bookmarkModel.unsavedChanges) {
   2.149 +        if (!this.actionsView.confirmLoadFile()) {
   2.150 +            return;
   2.151 +        }
   2.152 +        this.bookmarkModel.unsavedChanges = false;
   2.153 +    }
   2.154 +
   2.155 +    this.bookmarkModel.importFile(bookmarkFile);
   2.156 +};
   2.157 +
   2.158  BooketController.prototype.onEditBookmark = function (bookmarkUrl) {
   2.159      this.bookmarkView.displayBookmarkEditor(
   2.160          this.bookmarkModel.get(bookmarkUrl));