diff --git a/manifest.json b/manifest.json index 044a939..8d96fad 100644 --- a/manifest.json +++ b/manifest.json @@ -3,7 +3,7 @@ "name" : "Siderite's Bookmark Explorer", "description" : "Allows you to go to the previous/next item in a bookmark folder on the same page.", - "version" : "1.2.3", + "version" : "1.3.0", "permissions" : [ "tabs", @@ -11,7 +11,8 @@ "bookmarks", "contextMenus", "notifications", - "chrome://favicon/" + "chrome://favicon/", + "storage" ], "browser_action" : { "default_icon" : "icon.png", diff --git a/pagify.css b/pagify.css index 2587e4d..4eabc1f 100644 --- a/pagify.css +++ b/pagify.css @@ -37,6 +37,7 @@ a img { bottom:0px; background:#eeeeee; width: 100%; + height: 2em; padding: 0.75em 2.25em; } #tree>div { diff --git a/pagify.js b/pagify.js index 256b5f9..39ebdb3 100644 --- a/pagify.js +++ b/pagify.js @@ -14,7 +14,7 @@ function createTree(itm, level) { if (itm.url) { $('') .text(itm.title || itm.url) - .prepend($('').attr('src','chrome://favicon/'+itm.url)) + .prepend($('').attr('src', 'chrome://favicon/' + itm.url)) .attr('href', itm.url || '#') .attr('target', '_blank') .appendTo(elem); @@ -24,23 +24,55 @@ function createTree(itm, level) { .attr('title', 'Mark for delete'); if (level == 2) chk.appendTo(elem); - elem.click(function () { - chk.click(); + elem.click(function (ev) { + if (!chk.is(ev.target)) { + chk.prop('checked', !chk.prop('checked')); + } }); } return elem; } +function createEmpty() { + var elem = $('
'); + elem.append($('

').text('Bookmark for the URL not found')); + $('

').text('Move to a tab that has been bookmarked to populate this page.').appendTo(elem); + return elem; +} + +var currentData; function refresh(data) { + currentData = data; var tree = $('#tree').empty(); - if (!data.folder) + if (!data || !data.folder) { + tree.append(createEmpty()); + $('#btnToggleAll,#btnToggleBefore,#btnRemove').hide(); return; + } + $('#btnToggleAll,#btnToggleBefore,#btnRemove').show(); + var bottom = $('#buttons').offset().top; tree.append(createTree(data.folder, 1)); + var minTop = null; + var maxTop = null; $('a', '#tree').each(function () { if (sameUrls($(this).attr('href'), data.current.url)) { - $(this).parent().addClass('selected'); + var par = $(this).parent(); + par.addClass('selected'); + var ofs = par.offset(); + if (minTop === null) + minTop = ofs.top; + if (maxTop === null || ofs.top + par.height() > maxTop) + maxTop = ofs.top + par.height(); } }); + if (minTop && maxTop) { + var y = (minTop + maxTop) / 2; + if (y >= bottom) { + $('html,body').animate({ + scrollTop : y - bottom / 2 + }); + } + } } $(function () { @@ -51,7 +83,7 @@ $(function () { $('#tree>div>ul>li>div>input').prop('checked', val); }); $('#btnToggleBefore').click(function () { - var index = $('#tree>div>ul>li:has(a.selected)').index(); + var index = $('#tree>div>ul>li:has(div.selected)').index(); var val = $('#tree>div>ul>li>div>input:lt(' + index + '):checked').length < $('#tree>div>ul>li>div>input:lt(' + index + '):not(:checked)').length; $('#tree>div>ul>li>div>input:lt(' + index + ')').prop('checked', val); }); @@ -61,16 +93,84 @@ $(function () { return; if (!confirm('Are you sure you want to delete ' + inputs.length + ' bookmarks?')) return; - var ids = []; + var ids = [] inputs.each(function () { var id = + ($(this).val()); if (id) { - id += ''; - var input = this; - chrome.bookmarks.remove(id, function () { - $(input).closest('li').remove(); + ids.push({ + id : id + '', + input : this }); } }); + chrome.bookmarks.get(ids.map(function (p) { + return p.id; + }), function (bookmarks) { + chrome.storage.local.set({ + 'lastDeletedBookmarks' : bookmarks + }, function () { + if (chrome.runtime.lastError) { + notify('Error saving bookmarks before delete: ' + chrome.runtime.lastError.message); + } else { + $('#btnUndo').text('Restore ' + bookmarks.length + ' bookmarks').show(); + ids.forEach(function (p) { + chrome.bookmarks.remove(p.id, function () { + $(p.input).closest('li').remove(); + }); + }); + } + }); + }); + }); + chrome.storage.local.get('lastDeletedBookmarks', function (data) { + if (data && data.lastDeletedBookmarks) { + $('#btnUndo').text('Restore ' + data.lastDeletedBookmarks.length + ' bookmarks').show(); + } else { + $('#btnUndo').hide(); + } + }); + $('#btnUndo').click(function () { + chrome.storage.local.get('lastDeletedBookmarks', function (data) { + var bookmarks = data.lastDeletedBookmarks; + if (!confirm('Are you sure you want to restore ' + bookmarks.length + ' bookmarks?')) + return; + var parentIds = {}; + bookmarks.forEach(function (bm) { + if (bm.parentId) + parentIds[bm.parentId] = true; + }); + parentIds = Object.keys(parentIds); + getBookmarksById(parentIds, function (parentBookmarks) { + if (!parentBookmarks || parentBookmarks.filter(function (bm) { + return !!bm; + }).length != parentIds.length) { + notify('Parent bookmarks are missing, copying all in a new folder'); + getBookmarkBarId(function (barId) { + chrome.bookmarks.create({ + title : 'Undeleted items', + parentId : barId + }, function (parent) { + bookmarks.forEach(function (bm) { + bm.parentId = parent.id; + }); + createBookmarks(bookmarks); + notify('Bookmarks restored'); + chrome.storage.local.remove('lastDeletedBookmarks', function () { + $('#btnUndo').hide(); + refresh(currentData); + }); + }); + }); + } else { + createBookmarks(bookmarks); + notify('Bookmarks restored'); + chrome.storage.local.remove('lastDeletedBookmarks', function () { + $('#btnUndo').hide(); + refresh(currentData); + }); + } + }); + }); }); + refresh(); }); \ No newline at end of file