Saber 酱的抱枕

Fly me to the moon

05/19
2016
学习 软件

chrome查找重复书签之Bookmark Checker改进办法

如果chrome浏览器中有了重复书签,我们可以使用Bookmark Checker这个扩展来检查。但是Bookmark Checker的检查结果没有把重复书签放到一起,如果重复书签较多的话,找起来就非常费事。所以我写了一段JavaScript代码来重新组织Bookmark Checker的结果页面,以提高去重的效率。

首先安装Bookmark Checker,之后在浏览器的工具栏上点击它以打开操作界面。

Bookmark Checker chrome检查重复书签 扩展 改进 JavaScript

在下拉框选择“duplicate”,然后点击下方的“check”按钮,即可开始检查重复的书签。

等它检查完毕并且显示了结果页面后,请打开控制台,粘贴执行位于本文末尾的代码。

稍等片刻,等看到页面发生了变化时,就可以方便的删除书签了。重新组织后的界面如下:

Bookmark Checker chrome检查重复书签 扩展 改进 JavaScript

在重新组织后的界面里,重复书签分组放在一起,并且显示了其所在的文件夹。

点击任意书签最右侧的“Delete”,就会弹出确认对话框:
Bookmark Checker chrome检查重复书签 扩展 改进 JavaScript
确认之后该书签将被立即删除。

现在的代码保留了“一键删除已选择的书签”的功能(remove selected)。

需要注意的是本代码执行后,页面上删除文件夹的功能被隐藏了起来。但你仍然可以在书签管理器或其他扩展里删除文件夹。

代码如下:

function getFolderName (e) {	//获取书签所在的路径
    var parentE=e.parent();
    if (parentE.children()[0].nodeName==="DIV"&&parentE.children().eq(0).find(".icon.folder").length>0) {	//说明这个元素是文件夹
    	folderName=parentE.find("div").eq(0).find(".title .ng-binding").text()+"\\"+folderName;
		return getFolderName(parentE);
    }else{
	    if (parentE[0].nodeName==="DIV") {
			return folderName;
		}else{
			return getFolderName(parentE);
		}
    }
}

function sortUrl(propertyName) {	//按url排序
	return function(object1, object2) {
		var value1 = object1[propertyName];
		var value2 = object2[propertyName];
		if (value2 < value1) {
			return -1;
		} else if (value2 > value1) {
			return 1;
		} else {
			return 0;
		}
	}
}

function checkOPt(e) {		//检查并切换选中状态
	var checked=e.find("input[type=checkbox]").eq(0).prop("checked");
	if (checked) {
		e.find("input[type=checkbox]").eq(0).prop("checked",false);
	}else{
		e.find("input[type=checkbox]").eq(0).prop("checked",true);
	}
}

function delBookmark (bid,noalert) {		//删除书签
	if(noalert==="noalert"){
		chrome.bookmarks.remove(bid,function (response) {
			$("[bid="+bid+"]").parent().parent().parent().parent().remove();
			selectedL--;
			if(selectedL===0){
				alert("選擇的書籤已經全部刪除。");
			}
		});
	}else{
		if(window.confirm("你確定刪除這個書籤嗎?")){
			chrome.bookmarks.remove(bid,function (response) {
				$("[bid="+bid+"]").parent().parent().parent().parent().remove();
			});
		}
	}
}

$(".btn-remove-all").bind('click',function () {		//重做删除全部书签的功能
	if(window.confirm("你確定刪除所有选择的書籤嗎?")){
		var allInput=$("input[type=checkbox]:checked");
		selectedL=allInput.length;
		for (var i = 0; i < allInput.length; i++) {
			delBookmark(allInput.eq(i).parent().parent().find(".data-del").eq(0).attr("bid"),"noalert");
		}
	}
});

var selectedL=0;		//已选择的书签数量
var allLi=$(".angular-ui-tree-node");	//所有li,包含文件夹和书签
var allBookmarks=[];		//储存所有的书签
var allBookmarksSort=[];	//书签排序
for (var i = 0; i < allLi.length; i++) {
	if(allLi.eq(i).find("div").eq(0).find(".icon.bookmark").length>0){	//说明这是一个书签而不是文件夹
		var folderName="";
		allBookmarks.push({
			"id":allLi.eq(i).find("input").eq(0).attr("data-id"),
			"li":allLi.eq(i),
			"url":allLi.eq(i).find("a")[0].href,
			"folder":"位置:"+getFolderName(allLi.eq(i))
		});
	}
}

//书签的排序
for (var i = 0; i < allBookmarks.length; i++) {
	allBookmarksSort[i]=allBookmarks[i];
}
allBookmarksSort.sort(sortUrl("url"));

//创建输出区域
var listArea=document.createElement("div");
listArea.id="listArea";
$(".content-area.ng-scope")[0].insertBefore(listArea,$(".ng-scope.angular-ui-tree")[0]);
$("#listArea").css({"width":"100%","backgroundColor":"#fff"});
$(".ng-scope.angular-ui-tree").remove();

for (var i = 0; i < allBookmarksSort.length; i++) {
	//显示书签的路径
	var path=document.createElement("div");
	path.innerHTML=allBookmarksSort[i].folder;
	$(path).css({"color":"#D8534F","padding":"10px 0"})
	allBookmarksSort[i].li.find(".tree-content.bookmark")[0].insertBefore(path,allBookmarksSort[i].li.find(".url.ng-scope")[0]);

	//重做删除按钮和功能
	allBookmarksSort[i].li.find(".tree-delete.ng-scope").remove();
	var del=document.createElement("span");
	del.innerHTML="Delete";
	$(del).attr("bid",allBookmarksSort[i].id);
	$(del).click(function () {
		delBookmark($(this).attr("bid"));
	})
	$(del).css({"color":"#D8534F","cursor":"pointer"});
	$(del).addClass("data-del");
	allBookmarksSort[i].li.find(".tree-control.ng-scope")[0].appendChild(del);

	$("#listArea")[0].appendChild(allBookmarksSort[i].li[0]);	//插入书签

	//绑定选择/取消选择的功能
	allBookmarksSort[i].li[0].onclick=function () {
		checkOPt($(this));
	}

	//添加分割线
	if (i>0&&i<allBookmarks.length-1) {
		if (allBookmarksSort[i].url!==allBookmarksSort[i+1].url) {
			var hr=document.createElement("hr");
			$("#listArea")[0].appendChild(hr);
		}
	}
}

16.10.29 补充一个功能,需要手动执行:
如果书签都是成对重复的(每个书签都有两份,而不是三份或更多),可以执行下面的代码。执行完毕后,每对重复书签里会有一个被选中。然后点全部删除按钮(remove selected)就可以一键删除选中的书签了。这样去重更有效率。

for (var i = allBookmarksSort.length - 1; i >= 0; i=i-2) {
	allBookmarksSort[i].li[0].click();
}

注意,必须先运行上面那个很长的js代码之后再运行这个才会生效。

写这个脚本的时候挺痛苦的,因为Bookmark Checker的页面元素太过繁杂,class名还高度重复。等我重新组织了结果之后,发现原有的一些功能不生效了,自己要重写一遍 Orz

chrome查找重复书签之Bookmark Checker改进办法