diff --git a/background.js b/background.js index 1583bea..4e6279f 100644 --- a/background.js +++ b/background.js @@ -1,5 +1,3 @@ chrome.browserAction.onClicked.addListener(function(tab) { - chrome.tabs.create({'url': chrome.extension.getURL('cleanup.html')}, function(tab) { - // Tab opened. - }); + chrome.tabs.create({'url': chrome.extension.getURL('cleanup.html')}); }); diff --git a/bookmarkcleanup.js b/bookmarkcleanup.js index ed7f678..da2e44b 100644 --- a/bookmarkcleanup.js +++ b/bookmarkcleanup.js @@ -1,201 +1,280 @@ +noQuery = { + extend: function(recipient, source) { + for (var key in source) { + if(source.hasOwnProperty(key)){ + recipient[key] = source[key]; + } + } + }, + + checkboxes: function() { + var slice = Array.prototype.slice, + inputs = slice.call(document.querySelectorAll("form input")); + + return checkboxes = inputs.filter(function(input) { + return input.attributes['type'].value === "checkbox"; + }); + }, + + get: function(url) { + return new Promise(function(resolve, reject) { + var xhr = new XMLHttpRequest(); + + xhr.onreadystatechange = function(args) { + try { + if (this.readyState != 4) return; + resolve(this); + } catch(err) { + reject(new Error(err)); + } + }; -// Get all the bookmarks -$(document).ready(function(){ - - getBookmarks(); - - $( "#threehun" ).click(function() { - var val = $("#threehun a").text(); - switch(val){ - case "Deselect 300's": - $( "#threehun a" ).text("Select 300's") - $("form input:checkbox[status^=3]").prop("checked", false); - break; - case "Select 300's": - $( "#threehun a" ).text("Deselect 300's") - $("form input:checkbox[status^=3]").prop("checked", true); - break; - } - }); - - - $( "#fourhun" ).click(function() { - var val = $("#fourhun a").text(); - switch(val){ - case "Deselect 400's": - $( "#fourhun a" ).text("Select 400's") - $("form input:checkbox[status^=4]").prop("checked", false); - break; - case "Select 400's": - $( "#fourhun a" ).text("Deselect 400's") - $("form input:checkbox[status^=4]").prop("checked", true); - break; - } + xhr.open("GET", url); + xhr.send(); }); + } +} - $( "#fivehun" ).click(function() { - var val = $("#fivehun a").text(); - switch(val){ - case "Deselect 500's": - $( "#fivehun a" ).text("Select 500's") - $("form input:checkbox[status^=5]").prop("checked", false); - break; - case "Select 500's": - $( "#fivehun a" ).text("Deselect 500's") - $("form input:checkbox[status^=5]").prop("checked", true); - break; - } - }); +function Bookmark(data) { + noQuery.extend(this, data); + + this.statusCode = null; + this.statusLookupActivity = this.determineHttpStatus(); +}; + +Bookmark.prototype = { + toHtml: function(callback) { + return this.statusLookupActivity.then(function() { + return this._template(); + }.bind(this)); + }, + + determineHttpStatus: function() { + successCallback = function(xhr) { + this.statusCode = xhr.status; + }.bind(this), + failureCallback = function(error) { + throw(error); + }; - $( "#generics" ).click(function() { - var val = $("#generics a").text(); - switch(val){ - case "Deselect Generic Errors": - $( "#generics a" ).text("Select Generic Errors") - $("form input:checkbox[status^=0]").prop("checked", false); - break; - case "Select Generic Errors": - $( "#generics a" ).text("Deselect Generic Errors") - $("form input:checkbox[status^=0]").prop("checked", true); - break; - } + return noQuery.get(this.url) + .then(successCallback, failureCallback); + }, + + _template: function() { + return [ + ' ', + this.title, + ' ', + this.statusCode, + '' + ].join(''); + } +}; + +function Container(data) { + noQuery.extend(this, data); + this.raw = data; + this.children = this._calculateChildren(); +}; + +Container.prototype = { + toHTML: function() { + return [ + '', + ' ', this.title, '', + '' + ].join(''); + }, + + bookmarks: function() { + var accumulator; + this._bookmarks(accumulator = []); + return this._sanitizeBookmarks(accumulator); + }, + + bookmarksByAscendingDate: function() { + return this.bookmarks().sort(function(a, b) { + return b.dateAdded - a.dateAdded; }); + }, - - $( "#clean").click(function() { - console.log("clean click") - var checkedLength = $( "input:checked" ).length - if (checkedLength < 1) { - $( "#delwarning" ).text("You haven't selected any bookmarks to delete.") - $( "#dialog" ).dialog({ buttons: [ { text: "Close", click: function() { $( this ).dialog( "close" ); } } ] }); + _sanitizeBookmarks: function(bookmarks) { + function isNotScriptlet(url) { + return !url.match(/^(javascript|data|about):/); } - else { - $( "#delwarning" ).text("This will delete "+checkedLength+" bookmarks. Are you sure you want to do this?") - $( "#dialog" ).dialog({ buttons: [ - { text: "I'm sure.", click: function() { - $( this ).dialog( "close" ); - for (var i=0; i < checkedLength; i++) { - var badBookmark = $( "input:checked" )[i].value; - chrome.bookmarks.remove(String(badBookmark)) - $( '#'+badBookmark ).remove(); - }; - - }}, - { text: "Nope, get me out of here.", click: function() { $( this ).dialog( "close" );}} - - - ]}); - }; - + return bookmarks.filter(function(bookmark) { + return isNotScriptlet(bookmark.url); }); - - - -}); - -function getBookmarks(){ - - chrome.bookmarks.getTree(function(r) - { var arrayLength = r.length; - // console.log(arrayLength); - for (var i=0; i < arrayLength; i++) { - treeWalk(r[i]); - }; - + }, + + _bookmarks: function(memo) { + this.children.forEach(function(node) { + if (node instanceof Bookmark) { + memo.push(node); + } else if (node instanceof Container) { + node._bookmarks(memo); + } + }.bind(this)); + }, + + containers: function() { + var accumulator; + this._containers(accumulator = []); + return this._sanitizeContainers(accumulator); + }, + + _sanitizeContainers: function(containers) { + return containers.filter(function(container) { + return (container.title != ""); }); -} - - -function treeWalk(obj) { - if (obj.children) { - if (obj.title.length > 0){ - $("#bookmarks").append(' '+obj.title+'');} - - if (typeof bookmarksArray === "undefined") { - // Make an empty array to hold the bookmarks - bookmarksArray = [] - } - else { - //Do some stuff with the current bookmarksArray - console.log (bookmarksArray) - for (var i=0; i < bookmarksArray.length; i++) { - urlTesting(bookmarksArray[i]); - } - // Empty out the bookmarksArray array - bookmarksArray = [] - } - - // for each child, do the tree walk - for (var i=0; i < obj.children.length; i++) { - treeWalk(obj.children[i]); - // console.log(urls) - - } - - - } - if (obj['url']) { - // Test to make sure its not a "special" bookmark. - if (obj.id && (obj.url.indexOf('javascript:') < 0) && (obj.url.indexOf('data:') < 0) && (obj.url.indexOf('about:') < 0)) { - // Beginning the code for async - bookmarksArray.push(obj) - - } + }, + + _containers: function(memo) { + this.children.forEach(function(node) { + if (node instanceof Container) { + memo.push(node); + node._containers(memo) + } + }.bind(this)); + }, + + _calculateChildren: function() { + if (this.raw instanceof(Array)) { + return this.raw.map(function(childNode) { + return new Container(childNode); + }.bind(this)); + } else if (this.raw.children.length > 0) { + return this.raw.children.map(function(child) { + if (typeof(child.url) === "undefined") { + return new Container(child); + } else { + if (!child.url.match(/^http/)) return; + return new Bookmark(child); } - + }.bind(this)); } + throw { + message: "Expected Container to be initialized with children that were enumerable; they were not.", + name: "UnclassifiedChildrenCollectionType" + } + } +}; - -function urlTesting(obj) { - - $.ajax({ - url: obj.url, - type: 'GET', - statusCode: { - - 0: function() { - var code = 0; - var row = ' '+obj.title+' '+code+'' - $('#'+obj.parentId).after(row); - }, - - 403: function() { - var code = 403; - var row = ' '+obj.title+' '+code+'' - $('#'+obj.parentId).after(row); - }, - - - 404: function() { - var code = 404; - var row = ' '+obj.title+' '+code+'' - $('#'+obj.parentId).after(row); - }, - - 503: function() { - var code = 503; - var row = ' '+obj.title+' '+code+'' - $('#'+obj.parentId).after(row); - }, - - 408: function() { - var code = 408; - var row = ' '+obj.title+' '+code+'' - $('#'+obj.parentId).after(row); - }, - - 500: function() { - var code = 500; - var row = ' '+obj.title+' '+code+'' - $('#'+obj.parentId).after(row); - }, - - } - - }); +function View(selector) { + this.selectorNode = document.getElementById(selector); + this._initializeControls(); } +View.prototype = { + draw: function(obj) { + obj.containers().forEach(function(container) { + this.selectorNode + .insertAdjacentHTML('beforeend', container.toHTML()); + }.bind(this)); + + obj.bookmarksByAscendingDate().forEach(function(bookmark) { + bookmark.toHtml().then(function(bookmarkHtml) { + document.getElementById(bookmark.parentId) + .insertAdjacentHTML('afterend', bookmarkHtml); + }) + }); + }, + + _initializeSelectionControls: function() { + var links = [ + { selector: "threehun", text: "300s" }, + { selector: "fourhun", text: "400s" }, + { selector: "fivehun", text: "500s" }, + { selector: "generics", text: "Generic Errors" } + ].map(function(obj) { + var matchRE = new RegExp(obj.text.charAt(0)); + obj.inputsSelector = function() { + return noQuery.checkboxes() + .filter(function(cb) { + return cb.attributes['status'].value.match(matchRE); + }); + } + return obj; + }); + + links.forEach(function(clickBehaviorSpecifier) { + document + .getElementById(clickBehaviorSpecifier.selector) + .addEventListener('click', function(e) { + var targetNode = e.currentTarget, + untoggled = !targetNode.getAttribute('data-toggled'); + if (untoggled) { + targetNode.setAttribute('data-toggled', true); + targetNode.childNodes[0].innerHTML = "Deselect " + clickBehaviorSpecifier.text; + clickBehaviorSpecifier.inputsSelector().forEach(function(cb) { + cb.setAttribute('checked', true); + cb.checked = true; + }); + } else { + targetNode.removeAttribute('data-toggled'); + targetNode.childNodes[0].innerHTML = "Select " + clickBehaviorSpecifier.text; + clickBehaviorSpecifier.inputsSelector().forEach(function(cb) { + cb.checked = false; + }); + } + }); + }); + }, + + _initializeDeletionControls: function() { + document.getElementById("clean").addEventListener('click', function() { + var result, + warningText, + checkedBoxes = noQuery.checkboxes().filter(function(cb) { + return !!cb.checked; + }), + checkedLength = checkedBoxes.length; + + if (checkedLength < 1) { + alert("You haven't selected any bookmarks to delete."); + return; + } else { + result = confirm( + ["This will delete ", + checkedLength, + " bookmark", + (checkedLength > 1 ? "s" : ""), + ". Are you sure you want to do this?"].join('') + ); + if (result) { + checkedBoxes.forEach(function(cb) { + var badBookmarkValue = String(cb.getAttribute("value")), + node = document.getElementById(badBookmarkValue); + chrome.bookmarks.remove(badBookmarkValue) + node.parentNode.removeChild(node); + }); + } + } + }); + }, + _initializeControls: function() { + this._initializeSelectionControls(); + this._initializeDeletionControls(); + } +} +document.addEventListener('DOMContentLoaded', function() { + if ( typeof(chrome.bookmarks) === "undefined" ) return []; + chrome.bookmarks.getTree(function(r) { + new View("bookmarks").draw(new Container(r)); + }); +}); diff --git a/cleanup.html b/cleanup.html index 6ff68bd..66d89ab 100644 --- a/cleanup.html +++ b/cleanup.html @@ -1,9 +1,6 @@ - - -