# HG changeset patch # User Guido Berhoerster # Date 1410981158 -7200 # Node ID ef5d75bcac5ee5bc567b34f65b24ae36ae504013 # Parent 20902b548d9f8e5f68a5d8c2b52f67164f41ab67 Add Netscape bookmark file export function diff -r 20902b548d9f -r ef5d75bcac5e booket.html --- a/booket.html Wed Sep 17 19:55:26 2014 +0200 +++ b/booket.html Wed Sep 17 21:12:38 2014 +0200 @@ -89,6 +89,8 @@
Select bookmark file to import
Prefix+m
Import selected file
+
Prefix+x
+
Export selected file
Prefix+f
Focus search field
@@ -121,6 +123,16 @@ + +
+
+ Export Bookmarks + + +
+
diff -r 20902b548d9f -r ef5d75bcac5e booket.js --- a/booket.js Wed Sep 17 19:55:26 2014 +0200 +++ b/booket.js Wed Sep 17 21:12:38 2014 +0200 @@ -807,6 +807,65 @@ this.unsavedChanges = false; }; +BookmarkModel.prototype.exportFile = function () { + var htmlBlob; + var bookmarkDoc; + var commentNode; + var metaElement; + var titleElement; + var headingElement; + var bookmarkListElement; + var bookmarkLinkElement; + var bookmarkElement; + + bookmarkDoc = document.implementation.createHTMLDocument(); + + // construct Netscape bookmarks format within body + commentNode = bookmarkDoc.createComment('This is an automatically ' + + 'generated file.\nIt will be read and overwritten.\nDO NOT EDIT!'); + bookmarkDoc.body.appendChild(commentNode); + + metaElement = bookmarkDoc.createElement('meta'); + metaElement.setAttribute('http-equiv', 'Content-Type'); + metaElement.setAttribute('content', 'text/html; charset=UTF-8'); + bookmarkDoc.body.appendChild(metaElement); + + titleElement = bookmarkDoc.createElement('title'); + titleElement.textContent = 'Bookmarks'; + bookmarkDoc.body.appendChild(titleElement); + + headingElement = bookmarkDoc.createElement('h1'); + headingElement.textContent = 'Bookmarks'; + bookmarkDoc.body.appendChild(headingElement); + + bookmarkListElement = bookmarkDoc.createElement('dl'); + bookmarkDoc.body.appendChild(bookmarkListElement); + + this._bookmarks.forEach(function (bookmark) { + bookmarkElement = bookmarkDoc.createElement('dt'); + + bookmarkLinkElement = bookmarkDoc.createElement('a'); + bookmarkLinkElement.href = bookmark.url; + bookmarkLinkElement.textContent = bookmark.title; + bookmarkLinkElement.setAttribute('icon', bookmark.favicon); + bookmarkLinkElement.setAttribute('tags', + bookmark.tags.values().join(',')); + bookmarkLinkElement.setAttribute('add_date', + Math.round(bookmark.ctime.getTime() / 1000)); + bookmarkLinkElement.setAttribute('last_modified', + Math.round(bookmark.mtime.getTime() / 1000)); + + bookmarkElement.appendChild(bookmarkLinkElement); + + bookmarkListElement.appendChild(bookmarkElement); + bookmarkListElement.appendChild(bookmarkDoc.createElement('dd')); + }, this); + + htmlBlob = new Blob(['\n' + + bookmarkDoc.body.innerHTML], {type: 'text/html'}); + this.notify('export-file', htmlBlob); +}; + BookmarkModel.prototype.handleEvent = function (e) { if (e.type === 'load') { if (e.target === this.loadFileReader) { @@ -948,6 +1007,7 @@ var saveFormElement; var loadFormElement; var importFormElement; + var exportFormElement; var newNode; ObservableMixin.call(this); @@ -964,6 +1024,9 @@ importFormElement = document.querySelector('form#import-form'); importFormElement.addEventListener('submit', this); + exportFormElement = document.querySelector('form#export-form'); + exportFormElement.addEventListener('submit', this); + // create new editor form from template newNode = document.importNode( document.querySelector('#bookmark-editor-template').content, true); @@ -1074,6 +1137,11 @@ this.notify('import-file', e.target.file.files[0]); e.target.reset(); + } else if (e.target.id === 'export-form') { + e.preventDefault(); + e.target.blur(); + + this.notify('export-file'); } else if (e.target.classList.contains('bookmark-editor-form')) { e.preventDefault(); e.target.blur(); @@ -1115,6 +1183,14 @@ this.saveLinkElement.click(); }; +ActionsView.prototype.onExportFile = function (htmlBlob) { + var exportLinkElement; + + exportLinkElement = document.querySelector('a#export-link'); + exportLinkElement.href = URL.createObjectURL(htmlBlob); + exportLinkElement.click(); +}; + ActionsView.prototype.confirmLoadFile = function () { return window.confirm('There are unsaved changes to your bookmarks.\n' + 'Proceed loading the bookmark file?'); @@ -1506,6 +1582,8 @@ this.actionsView.onParseFileError.bind(this.actionsView)); this.bookmarkModel.addObserver('save-file', this.actionsView.onSaveFile.bind(this.actionsView)); + this.bookmarkModel.addObserver('export-file', + this.actionsView.onExportFile.bind(this.actionsView)); this.bookmarkModel.addObserver('tag-added', this.tagView.onTagAdded.bind(this.tagView)); this.bookmarkModel.addObserver('tag-count-changed', @@ -1522,6 +1600,8 @@ window.addEventListener('beforeunload', this.onBeforeUnload.bind(this)); this.actionsView.addObserver('save-file', this.bookmarkModel.saveFile.bind(this.bookmarkModel)); + this.actionsView.addObserver('export-file', + this.bookmarkModel.exportFile.bind(this.bookmarkModel)); this.actionsView.addObserver('load-file', this.onLoadFile.bind(this)); this.actionsView.addObserver('import-file', this.onImportFile.bind(this)); this.actionsView.addObserver('save-bookmark',