comparison booket.js @ 10:20902b548d9f

Add Netscape bookmark file import function
author Guido Berhoerster <guido+booket@berhoerster.name>
date Wed, 17 Sep 2014 19:55:26 +0200
parents a1a934adff8d
children ef5d75bcac5e
comparison
equal deleted inserted replaced
9:19900803f7d0 10:20902b548d9f
452 452
453 var BookmarkModel = function () { 453 var BookmarkModel = function () {
454 ObservableMixin.call(this); 454 ObservableMixin.call(this);
455 455
456 this.unsavedChanges = false; 456 this.unsavedChanges = false;
457 this.loadFileReader = null;
458 this.importFileReader= null;
457 this._bookmarks = new StringMap(); 459 this._bookmarks = new StringMap();
458 this._tagCount = new StringMap(); 460 this._tagCount = new StringMap();
459 this._filterTags = new StringSet(); 461 this._filterTags = new StringSet();
460 this._searchTerm = ''; 462 this._searchTerm = '';
461 this._filteredBookmarks = new StringSet(); 463 this._filteredBookmarks = new StringSet();
721 return bookmark1.ctime - bookmark2.ctime; 723 return bookmark1.ctime - bookmark2.ctime;
722 })); 724 }));
723 this.unsavedChanges = false; 725 this.unsavedChanges = false;
724 }; 726 };
725 727
728 BookmarkModel.prototype.parseImportedBookmarks = function (data) {
729 var bookmarkDoc;
730 var bookmarkElements;
731 var i;
732 var url;
733 var title;
734 var favicon;
735 var tags;
736 var ctime;
737 var mtime;
738 var bookmarks = [];
739
740 bookmarkDoc = document.implementation.createHTMLDocument();
741 bookmarkDoc.open();
742 bookmarkDoc.write(data);
743 bookmarkDoc.close();
744
745 // create a temporary list of valid bookmarks
746 bookmarkElements = bookmarkDoc.querySelectorAll('dt > a[href]');
747 for (i = 0; i < bookmarkElements.length; i++) {
748 url = bookmarkElements[i].href;
749 if (url !== '') {
750 title = bookmarkElements[i].textContent;
751 favicon = bookmarkElements[i].getAttribute('icon');
752 tags = ((tags = bookmarkElements[i].getAttribute('tags')) !==
753 null) ? tags.split(',') : [];
754 ctime = !isNaN(ctime =
755 parseInt(bookmarkElements[i].getAttribute('add_date'), 10)) ?
756 ctime * 1000 : undefined;
757 mtime = !isNaN(mtime =
758 parseInt(bookmarkElements[i].getAttribute('last_modified'),
759 10)) ? mtime * 1000 : undefined;
760 bookmarks.push(new Bookmark(url, title, favicon, tags, ctime, mtime));
761 }
762 }
763
764 // add each bookmark to the model ordered by the last modification time
765 this.add(bookmarks.sort(function (bookmark1, bookmark2) {
766 return bookmark1.ctime - bookmark2.ctime;
767 }));
768
769 this.unsavedChanges = false;
770 };
771
726 BookmarkModel.prototype.loadFile = function (bookmarkFile) { 772 BookmarkModel.prototype.loadFile = function (bookmarkFile) {
727 var bookmarkFileReader;
728
729 // delete all existing bookmarks first 773 // delete all existing bookmarks first
730 this.delete(this._bookmarks.keys()); 774 this.delete(this._bookmarks.keys());
731 this.unsavedChanges = false; 775 this.unsavedChanges = false;
732 776
733 bookmarkFileReader = new FileReader(); 777 this.loadFileReader = new FileReader();
734 bookmarkFileReader.addEventListener('error', this); 778 this.loadFileReader.addEventListener('error', this);
735 bookmarkFileReader.addEventListener('load', this); 779 this.loadFileReader.addEventListener('load', this);
736 bookmarkFileReader.readAsText(bookmarkFile); 780 this.loadFileReader.readAsText(bookmarkFile);
781 };
782
783 BookmarkModel.prototype.importFile = function (bookmarkFile) {
784 // delete all existing bookmarks first
785 this.delete(this._bookmarks.keys());
786 this.unsavedChanges = false;
787
788 this.importFileReader = new FileReader();
789 this.importFileReader.addEventListener('error', this);
790 this.importFileReader.addEventListener('load', this);
791 this.importFileReader.readAsText(bookmarkFile);
737 }; 792 };
738 793
739 BookmarkModel.prototype.saveFile = function () { 794 BookmarkModel.prototype.saveFile = function () {
740 var jsonBlob; 795 var jsonBlob;
741 var bookmarkData = { 796 var bookmarkData = {
752 this.unsavedChanges = false; 807 this.unsavedChanges = false;
753 }; 808 };
754 809
755 BookmarkModel.prototype.handleEvent = function (e) { 810 BookmarkModel.prototype.handleEvent = function (e) {
756 if (e.type === 'load') { 811 if (e.type === 'load') {
757 this.parseLoadedBookmarks(e.target.result); 812 if (e.target === this.loadFileReader) {
813 this.parseLoadedBookmarks(e.target.result);
814 this.loadFileReader = null;
815 } else if (e.target === this.importFileReader) {
816 this.parseImportedBookmarks(e.target.result);
817 this.importFileReader = null;
818 }
758 } else if (e.type === 'error') { 819 } else if (e.type === 'error') {
759 this.notify('load-file-error', e.target.error.message); 820 this.notify('load-file-error', e.target.error.message);
760 } 821 }
761 }; 822 };
762 823
884 945
885 946
886 var ActionsView = function () { 947 var ActionsView = function () {
887 var saveFormElement; 948 var saveFormElement;
888 var loadFormElement; 949 var loadFormElement;
950 var importFormElement;
889 var newNode; 951 var newNode;
890 952
891 ObservableMixin.call(this); 953 ObservableMixin.call(this);
892 954
893 this.tagInputTemplate = document.querySelector('#tag-input-template'); 955 this.tagInputTemplate = document.querySelector('#tag-input-template');
896 958
897 this.saveLinkElement = saveFormElement.querySelector('a#save-link'); 959 this.saveLinkElement = saveFormElement.querySelector('a#save-link');
898 960
899 loadFormElement = document.querySelector('form#load-form'); 961 loadFormElement = document.querySelector('form#load-form');
900 loadFormElement.addEventListener('submit', this); 962 loadFormElement.addEventListener('submit', this);
963
964 importFormElement = document.querySelector('form#import-form');
965 importFormElement.addEventListener('submit', this);
901 966
902 // create new editor form from template 967 // create new editor form from template
903 newNode = document.importNode( 968 newNode = document.importNode(
904 document.querySelector('#bookmark-editor-template').content, true); 969 document.querySelector('#bookmark-editor-template').content, true);
905 970
1000 } else if (e.target.id === 'load-form') { 1065 } else if (e.target.id === 'load-form') {
1001 e.preventDefault(); 1066 e.preventDefault();
1002 e.target.blur(); 1067 e.target.blur();
1003 1068
1004 this.notify('load-file', e.target.file.files[0]); 1069 this.notify('load-file', e.target.file.files[0]);
1070 e.target.reset();
1071 } else if (e.target.id === 'import-form') {
1072 e.preventDefault();
1073 e.target.blur();
1074
1075 this.notify('import-file', e.target.file.files[0]);
1005 e.target.reset(); 1076 e.target.reset();
1006 } else if (e.target.classList.contains('bookmark-editor-form')) { 1077 } else if (e.target.classList.contains('bookmark-editor-form')) {
1007 e.preventDefault(); 1078 e.preventDefault();
1008 e.target.blur(); 1079 e.target.blur();
1009 1080
1450 window.addEventListener('hashchange', this.onHashChange.bind(this)); 1521 window.addEventListener('hashchange', this.onHashChange.bind(this));
1451 window.addEventListener('beforeunload', this.onBeforeUnload.bind(this)); 1522 window.addEventListener('beforeunload', this.onBeforeUnload.bind(this));
1452 this.actionsView.addObserver('save-file', 1523 this.actionsView.addObserver('save-file',
1453 this.bookmarkModel.saveFile.bind(this.bookmarkModel)); 1524 this.bookmarkModel.saveFile.bind(this.bookmarkModel));
1454 this.actionsView.addObserver('load-file', this.onLoadFile.bind(this)); 1525 this.actionsView.addObserver('load-file', this.onLoadFile.bind(this));
1526 this.actionsView.addObserver('import-file', this.onImportFile.bind(this));
1455 this.actionsView.addObserver('save-bookmark', 1527 this.actionsView.addObserver('save-bookmark',
1456 this.onSaveBookmark.bind(this)); 1528 this.onSaveBookmark.bind(this));
1457 this.bookmarkView.addObserver('edit-bookmark', 1529 this.bookmarkView.addObserver('edit-bookmark',
1458 this.onEditBookmark.bind(this)); 1530 this.onEditBookmark.bind(this));
1459 this.bookmarkView.addObserver('save-bookmark', 1531 this.bookmarkView.addObserver('save-bookmark',
1528 } 1600 }
1529 1601
1530 this.bookmarkModel.loadFile(bookmarkFile); 1602 this.bookmarkModel.loadFile(bookmarkFile);
1531 }; 1603 };
1532 1604
1605 BooketController.prototype.onImportFile = function (bookmarkFile) {
1606 if (this.bookmarkModel.unsavedChanges) {
1607 if (!this.actionsView.confirmLoadFile()) {
1608 return;
1609 }
1610 this.bookmarkModel.unsavedChanges = false;
1611 }
1612
1613 this.bookmarkModel.importFile(bookmarkFile);
1614 };
1615
1533 BooketController.prototype.onEditBookmark = function (bookmarkUrl) { 1616 BooketController.prototype.onEditBookmark = function (bookmarkUrl) {
1534 this.bookmarkView.displayBookmarkEditor( 1617 this.bookmarkView.displayBookmarkEditor(
1535 this.bookmarkModel.get(bookmarkUrl)); 1618 this.bookmarkModel.get(bookmarkUrl));
1536 }; 1619 };
1537 1620