/* * * jQuery listmenu plugin * Copyright (c) 2009 iHwy, Inc. * Author: Jack Killpatrick * * Version 1.1 (08/09/2009) * Requires jQuery 1.3.2 or jquery 1.2.6 * * Visit http://www.ihwy.com/labs/jquery-listmenu-plugin.aspx for more information. * * Dual licensed under the MIT and GPL licenses: * http://www.opensource.org/licenses/mit-license.php * http://www.gnu.org/licenses/gpl.html * */ (function($) { $.fn.listmenu = function(options) { var opts = $.extend({}, $.fn.listmenu.defaults, options); var alph = ['_', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '-']; return this.each(function() { var $wrapper, list, $list, $letters, letters = {}, $letterCount, id, $menu, colOpts = $.extend({}, $.fn.listmenu.defaults.cols, opts.cols), onNav = false, onMenu = false, currentLetter = ''; id = this.id; $list = $(this); function init() { $list.css('visibility', 'hidden'); // hiding to prevent pre-load flicker. Using visibility:hidden so that list item dimensions remain available setTimeout(function() { $list.before(createWrapperHtml()); $wrapper = $('#' + id + '-menu'); $wrapper.append(createLettersHtml()); $letters = $('.lm-letters', $wrapper).slice(0, 1); // will always be a single item if (opts.showCounts) $letterCount = $('.lm-letter-count', $wrapper).slice(0, 1); // will always be a single item $wrapper.append(createMenuHtml()); $menu = $('.lm-menu', $wrapper); populateMenu(); if (opts.flagDisabled) addDisabledClass(); // run after populateMenu(): needs some data from there bindHandlers(); // decide whether to include num and/or other links // if (!opts.includeNums) $('._', $letters).remove(); if (!opts.includeOther) $('.-', $letters).remove(); $(':last', $letters).addClass('lm-last'); $wrapper.show(); }, 50); } // positions the letter count div above the letter links (so we only have to do it once: after this we just change it's left position via mouseover) // function setLetterCountTop() { $letterCount.css({ top: $('.a', $letters).slice(0, 1).offset({ margin: false, border: true }).top - $letterCount.outerHeight({ margin: true }) }); } function addDisabledClass() { for (var i = 0; i < alph.length; i++) { if (letters[alph[i]] === undefined) $('.' + alph[i], $letters).addClass('lm-disabled'); } } function populateMenu() { var gutter = colOpts.gutter, cols = colOpts.count, menuWidth, colWidth; if (opts.menuWidth) menuWidth = opts.menuWidth; // use user defined menu width if one provided, else calculate one else menuWidth = $('.lm-letters', $wrapper).width() - ($menu.outerWidth() - $menu.width()); colWidth = (cols == 1) ? menuWidth : Math.floor((menuWidth - (gutter * (cols - 1))) / cols); $menu.width(menuWidth); // prevents it from resizing based on content $list.width(colWidth); var letter, outerHeight; $list.children().each(function() { str = $(this).text().replace(/\s+/g, ''); // strip all white space from text (including tabs and linebreaks that might have been in the HTML) // thanks to Liam Byrne, liam@onsight.ie // Deployed with SRF 1.9 to recognize the data-sortkey var sortKey = String( $(this).data( 'sortkey' ) ); if ( sortKey !== 'undefined' ){ firstChar = sortKey.toLowerCase(); } else { if (str !== '') { firstChar = str.slice(0, 1).toLowerCase(); if (/\W/.test(firstChar)) firstChar = '-'; // not A-Z, a-z or 0-9, so considered "other" if (!isNaN(firstChar)) firstChar = '_'; // use '_' if the first char is a number } } outerHeight = $(this).outerHeight(); if (letters[firstChar] === undefined) letters[firstChar] = { totHeight: 0, count: 0, colHeight: 0, hasMenu: false }; letter = letters[firstChar]; letter.totHeight += outerHeight; letter.count++; $.data($(this)[0], id, { firstChar: firstChar, height: outerHeight }); }); $.each(letters, function() { this.colHeight = (this.count > 1) ? Math.ceil(this.totHeight / cols) : this.totHeight; }); var $this, data, iHeight, iLetter, cols = {}, c; var tagName = $list[0].tagName.toLowerCase(); $list.children().each(function() { $this = $(this); data = $.data($this.get(0), id); iLetter = data.firstChar; iHeight = data.height; if (!letters[l = iLetter].hasMenu) { $menu.append('
'); letters[iLetter].hasMenu = true; } if (cols[iLetter] === undefined) cols[iLetter] = { height: 0, colNum: 0, itemCount: 0, $colRoot: null }; c = cols[iLetter]; c.itemCount++; if (c.height === 0) { c.colNum++; $('.lm-submenu.' + iLetter, $menu).append('