diff --git a/README.txt b/README.txt index 2b89d1f0..448d01a1 100644 --- a/README.txt +++ b/README.txt @@ -3,13 +3,13 @@ --- README ------------------------------------------------------------- -SimpleMenu, Version 4.0 +SimpleMenu, Version 6.0 Written by Ted Serbinski, aka, m3avrck hello@tedserbinski.com http://tedserbinski.com -Requirements: Drupal 5.0 +Requirements: Drupal 6.x jQuery Superfish: http://users.tpg.com.au/j_birch/plugins/superfish/ @@ -29,6 +29,14 @@ jQuery Superfish: http://users.tpg.com.au/j_birch/plugins/superfish/ --- CHANGELOG -------------------------------------------------------- +6.0, 2008-xx-xx +---------------------- +- compatible with Drupal 6.x +- Superfish 1.4.1 +- separate superfish.js into own file +- remove devel links, since devel module links in 6.x can be moved to any menu now + + 5.0, 2008-Jan-26 ---------------------- diff --git a/simplemenu.info b/simplemenu.info index aaa5bfd2..129bff7a 100644 --- a/simplemenu.info +++ b/simplemenu.info @@ -1,3 +1,4 @@ ; $Id$ name = SimpleMenu description = Creates a menu bar that is displayed at the top of every page. +core = 6.x diff --git a/simplemenu.js b/simplemenu.js index 2a907b84..bf3db599 100644 --- a/simplemenu.js +++ b/simplemenu.js @@ -1,11 +1,9 @@ // $Id$ $(document).ready(function() { - // get the Drupal basepath - var basePath = Drupal.settings.simplemenu.basePath; // get the element to add the menu to var element = Drupal.settings.simplemenu.element; - var menu = ''; + var menu = $(simplemenu).attr("id", "simplemenu"); switch (Drupal.settings.simplemenu.placement) { case 'prepend': @@ -25,8 +23,7 @@ $(document).ready(function() { animation[Drupal.settings.simplemenu.effect] = 'toggle'; // Build menu - $('#simplemenu') - .append(simplemenu) + $(menu) .superfish( { animation: animation, delay: Drupal.settings.simplemenu.hideDelay, @@ -49,106 +46,6 @@ $(document).ready(function() { }); -/* - * Superfish v1.3 - jQuery menu widget - * - * Copyright (c) 2007 Joel Birch - * - * Dual licensed under the MIT and GPL licenses: - * http://www.opensource.org/licenses/mit-license.php - * http://www.gnu.org/licenses/gpl.html - * - * YOU MAY DELETE THIS CHANGELOG: - * v1.2.1 altered: 2nd July 07. added hide() before animate to make work for jQuery 1.1.3. See comment in 'over' function. - * v1.2.2 altered: 2nd August 07. changed over function .find('ul') to .find('>ul') for smoother animations - * Also deleted the iframe removal lines - not necessary it turns out - * v1.2.3 altered: jquery 1.1.3.1 broke keyboard access - had to change quite a few things and set display:none on the - * .superfish rule in CSS instead of top:-999em - * v1.3 : Pretty much a complete overhaul to make all original features work in 1.1.3.1 and above. - * .superfish rule reverted back to top:-999em (which is better) - */ - -(function($){ - $.fn.superfish = function(o){ - var $sf = this, - defaults = { - hoverClass : 'sfHover', - pathClass : 'overideThisToUse', - delay : 800, - animation : {opacity:'show'}, - speed : 'normal' - }, - over = function(){ - clearTimeout(this.sfTimer); - clearTimeout($sf[0].sfTimer); - $(this) - .showSuperfishUl() - .siblings() - .hideSuperfishUl(); - }, - out = function(){ - var $$ = $(this); - if ( !$$.is('.'+o.bcClass) ) { - this.sfTimer=setTimeout(function(){ - $$.hideSuperfishUl(); - if (!$('.'+o.hoverClass,$sf).length) { - over.call($currents.hideSuperfishUl()); - } - },o.delay); - } - }; - $.fn.extend({ - hideSuperfishUl : function(){ - return this - .removeClass(o.hoverClass) - .find('ul:visible') - .hide() - .end(); - }, - showSuperfishUl : function(){ - return this - .addClass(o.hoverClass) - .find('>ul:hidden') - .animate(o.animation,o.speed,function(){ - $(this).removeAttr('style'); - }) - .end(); - }, - applySuperfishHovers : function(){ - return this[($.fn.hoverIntent) ? 'hoverIntent' : 'hover'](over,out); - } - }); - o = $.extend({bcClass:'sfbreadcrumb'},defaults,o || {}); - var $currents = $('.'+o.pathClass,this).filter('li[ul]'); - if ($currents.length) { - $currents.each(function(){ - $(this).removeClass(o.pathClass).addClass(o.hoverClass+' '+o.bcClass); - }); - } - var $sfHovAr=$('li[ul]',this).applySuperfishHovers(over,out) - .find('a').each(function(){ - var $a = $(this), $li = $a.parents('li'); - $a.focus(function(){ - over.call($li); - return false; - }).blur(function(){ - $li.removeClass(o.hoverClass); - }); - }) - .end() - .not('.'+o.bcClass) - .hideSuperfishUl() - .end(); - $(window).unload(function(){ - $sfHovAr.unbind('mouseover').unbind('mouseout'); - }); - return this.addClass('superfish').blur(function(){ - out.call(this); - }); - }; -})(jQuery); - - /* Copyright (c) 2006 Brandon Aaron (http://brandonaaron.net) * Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php) * and GPL (http://www.opensource.org/licenses/gpl-license.php) licenses. diff --git a/simplemenu.module b/simplemenu.module index 024afa2e..e55f9087 100644 --- a/simplemenu.module +++ b/simplemenu.module @@ -9,30 +9,27 @@ /** * Implementation of hook_menu(). */ -function simplemenu_menu($may_cache) { +function simplemenu_menu() { $items = array(); - if ($may_cache) { - $items[] = array( - 'path' => 'admin/settings/simplemenu', - 'title' => t('SimpleMenu'), - 'description' => t('Select the menu to display.'), - 'callback' => 'drupal_get_form', - 'callback arguments' => array('simplemenu_admin_settings'), - 'access' => user_access('administer simplemenu') + $items['admin/settings/simplemenu'] = array( + 'title' => 'SimpleMenu', + 'description' => 'Select the menu to display.', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('simplemenu_admin_settings'), + 'access arguments' => array('administer simplemenu') ); - } return $items; } /** - * Implementation of hook_footer() + * Implementation of hook_init() */ -function simplemenu_footer() { +function simplemenu_init() { global $theme; $exclusions = variable_get('simplemenu_exclusions', array()); - if (user_access('view simplemenu') && !$exclusions[$theme]) { + if (user_access('view simplemenu') && (!isset($exclusions[$theme])) ) { global $theme, $custom_theme; $path = drupal_get_path('module', 'simplemenu'); $simplemenu_theme = variable_get('simplemenu_theme', 'original'); @@ -43,9 +40,6 @@ function simplemenu_footer() { } $settings = array( - // pass in base path to the JS file - // url() handles appending ?q= but in this case, we need to pass in the variable so the menus work when mod_rewrite is off - 'basePath' => base_path() . (variable_get('clean_url', 0) ? '' : '?q='), 'effect' => variable_get('simplemenu_effect', 'opacity'), 'effectSpeed' => variable_get('simplemenu_effect_speed', 'fast'), 'element' => variable_get('simplemenu_element', 'body'), @@ -56,6 +50,7 @@ function simplemenu_footer() { drupal_add_js(array('simplemenu' => $settings), 'setting'); drupal_add_js('var simplemenu = '. drupal_to_js(simplemenu_get_menu()) .';', 'inline'); drupal_add_js($path .'/simplemenu.js'); + drupal_add_js($path .'/superfish.js'); } } @@ -74,21 +69,12 @@ function simplemenu_admin_settings() { $form['default_menu']['simplemenu_menu'] = array( '#type' => 'select', '#title' => t('Menu'), - '#options' => menu_parent_options(0), - '#default_value' => variable_get('simplemenu_menu', 1), + '#options' => menu_parent_options(menu_get_menus(), array( 'mlid' => 0 )), // return complete tree; + '#default_value' => variable_get('simplemenu_menu', 'navigation:0'), '#description' => t('Select the menu to display.') ); } - if (module_exists('devel')) { - $form['default_menu']['simplemenu_devel'] = array( - '#type' => 'checkbox', - '#title' => t('Add devel module links'), - '#default_value' => variable_get('simplemenu_devel', 0), - '#description' => t('Add devel module links for those users that can access the devel module.') - ); - } - $form['default_menu']['simplemenu_theme'] = array( '#type' => 'select', '#title' => t('Theme'), @@ -164,18 +150,13 @@ function simplemenu_get_menu() { // if a user turned off menu module but SimpleMenu was previously set // reset variable so a menu appears - if (module_exists('menu')) { - $menu = simplemenu_menu_tree(variable_get('simplemenu_menu', 1)); - } - else { - $menu = simplemenu_menu_tree(1); - } + $menu_name = module_exists('menu') ? variable_get('simplemenu_menu', 'navigation:0') : 'navigation:0'; + $menu = simplemenu_menu_tree($menu_name); if (!$menu) { $menu = '
  • '. t('No menu items found. Try a different menu as the default.') .'
  • '; } - $output .= simplemenu_get_devel(); $output .= $menu; return $output; @@ -186,58 +167,74 @@ function simplemenu_get_menu() { * We want to retrieve the entire menu structure for a given menu, * regardless of whether or not the menu item is expanded or not. */ -function simplemenu_menu_tree($pid = 1) { - $menu = menu_get_menu(); - $output = ''; - if (isset($menu['visible'][$pid]) && $menu['visible'][$pid]['children']) { - foreach ($menu['visible'][$pid]['children'] as $mid) { - $type = isset($menu['visible'][$mid]['type']) ? $menu['visible'][$mid]['type'] : NULL; - $children = isset($menu['visible'][$mid]['children']) ? $menu['visible'][$mid]['children'] : NULL; - $output .= theme('menu_item', $mid, simplemenu_theme_menu_tree($mid), count($children) == 0); +function simplemenu_menu_tree($menu_name = 'navigation:0') { + static $menu_output = array(); + + if (!isset($menu_output[$menu_name])) { + $tree = simplemenu_tree_all_data($menu_name); + $menu_output[$menu_name] = menu_tree_output($tree); + } + return $menu_output[$menu_name]; +} + +/** + * Modified menu_tree_all_data(), providing the complete menu tree below $root_menu + * (which can be *any* menu item, not just the root of a custom menu). + * + * @param $root_menu + * root menu item of the tree to return as "menu_name:mlid" (mlid = menu link id) + * + * @todo we don't actually need $menu_name, $mlid would be sufficient + */ +function simplemenu_tree_all_data($root_menu = 'navigation:0') { + static $tree = array(); + + list($menu_name, $mlid) = explode(':', $root_menu); + + // Generate the cache ID. + // "links:navigation:all:2" means "all from root to 2" (what the ...), so for "all from 2 down" we do "links:navigation:all:2:all" + $cid = "links:$menu_name:all:$mlid". ($mlid ? ':all' : ''); + + if (!isset($tree[$cid])) { + // If the static variable doesn't have the data, check {cache_menu}. + $cache = cache_get($cid, 'cache_menu'); + if ($cache && isset($cache->data)) { + $data = $cache->data; } - } - - return $output; -} - -/** - * Custom implementation of theme_menu_tree() to call our custom menu above. - */ -function simplemenu_theme_menu_tree($pid = 1) { - if ($tree = simplemenu_menu_tree($pid)) { - return ''; - } -} - -/** - * Return a list of devel module links if the module is enabled - * and the user has access to this module. - */ -function simplemenu_get_devel() { - $output = ''; - - if (variable_get('simplemenu_devel', 0) && module_exists('devel')) { - if (user_access('access devel information')) { - $links[] = l('Devel settings', 'admin/settings/devel', array('title' => t('Adjust module settings for devel module'))); - $links[] = l('Empty cache', 'devel/cache/clear', array('title' => t('Clear the database cache tables which store page, menu, node, and variable caches.')), drupal_get_destination()); - $links[] = l('Phpinfo()', 'admin/logs/status/php'); - $links[] = l('Function reference', 'devel/reference', array('title' => t('View a list of currently defined user functions with documentation links'))); - $links[] = l('Reinstall modules', 'devel/reinstall', array('title' => t('Re-run hook_install() for a given module'))); - $links[] = l('Reset menus', 'devel/menu/reset', array('title' => t('Resets all menu items to their default settings'))); - $links[] = l('Variable editor', 'devel/variable', array('title' => t('Edit and delete site variables'))); - $links[] = l('Session viewer', 'devel/session', array('title' => t('List the contents of $_SESSION'))); - - if (function_exists('devel_node_access_perm') && user_access(DNA_ACCESS_VIEW)) { - // True only if devel_node_access enabled. - $links[] = l('Node access summary', 'devel/node_access/summary'); + else { + // Build and run the query, and build the tree. + if ($mlid > 0) { + $item = menu_link_load($mlid); + // The tree is a subtree of $menu_name, so we need to restrict the query to + // this subtree. + $px = "p$item[depth]"; + $where = " AND ml.$px = %d AND ml.mlid != %d"; + $args = array($item[$px], $mlid); } - - $output = '
  • '. t('Devel module') .'
  • '; + else { + // Get all links in this menu. + $where = ''; + $args = array(); + } + array_unshift($args, $menu_name); + // Select the links from the table, and recursively build the tree. We + // LEFT JOIN since there is no match in {menu_router} for an external + // link. + $data['tree'] = menu_tree_data(db_query(" + SELECT m.load_functions, m.to_arg_functions, m.access_callback, m.access_arguments, m.page_callback, m.page_arguments, m.title, m.title_callback, m.title_arguments, m.type, m.description, ml.* + FROM {menu_links} ml LEFT JOIN {menu_router} m ON m.path = ml.router_path + WHERE ml.menu_name = '%s'". $where ." + ORDER BY p1 ASC, p2 ASC, p3 ASC, p4 ASC, p5 ASC, p6 ASC, p7 ASC, p8 ASC, p9 ASC", $args)); + $data['node_links'] = array(); + menu_tree_collect_node_links($data['tree'], $data['node_links']); + // Cache the data. + cache_set($cid, $data, 'cache_menu'); } + // Check access for the current user to each item in the tree. + menu_tree_check_access($data['tree'], $data['node_links']); + $tree[$cid] = $data['tree']; } - return $output; + return $tree[$cid]; } \ No newline at end of file diff --git a/superfish.js b/superfish.js new file mode 100644 index 00000000..fb7ead0a --- /dev/null +++ b/superfish.js @@ -0,0 +1,100 @@ +/* + * Superfish v1.4.1 - jQuery menu widget + * Copyright (c) 2008 Joel Birch + * + * Dual licensed under the MIT and GPL licenses: + * http://www.opensource.org/licenses/mit-license.php + * http://www.gnu.org/licenses/gpl.html + * + * CHANGELOG: http://users.tpg.com.au/j_birch/plugins/superfish/changelog.txt + */ + +(function($){ + $.superfish = {}; + $.superfish.o = []; + $.superfish.op = {}; + $.superfish.defaults = { + hoverClass : 'sfHover', + pathClass : 'overideThisToUse', + delay : 800, + animation : {opacity:'show'}, + speed : 'normal', + oldJquery : false, /* set to true if using jQuery version below 1.2 */ + disableHI : false, /* set to true to disable hoverIntent usage */ + // callback functions: + onInit : function(){}, + onBeforeShow: function(){}, + onShow : function(){}, /* note this name changed ('onshow' to 'onShow') from version 1.4 onward */ + onHide : function(){} + }; + $.fn.superfish = function(op){ + var bcClass = 'sfbreadcrumb', + over = function(){ + var $$ = $(this), menu = getMenu($$); + getOpts(menu,true); + clearTimeout(menu.sfTimer); + $$.showSuperfishUl().siblings().hideSuperfishUl(); + }, + out = function(){ + var $$ = $(this), menu = getMenu($$); + var o = getOpts(menu,true); + clearTimeout(menu.sfTimer); + if ( !$$.is('.'+bcClass) ) { + menu.sfTimer=setTimeout(function(){ + $$.hideSuperfishUl(); + if (o.$path.length){over.call(o.$path);} + },o.delay); + } + }, + getMenu = function($el){ return $el.parents('ul.superfish:first')[0]; }, + getOpts = function(el,menuFound){ el = menuFound ? el : getMenu(el); return $.superfish.op = $.superfish.o[el.serial]; }, + hasUl = function(){ return $.superfish.op.oldJquery ? 'li[ul]' : 'li:has(ul)'; }; + + return this.each(function() { + var s = this.serial = $.superfish.o.length; + var o = $.extend({},$.superfish.defaults,op); + o.$path = $('li.'+o.pathClass,this).each(function(){ + $(this).addClass(o.hoverClass+' '+bcClass) + .filter(hasUl()).removeClass(o.pathClass); + }); + $.superfish.o[s] = $.superfish.op = o; + + $(hasUl(),this)[($.fn.hoverIntent && !o.disableHI) ? 'hoverIntent' : 'hover'](over,out) + .not('.'+bcClass) + .hideSuperfishUl(); + + var $a = $('a',this); + $a.each(function(i){ + var $li = $a.eq(i).parents('li'); + $a.eq(i).focus(function(){over.call($li);}).blur(function(){out.call($li);}); + }); + + o.onInit.call(this); + + }).addClass('superfish'); + }; + + $.fn.extend({ + hideSuperfishUl : function(){ + var o = $.superfish.op, + $ul = $('li.'+o.hoverClass,this).add(this).removeClass(o.hoverClass) + .find('>ul').hide().css('visibility','hidden'); + o.onHide.call($ul); + return this; + }, + showSuperfishUl : function(){ + var o = $.superfish.op, + $ul = this.addClass(o.hoverClass) + .find('>ul:hidden').css('visibility','visible'); + o.onBeforeShow.call($ul); + $ul.animate(o.animation,o.speed,function(){ o.onShow.call(this); }); + return this; + } + }); + + $(window).unload(function(){ + $('ul.superfish').each(function(){ + $('li',this).unbind('mouseover','mouseout','mouseenter','mouseleave'); + }); + }); +})(jQuery); \ No newline at end of file