NOTICE: By continued use of this site you understand and agree to the binding Terms of Service and Privacy Policy.
// ==UserScript== // @name Google Bookmarks Nested Labels // @namespace https://github.com/Lorentz83 // @description Add the 'Nested Labels' feature to google bookmarks. // @include http://www.google.com/bookmarks/* // @include https://www.google.com/bookmarks/* // @require http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.js // @version 1.3b // @grant none // @updateURL https://greasyfork.org/scripts/3186-google-bookmarks-nested-labels/code/Google%20Bookmarks%20Nested%20Labels.meta.js // @downloadURL https://greasyfork.org/scripts/3186-google-bookmarks-nested-labels/code/Google%20Bookmarks%20Nested%20Labels.user.js // @icon https://raw.githubusercontent.com/Lorentz83/userscripts/master/GoogleBookmarksNestedLabels/icon.png // @license GPLv2; http://www.gnu.org/licenses/ // ==/UserScript== /** * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ var containKeys = function(obj) { for (var key in obj) { return true; } return false; } var Tag = function(label, fullLabel, href, initialOpen, bold) { this.label = label; this.fullLabel = fullLabel; this.href = href; this.subLabel = new Object(); this.initialOpen = initialOpen; this.bold = bold; } Tag.prototype.separator = '/'; Tag.prototype.addToTree = function(splittedLabel, fullLabel, href, initialOpen){ if ( splittedLabel.length > 0 ) { if (this.subLabel[ splittedLabel[0] ] == undefined) { var bold = initialOpen && splittedLabel.length == 1; // is open and is the last //this must be fix if here there is a middle label this.subLabel[ splittedLabel[0] ] = new Tag(splittedLabel[0], fullLabel, href, initialOpen, bold); } this.initialOpen = this.initialOpen || initialOpen; this.subLabel[ splittedLabel[0] ].addToTree( splittedLabel.slice(1), fullLabel, href, initialOpen); } } Tag.prototype.toLi = function (prefix) { if (prefix == undefined) prefix = ''; var labelCssClass = 'item'; if (this.bold) { labelCssClass = 'item selectedLabel'; } var hasSubTree = containKeys(this.subLabel); var expandLinkText = '|'; var olStyle = ''; if (hasSubTree) { if (this.initialOpen){ expandLinkText = '[-]'; } else { expandLinkText = '[+]'; olStyle = 'display:none;'; } expandLinkText = '<span class="expandLink">' + expandLinkText + '</span>'; } var toReturn = new Array(); var i = 0; toReturn[i++] = prefix + '<li>'; toReturn[i++] = prefix + ' <div class="expandLinkContainer">' + expandLinkText + '</div>'; toReturn[i++] = prefix + ' <a href="' + this.href + '" title="' + this.fullLabel + '" class="' + labelCssClass + '">' + this.label + '</a>' if (hasSubTree) { toReturn[i++] = prefix + ' <ol class="subLabelsList" style="' + olStyle + '">'; for (var label in this.subLabel) { toReturn[i++] = this.subLabel[label].toLi(prefix + ' '); } toReturn[i++] = prefix + ' </ol>'; } toReturn[i++] = prefix + '</li>'; return toReturn.join('\n'); } Tag.prototype.toString = function (prefix) { if (!prefix) prefix = ''; var toReturn = prefix + this.label + '\n'; for (var i in this.subLabel) { toReturn += this.subLabel[i].toString(prefix + '-'); } return toReturn } Tag.prototype.push = function(label, href, initialOpen) { this.addToTree(label.split(this.separator), label, href, initialOpen); } Tag.prototype.clickExpandTree = function(elem) { if (elem.html() == '[-]') { elem.parent().siblings('ol').slideUp(); elem.html('[+]'); } else if (elem.html() == '[+]') { elem.parent().siblings('ol').slideDown(); elem.html('[-]'); } return false; } var li = $('#sidenav').find('li:has(a[href^="/bookmarks/lookup?"]) , li:has(a[href^="./find?q="])'); li.hide(); var tags = null; li.each(function(index){ var curr = $(this); var a = curr.find('a'); var bdo = a.find('bdo'); var num = bdo.text(); bdo.remove(); var txt = $.trim(a.text()); if(tags == null) tags = new Tag(txt, txt, a.attr('href')); else tags.push(txt, a.attr('href'), curr.hasClass('selected')); }); $('#sidenav ul').before( '<ol id="allNestedLabels" class="subLabelsList">' + tags.toLi() + '</ol>'); $('#allNestedLabels .expandLink').click( function() {return Tag.prototype.clickExpandTree( $(this) ); } ); $('#allNestedLabels > li > a').css('color', '#4D90F0'); var history = $('#sidenav').find('li:has(a[href^="/history/lookup?"])'); var historyTitle = history.eq(0); var historyEntries = history.slice(1); historyEntries.prepend('<div style="margin-left: 17px;" class="expandLinkContainer">|</div>'); historyEntries.hide(); history.find('a').css('display', 'inline'); history.find('a').css('padding-left', '5px'); historyTitle.prepend('<div style="margin-left: 13px;" class="expandLinkContainer"><span class="expandLink">[+]</span></div>'); historyTitle.find('span').click( function() { var elem = $(this); if (elem.html() == '[-]') { historyEntries.slideUp(); elem.html('[+]'); } else if (elem.html() == '[+]') { historyEntries.slideDown(); elem.html('[-]'); } return false; }); ////////////////////////////////////////////////// var customCss = new Array(); var i=0; customCss[i++] = '<style type="text/css">'; customCss[i++] = '.expandLinkContainer{display:inline-block; width:1.5em; text-align:center;}'; customCss[i++] = '.expandLink{cursor:pointer;}'; customCss[i++] = '.subLabelsList{margin-left:1.8em; }'; customCss[i++] = '#allNestedLabels li a {line-height: 18px; display:inline-block;margin:0;padding:0;}'; customCss[i++] = '#allNestedLabels li {white-space:nowrap;}'; customCss[i++] = '#allNestedLabels { margin-left: 1em; margin-bottom: 1em;}'; customCss[i++] = '.selectedLabel{font-weight:bold;}'; customCss[i++] = '</style>' $('head').append(customCss.join('\n'));