supersubs.js 3.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. /*
  2. * Supersubs v0.2b - jQuery plugin - LAST UPDATE: MARCH 23rd, 2011
  3. * Copyright (c) 2008 Joel Birch
  4. *
  5. * Jan 16th, 2011 - Modified a little in order to work with NavBar menus as well.
  6. *
  7. * Dual licensed under the MIT and GPL licenses:
  8. * http://www.opensource.org/licenses/mit-license.php
  9. * http://www.gnu.org/licenses/gpl.html
  10. *
  11. * This plugin automatically adjusts submenu widths of suckerfish-style menus to that of
  12. * their longest list item children. If you use this, please expect bugs and report them
  13. * to the jQuery Google Group with the word 'Superfish' in the subject line.
  14. *
  15. */
  16. (function($){ // $ will refer to jQuery within this closure
  17. $.fn.supersubs = function(options){
  18. var opts = $.extend({}, $.fn.supersubs.defaults, options);
  19. // return original object to support chaining
  20. return this.each(function() {
  21. // cache selections
  22. var $$ = $(this);
  23. // support metadata
  24. var o = $.meta ? $.extend({}, opts, $$.data()) : opts;
  25. // get the font size of menu.
  26. // .css('fontSize') returns various results cross-browser, so measure an em dash instead
  27. var fontsize = $('<li id="menu-fontsize">&#8212;</li>').css({
  28. 'padding' : 0,
  29. 'position' : 'absolute',
  30. 'top' : '-99999em',
  31. 'width' : 'auto'
  32. }).appendTo($$).width(); //clientWidth is faster, but was incorrect here
  33. // remove em dash
  34. $('#menu-fontsize').remove();
  35. // Jump on level if it's a "NavBar"
  36. if ($$.hasClass('sf-navbar')) {
  37. $$ = $('li > ul', $$);
  38. }
  39. // cache all ul elements
  40. $ULs = $$.find('ul:not(.sf-megamenu)');
  41. // loop through each ul in menu
  42. $ULs.each(function(i) {
  43. // cache this ul
  44. var $ul = $ULs.eq(i);
  45. // get all (li) children of this ul
  46. var $LIs = $ul.children();
  47. // get all anchor grand-children
  48. var $As = $LIs.children('a');
  49. // force content to one line and save current float property
  50. var liFloat = $LIs.css('white-space','nowrap').css('float');
  51. // remove width restrictions and floats so elements remain vertically stacked
  52. var emWidth = $ul.add($LIs).add($As).css({
  53. 'float' : 'none',
  54. 'width' : 'auto'
  55. })
  56. // this ul will now be shrink-wrapped to longest li due to position:absolute
  57. // so save its width as ems. Clientwidth is 2 times faster than .width() - thanks Dan Switzer
  58. .end().end()[0].clientWidth / fontsize;
  59. // add more width to ensure lines don't turn over at certain sizes in various browsers
  60. emWidth += o.extraWidth;
  61. // restrict to at least minWidth and at most maxWidth
  62. if (emWidth > o.maxWidth) { emWidth = o.maxWidth; }
  63. else if (emWidth < o.minWidth) { emWidth = o.minWidth; }
  64. emWidth += 'em';
  65. // set ul to width in ems
  66. $ul.css('width',emWidth);
  67. // restore li floats to avoid IE bugs
  68. // set li width to full width of this ul
  69. // revert white-space to normal
  70. $LIs.css({
  71. 'float' : liFloat,
  72. 'width' : '100%',
  73. 'white-space' : 'normal'
  74. })
  75. // update offset position of descendant ul to reflect new width of parent
  76. .each(function(){
  77. var $childUl = $('>ul',this);
  78. var offsetDirection = $childUl.css('left')!==undefined ? 'left' : 'right';
  79. $childUl.css(offsetDirection,emWidth);
  80. });
  81. });
  82. });
  83. };
  84. // expose defaults
  85. $.fn.supersubs.defaults = {
  86. minWidth: 9, // requires em unit.
  87. maxWidth: 25, // requires em unit.
  88. extraWidth: 0 // extra width can ensure lines don't sometimes turn over due to slight browser differences in how they round-off values
  89. };
  90. })(jQuery); // plugin code ends