jquery.treeview.js 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208
  1. ;(function($) {
  2. $.extend($.fn, {
  3. swapClass: function(c1, c2) {
  4. var c1Elements = this.filter('.' + c1);
  5. this.filter('.' + c2).removeClass(c2).addClass(c1);
  6. c1Elements.removeClass(c1).addClass(c2);
  7. return this;
  8. },
  9. replaceClass: function(c1, c2) {
  10. return this.filter('.' + c1).removeClass(c1).addClass(c2).end();
  11. },
  12. hoverClass: function(className) {
  13. className = className || "hover";
  14. return this.hover(function() {
  15. $(this).addClass(className);
  16. }, function() {
  17. $(this).removeClass(className);
  18. });
  19. },
  20. heightToggle: function(animated, callback) {
  21. animated ?
  22. this.animate({ height: "toggle" }, animated, callback) :
  23. this.each(function(){
  24. jQuery(this)[ jQuery(this).is(":hidden") ? "show" : "hide" ]();
  25. if(callback)
  26. callback.apply(this, arguments);
  27. });
  28. },
  29. heightHide: function(animated, callback) {
  30. if (animated) {
  31. this.animate({ height: "hide" }, animated, callback);
  32. } else {
  33. this.hide();
  34. if (callback)
  35. this.each(callback);
  36. }
  37. },
  38. prepareBranches: function(settings) {
  39. if (!settings.prerendered) {
  40. this.filter(":last-child:not(ul)").addClass(CLASSES.last);
  41. this.filter((settings.collapsed ? "" : "." + CLASSES.closed) + ":not(." + CLASSES.open + ")").find(">ul").hide();
  42. }
  43. return this.filter(":has(>ul)");
  44. },
  45. applyClasses: function(settings, toggler) {
  46. this.filter(":has(>ul):not(:has(>a))").find(">span").click(function(event) {
  47. toggler.apply($(this).next());
  48. }).add( $("a", this) ).hoverClass();
  49. if (!settings.prerendered) {
  50. this.filter(":has(>ul:hidden)")
  51. .addClass(CLASSES.expandable)
  52. .replaceClass(CLASSES.last, CLASSES.lastExpandable);
  53. this.not(":has(>ul:hidden)")
  54. .addClass(CLASSES.collapsable)
  55. .replaceClass(CLASSES.last, CLASSES.lastCollapsable);
  56. this.prepend("<div class=\"" + CLASSES.hitarea + "\"/>").find("div." + CLASSES.hitarea).each(function() {
  57. var classes = "";
  58. $.each($(this).parent().attr("class").split(" "), function() {
  59. classes += this + "-hitarea ";
  60. });
  61. $(this).addClass( classes );
  62. });
  63. }
  64. this.find("div." + CLASSES.hitarea).click( toggler );
  65. },
  66. treeview: function(settings) {
  67. settings = $.extend({
  68. cookieId: "treeview"
  69. }, settings);
  70. if (settings.add) {
  71. return this.trigger("add", [settings.add]);
  72. }
  73. if ( settings.toggle ) {
  74. var callback = settings.toggle;
  75. settings.toggle = function() {
  76. return callback.apply($(this).parent()[0], arguments);
  77. };
  78. }
  79. function treeController(tree, control) {
  80. function handler(filter) {
  81. return function() {
  82. toggler.apply( $("div." + CLASSES.hitarea, tree).filter(function() {
  83. return filter ? $(this).parent("." + filter).length : true;
  84. }) );
  85. return false;
  86. };
  87. }
  88. $("a:eq(0)", control).click( handler(CLASSES.collapsable) );
  89. $("a:eq(1)", control).click( handler(CLASSES.expandable) );
  90. $("a:eq(2)", control).click( handler() );
  91. }
  92. function toggler() {
  93. $(this)
  94. .parent()
  95. .find(">.hitarea")
  96. .swapClass( CLASSES.collapsableHitarea, CLASSES.expandableHitarea )
  97. .swapClass( CLASSES.lastCollapsableHitarea, CLASSES.lastExpandableHitarea )
  98. .end()
  99. .swapClass( CLASSES.collapsable, CLASSES.expandable )
  100. .swapClass( CLASSES.lastCollapsable, CLASSES.lastExpandable )
  101. .find( ">ul" )
  102. .heightToggle( settings.animated, settings.toggle );
  103. if ( settings.unique ) {
  104. $(this).parent()
  105. .siblings()
  106. .find(">.hitarea")
  107. .replaceClass( CLASSES.collapsableHitarea, CLASSES.expandableHitarea )
  108. .replaceClass( CLASSES.lastCollapsableHitarea, CLASSES.lastExpandableHitarea )
  109. .end()
  110. .replaceClass( CLASSES.collapsable, CLASSES.expandable )
  111. .replaceClass( CLASSES.lastCollapsable, CLASSES.lastExpandable )
  112. .find( ">ul" )
  113. .heightHide( settings.animated, settings.toggle );
  114. }
  115. }
  116. function serialize() {
  117. function binary(arg) {
  118. return arg ? 1 : 0;
  119. }
  120. var data = [];
  121. branches.each(function(i, e) {
  122. data[i] = $(e).is(":has(>ul:visible)") ? 1 : 0;
  123. });
  124. $.cookie(settings.cookieId, data.join("") );
  125. }
  126. function deserialize() {
  127. var stored = $.cookie(settings.cookieId);
  128. if ( stored ) {
  129. var data = stored.split("");
  130. branches.each(function(i, e) {
  131. $(e).find(">ul")[ parseInt(data[i]) ? "show" : "hide" ]();
  132. });
  133. }
  134. }
  135. this.addClass("treeview");
  136. var branches = this.find("li").prepareBranches(settings);
  137. switch(settings.persist) {
  138. case "cookie":
  139. var toggleCallback = settings.toggle;
  140. settings.toggle = function() {
  141. serialize();
  142. if (toggleCallback) {
  143. toggleCallback.apply(this, arguments);
  144. }
  145. };
  146. deserialize();
  147. break;
  148. case "location":
  149. var current = this.find("a").filter(function() { return this.href.toLowerCase() == location.href.toLowerCase(); });
  150. if ( current.length ) {
  151. current.addClass("selected").parents("ul, li").add( current.next() ).show();
  152. }
  153. break;
  154. }
  155. branches.applyClasses(settings, toggler);
  156. if ( settings.control ) {
  157. treeController(this, settings.control);
  158. $(settings.control).show();
  159. }
  160. return this.bind("add", function(event, branches) {
  161. $(branches).prev()
  162. .removeClass(CLASSES.last)
  163. .removeClass(CLASSES.lastCollapsable)
  164. .removeClass(CLASSES.lastExpandable)
  165. .find(">.hitarea")
  166. .removeClass(CLASSES.lastCollapsableHitarea)
  167. .removeClass(CLASSES.lastExpandableHitarea);
  168. $(branches).find("li").andSelf().prepareBranches(settings).applyClasses(settings, toggler);
  169. });
  170. }
  171. });
  172. var CLASSES = $.fn.treeview.classes = {
  173. open: "open",
  174. closed: "closed",
  175. expandable: "expandable",
  176. expandableHitarea: "expandable-hitarea",
  177. lastExpandableHitarea: "lastExpandable-hitarea",
  178. collapsable: "collapsable",
  179. collapsableHitarea: "collapsable-hitarea",
  180. lastCollapsableHitarea: "lastCollapsable-hitarea",
  181. lastCollapsable: "lastCollapsable",
  182. lastExpandable: "lastExpandable",
  183. last: "last",
  184. hitarea: "hitarea"
  185. };
  186. $.fn.Treeview = $.fn.treeview;
  187. })(jQuery);