Google Bookmarks Nested Labels

Add the 'Nested Labels' feature to google bookmarks.

目前为 2014-07-09 提交的版本。查看 最新版本

  1. // ==UserScript==
  2. // @name Google Bookmarks Nested Labels
  3. // @namespace http://userscripts.org/users/lorentz
  4. // @description Add the 'Nested Labels' feature to google bookmarks.
  5. // @include http://www.google.com/bookmarks/*
  6. // @include https://www.google.com/bookmarks/*
  7. // @require http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.js
  8. // @version 1.2
  9. // @grant none
  10. // ==/UserScript==
  11.  
  12. /**
  13. * This program is free software: you can redistribute it and/or modify
  14. * it under the terms of the GNU General Public License as published by
  15. * the Free Software Foundation, either version 2 of the License, or
  16. * (at your option) any later version.
  17. *
  18. * This program is distributed in the hope that it will be useful,
  19. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  20. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  21. * GNU General Public License for more details.
  22. *
  23. * You should have received a copy of the GNU General Public License
  24. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  25. */
  26.  
  27. var containKeys = function(obj) {
  28. for (var key in obj) {
  29. return true;
  30. }
  31. return false;
  32. }
  33.  
  34. var Tag = function(label, fullLabel, href, initialOpen, bold) {
  35. this.label = label;
  36. this.fullLabel = fullLabel;
  37. this.href = href;
  38. this.subLabel = new Object();
  39. this.initialOpen = initialOpen;
  40. this.bold = bold;
  41. }
  42.  
  43. Tag.prototype.separator = '/';
  44.  
  45. Tag.prototype.addToTree = function(splittedLabel, fullLabel, href, initialOpen){
  46. if ( splittedLabel.length > 0 ) {
  47. if (this.subLabel[ splittedLabel[0] ] == undefined) {
  48. var bold = initialOpen && splittedLabel.length == 1; // is open and is the last
  49. //this must be fix if here there is a middle label
  50. this.subLabel[ splittedLabel[0] ] = new Tag(splittedLabel[0], fullLabel, href, initialOpen, bold);
  51. }
  52. this.initialOpen = this.initialOpen || initialOpen;
  53. this.subLabel[ splittedLabel[0] ].addToTree( splittedLabel.slice(1), fullLabel, href, initialOpen);
  54. }
  55. }
  56.  
  57. Tag.prototype.toLi = function (prefix) {
  58. if (prefix == undefined)
  59. prefix = '';
  60. var labelCssClass = 'item';
  61. if (this.bold) {
  62. labelCssClass = 'item selectedLabel';
  63. }
  64. var hasSubTree = containKeys(this.subLabel);
  65. var expandLinkText = '|';
  66. var olStyle = '';
  67. if (hasSubTree) {
  68. if (this.initialOpen){
  69. expandLinkText = '[-]';
  70. }
  71. else {
  72. expandLinkText = '[+]';
  73. olStyle = 'display:none;';
  74. }
  75. expandLinkText = '<span class="expandLink">' + expandLinkText + '</span>';
  76. }
  77. var toReturn = new Array();
  78. var i = 0;
  79. toReturn[i++] = prefix + '<li>';
  80. toReturn[i++] = prefix + ' <div class="expandLinkContainer">' + expandLinkText + '</div>';
  81. toReturn[i++] = prefix + ' <a href="' + this.href + '" title="' + this.fullLabel + '" class="' + labelCssClass + '">' + this.label + '</a>'
  82. if (hasSubTree) {
  83. toReturn[i++] = prefix + ' <ol class="subLabelsList" style="' + olStyle + '">';
  84. for (var label in this.subLabel) {
  85. toReturn[i++] = this.subLabel[label].toLi(prefix + ' ');
  86. }
  87. toReturn[i++] = prefix + ' </ol>';
  88. }
  89. toReturn[i++] = prefix + '</li>';
  90. return toReturn.join('\n');
  91. }
  92.  
  93. Tag.prototype.toString = function (prefix) {
  94. if (!prefix)
  95. prefix = '';
  96. var toReturn = prefix + this.label + '\n';
  97. for (var i in this.subLabel) {
  98. toReturn += this.subLabel[i].toString(prefix + '-');
  99. }
  100. return toReturn
  101. }
  102.  
  103. Tag.prototype.push = function(label, href, initialOpen) {
  104. this.addToTree(label.split(this.separator), label, href, initialOpen);
  105. }
  106.  
  107. Tag.prototype.clickExpandTree = function(elem) {
  108. if (elem.html() == '[-]') {
  109. elem.parent().siblings('ol').slideUp();
  110. elem.html('[+]');
  111. }
  112. else
  113. if (elem.html() == '[+]') {
  114. elem.parent().siblings('ol').slideDown();
  115. elem.html('[-]');
  116. }
  117. return false;
  118. }
  119.  
  120.  
  121. var li = $('#sidenav').find('li:has(a[href^="/bookmarks/lookup?"]) , li:has(a[href^="./find?q="])');
  122. li.hide();
  123.  
  124. var tags = null;
  125. li.each(function(index){
  126. var curr = $(this);
  127. var a = curr.find('a');
  128. var bdo = a.find('bdo');
  129. var num = bdo.text();
  130. bdo.remove();
  131. var txt = $.trim(a.text());
  132. if(tags == null)
  133. tags = new Tag(txt, txt, a.attr('href'));
  134. else
  135. tags.push(txt, a.attr('href'), curr.hasClass('selected'));
  136. });
  137. $('#sidenav ul').before( '<ol id="allNestedLabels" class="subLabelsList">' + tags.toLi() + '</ol>');
  138. $('#allNestedLabels .expandLink').click( function() {return Tag.prototype.clickExpandTree( $(this) ); } );
  139. $('#allNestedLabels > li > a').css('color', '#4D90F0');
  140.  
  141. var history = $('#sidenav').find('li:has(a[href^="/history/lookup?"])');
  142. var historyTitle = history.eq(0);
  143. var historyEntries = history.slice(1);
  144. historyEntries.prepend('<div style="margin-left: 17px;" class="expandLinkContainer">|</div>');
  145. historyEntries.hide();
  146. history.find('a').css('display', 'inline');
  147. history.find('a').css('padding-left', '5px');
  148. historyTitle.prepend('<div style="margin-left: 13px;" class="expandLinkContainer"><span class="expandLink">[+]</span></div>');
  149. historyTitle.find('span').click( function() {
  150. var elem = $(this);
  151. if (elem.html() == '[-]') {
  152. historyEntries.slideUp();
  153. elem.html('[+]');
  154. }
  155. else
  156. if (elem.html() == '[+]') {
  157. historyEntries.slideDown();
  158. elem.html('[-]');
  159. }
  160. return false;
  161. });
  162.  
  163.  
  164. //////////////////////////////////////////////////
  165.  
  166. var customCss = new Array();
  167. var i=0;
  168. customCss[i++] = '<style type="text/css">';
  169. customCss[i++] = '.expandLinkContainer{display:inline-block; width:1.5em; text-align:center;}';
  170. customCss[i++] = '.expandLink{cursor:pointer;}';
  171. customCss[i++] = '.subLabelsList{margin-left:1.8em; }';
  172. customCss[i++] = '#allNestedLabels li a {line-height: 18px; display:inline-block;margin:0;padding:0;}';
  173. customCss[i++] = '#allNestedLabels li {white-space:nowrap;}';
  174. customCss[i++] = '#allNestedLabels { margin-left: 1em; margin-bottom: 1em;}';
  175. customCss[i++] = '.selectedLabel{font-weight:bold;}';
  176. customCss[i++] = '</style>'
  177.  
  178. $('head').append(customCss.join('\n'));
  179.