diff --git a/simplemenu.admin.inc b/simplemenu.admin.inc
index 0e47f6a5..aaf09686 100644
--- a/simplemenu.admin.inc
+++ b/simplemenu.admin.inc
@@ -10,6 +10,8 @@
* SimpleMenu settings page.
*/
function simplemenu_admin_settings() {
+ $simplemenu_path = drupal_get_path('module', 'simplemenu');
+
// menu selection
$form['default_menu'] = array(
'#type' => 'fieldset',
@@ -22,29 +24,22 @@ function simplemenu_admin_settings() {
$form['default_menu']['simplemenu_menu'] = array(
'#type' => 'select',
'#title' => t('Menu'),
- '#options' => menu_parent_options(menu_get_menus(), array( 'mlid' => 0 )), // return complete tree;
+ '#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.'),
- );
+ $themes = file_scan_directory($simplemenu_path . '/themes', '.*',
+ array('.', '..', 'CVS', '.svn'), 0, FALSE, 'basename');
+ $theme_selection = array('custom' => 'custom');
+ foreach ($themes as $name => $ignore) {
+ $theme_selection[$name] = $name;
}
-
$form['default_menu']['simplemenu_theme'] = array(
'#type' => 'select',
'#title' => t('Theme'),
- '#options' => array(
- 'original' => t('original'),
- 'blackblue' => t('black & blue'),
- 'custom' => t('custom'),
- ),
+ '#options' => $theme_selection,
'#default_value' => variable_get('simplemenu_theme', 'original'),
'#description' => t('Select which theme to use. If you specify custom, you need to define CSS in your theme.'),
);
@@ -68,7 +63,9 @@ function simplemenu_admin_settings() {
'#title' => t('Scroll or fix menu'),
'#options' => $fix_options,
'#default_value' => variable_get('simplemenu_fix', 'scroll'),
- '#description' => t('Select the mode to use. The default is to let the menu scroll with the page.
WARNING: The At the Top/Bottom options prevent you from ever seeing the bottom of your drop-down menus. In other words, if you have many modules installed, it is not unlikely that your Site configuration menu will not fit the screen and the last few entries won\'t be accessible via Simplemenu.'),
+ '#description' => t('Select the mode to use. The default is to let the menu scroll with the page.')
+ . '
' . t('WARNING') . ': '
+ . t('The At the Top/Bottom options prevent you from ever seeing the bottom of your drop-down menus. In other words, if you have many modules installed, it is not unlikely that your Site configuration menu will not fit the screen and the last few entries won\'t be accessible via Simplemenu.'),
);
$form['settings']['simplemenu_hide_delay'] = array(
@@ -115,24 +112,43 @@ function simplemenu_admin_settings() {
'#default_value' => variable_get('simplemenu_uid1', 1),
);
- $simplemenu_path = drupal_get_path('module', 'simplemenu');
- $superfish = file_scan_directory($simplemenu_path, '^superfish-[0-9.]*\.js$',
+ $superfish_js = file_scan_directory($simplemenu_path, '^superfish-[0-9.]*\.js$',
array('.', '..', 'CVS', '.svn'), 0, FALSE, 'basename');
- foreach ($superfish as $name => $ignore) {
+ $superfish = array('custom' => 'custom or theme');
+ foreach ($superfish_js as $name => $ignore) {
$superfish[$name] = $name;
}
$form['advanced']['simplemenu_superfish_version'] = array(
'#type' => 'select',
'#title' => t('SuperFish Version'),
'#options' => $superfish,
- '#description' => t('Select which version of SuperFish you prefer using.') .$simplemenu_path,
+ '#description' => t('Select which version of SuperFish you prefer using. The choice "custom or theme" means that Simplemenu does not include one of its own version of Superfish. It is expected that another module or your theme does so already.'),
'#default_value' => variable_get('simplemenu_superfish_version', 'superfish-1.4.1.js'),
);
+ $scope = array(
+ 'header' => 'Header',
+ 'footer' => 'Footer',
+ );
+ $form['advanced']['simplemenu_menu_scope'] = array(
+ '#type' => 'select',
+ '#title' => t('Scope of simplemenu variable'),
+ '#options' => $scope,
+ '#description' => t('By default, the simplemenu
variable is put in the footer (backward compatible.) It is also possible to put it in the header instead.'),
+ '#default_value' => variable_get('simplemenu_menu_scope', 'footer'),
+ );
+
+ $form['advanced']['simplemenu_cache_menu'] = array(
+ '#type' => 'checkbox',
+ '#title' => t('Cache the simplemenu variable'),
+ '#description' => t('The Simplemenu now has the capability to cache the simplemenu variable in a .js file. This accelerate the transfer by using the Browser cache.'),
+ '#default_value' => variable_get('simplemenu_cache_menu', TRUE),
+ );
+
$form['advanced']['simplemenu_menubar_zindex'] = array(
'#type' => 'textfield',
'#title' => t('Menubar CSS z-index value'),
- '#description' => t('By default, the menubar CSS z-index is set to 1. Some themes or other modules may require you to change this value. Use -1 to completely disable the z-index in the menubar.'),
+ '#description' => t('By default, the menubar CSS z-index is set to 9999. Some themes or other modules may require you to change this value. Use -1 to completely disable the z-index in the menubar. If this value is not set to -1, then the following z-index will not have any effect and can as well be set to -1.'),
'#default_value' => variable_get('simplemenu_menubar_zindex', 9999),
);
diff --git a/simplemenu.install b/simplemenu.install
index 7b2c41cc..cf2afcf6 100644
--- a/simplemenu.install
+++ b/simplemenu.install
@@ -30,4 +30,15 @@ function simplemenu_update_6002() {
return array();
}
+/**
+ * Implementation of hook_update_N().
+ */
+function simplemenu_update_6003() {
+ if (variable_get('simplemenu_devel', 0)) {
+ drupal_set_message('The Simplemenu Devel is now defined in a separate module. Enable that module if you want to use the devel menu.', 'warning');
+ }
+ variable_del('simplemenu_devel');
+ return array();
+}
+
// vim: ts=2 sw=2 et syntax=php
diff --git a/simplemenu.module b/simplemenu.module
index d40bdc52..f8fb2c5e 100644
--- a/simplemenu.module
+++ b/simplemenu.module
@@ -33,10 +33,10 @@ function simplemenu_enabled() {
if (!isset($enabled)) {
global $theme;
$exclusions = variable_get('simplemenu_exclusions', array());
- $enabled = (user_access('view simplemenu')
- && (!isset($exclusions[$theme]) || !$exclusions[$theme])
+ $enabled = (!isset($exclusions[$theme]) || !$exclusions[$theme])
+ && user_access('view simplemenu')
&& _simplemenu_page_visibility()
- && _simplemenu_superuser_active());
+ && _simplemenu_superuser_active();
}
return $enabled;
@@ -47,104 +47,198 @@ function simplemenu_enabled() {
*/
function simplemenu_init() {
// do a simple access check here, since theme isn't available to check yet
- if (user_access('view simplemenu') && simplemenu_enabled()) {
- $simplemenu_path = drupal_get_path('module', 'simplemenu');
- $css_path = file_create_path('css'); // same path as concatenated Core CSS
- if (file_check_directory($css_path, FILE_CREATE_DIRECTORY)) {
- // The old way had a "static" CSS which meant that we could not easily
- // offer options to the users.
- //drupal_add_css($simplemenu_path .'/simplemenu.css');
+ if (simplemenu_enabled()) {
+ _simplemenu_add_menu();
+ _simplemenu_add_css(); // basic CSS must be before _simplemenu_add_theme()
+ _simplemenu_add_theme();
+ _simplemenu_add_js();
+ }
+}
- $fix = variable_get('simplemenu_fix', 'scroll');
+/** \brief Add the simplemenu variable with the menu to be displayed.
+ *
+ * This function loads the menu to be displayed and transforms it so
+ * it works with superfish.
+ *
+ * If the cache version of the simplemenu JavaScript string cannot be
+ * created, then it is sent inline whether or not the user asked for it
+ * to be sent inline.
+ */
+function _simplemenu_add_menu() {
+ $simplemenu = 'var simplemenu=' . drupal_to_js(simplemenu_get_menu()) . ';';
- // XXX add a variable simplemenu_update which is set to TRUE whenever
- // the settings get modified and false here
- $output_filename = variable_get('simplemenu_css_filename', '');
- if (!$output_filename) {
- $tags = array(
- '@MENUBAR_ZINDEX@' => simplemnu_get_zindex('simplemenu_menubar_zindex', 9999),
- '@DROPDOWN_ZINDEX@' => simplemnu_get_zindex('simplemenu_dropdown_zindex', 9999),
- );
- switch ($fix) {
- case 'top':
- $tags['@FIX@'] = "position: fixed;\n top: 0;";
- break;
+ $has_file = variable_get('simplemenu_cache_menu', TRUE);
+ if ($has_file) {
+ $js_path = file_create_path('js'); // same path as concatenated Core JS
+ $js_md5 = md5($simplemenu); // this is a lot faster than transferring the menu for each page!
+ $js_filename = $js_path . '/simplemenu-' . $js_md5 . '.js';
- case 'bottom':
- $tags['@FIX@'] = "position: fixed;\n bottom: 0;";
- break;
-
- default: // scroll
- $tags['@FIX@'] = 'position: relative;';
- break;
-
- }
- $css = file_get_contents($simplemenu_path . '/simplemenu.css.tpl');
- $css = strtr($css, $tags);
- $css_md5 = md5($css);
- $output_filename = $css_path . '/simplemenu-' . $css_md5 . '.css';
- if (!file_exists($output_filename)) {
- // new content, create a new file
- file_put_contents($output_filename, $css);
- }
- else {
- // this call is rather ugly, but we must make sure that the
- // system cache will take the current Simplemenu CSS in account
- _drupal_flush_css_js();
- }
- //variable_set('simplemenu_css_filename', $output_filename);
+ $has_file = file_check_directory($js_path, FILE_CREATE_DIRECTORY);
+ if ($has_file) {
+ // The old way was to send the whole menu each time
+ if (!file_exists($js_filename)) {
+ // use LOCK so concurrent writes don't mess up the file
+ @file_put_contents($js_filename, $simplemenu);
+ $has_file = file_exists($js_filename);
+ }
+ else {
+ $has_file = TRUE;
}
- drupal_add_css($output_filename);
}
- else {
+ }
+
+ $scope = variable_get('simplemenu_menu_scope', 'footer');
+ if ($has_file) {
+ drupal_add_js($js_filename, 'module', $scope);
+ }
+ else {
+ drupal_add_js($simplemenu, 'inline', $scope);
+ }
+}
+
+/** \brief Generate the CSS and add it to the page.
+ *
+ * This function generates the dynamic CSS and then insert that to
+ * the header of the page.
+ *
+ * The function regenerates the CSS only when the settings were
+ * modified. Otherwise, it uses the cached version.
+ *
+ * The function has a fall back, in case the dynamic CSS cannot
+ * be created.
+ */
+function _simplemenu_add_css() {
+ global $user;
+
+ $simplemenu_path = drupal_get_path('module', 'simplemenu');
+ $css_path = file_create_path('css'); // same path as concatenated Core CSS
+ if (file_check_directory($css_path, FILE_CREATE_DIRECTORY)) {
+ $fix = variable_get('simplemenu_fix', 'scroll');
+
+ // XXX add a variable simplemenu_update which is set to TRUE whenever
+ // the settings get modified and false here
+ $output_filename = variable_get('simplemenu_css_filename', '');
+ if (!$output_filename) {
+ $tags = array(
+ '@MENUBAR_ZINDEX@' => simplemnu_get_zindex('simplemenu_menubar_zindex', 9999),
+ '@DROPDOWN_ZINDEX@' => simplemnu_get_zindex('simplemenu_dropdown_zindex', 9999),
+ );
+ switch ($fix) {
+ case 'top':
+ $tags['@FIX@'] = "position: fixed;\n top: 0;";
+ break;
+
+ case 'bottom':
+ $tags['@FIX@'] = "position: fixed;\n bottom: 0;";
+ break;
+
+ default: // scroll
+ $tags['@FIX@'] = 'position: relative;';
+ break;
+
+ }
+ $css = file_get_contents($simplemenu_path . '/simplemenu.css.tpl');
+ $css = strtr($css, $tags);
+ $css_md5 = md5($css);
+ $output_filename = $css_path . '/simplemenu-' . $css_md5 . '.css';
+ if (!file_exists($output_filename)) {
+ // new content, create a new file
+ file_put_contents($output_filename, $css);
+ }
+ else {
+ // this call is rather ugly, but we must make sure that the
+ // system cache will take the current Simplemenu CSS in account
+ _drupal_flush_css_js();
+ }
+ //variable_set('simplemenu_css_filename', $output_filename);
+ }
+ drupal_add_css($output_filename);
+ }
+ else {
+ // in case we cannot create the dynamic CSS
+ $last_msg = variable_get('simplemenu_css_error', 0);
+ if (($last_msg != -1 && $last_msg + 3600 > time()) || $user->uid == 1) {
+ // avoid displaying the error on each page... only once per hour.
+ // (unless you are the admin, in which case you probably want to know!)
+ variable_set('simplemenu_css_error', time());
drupal_set_message(t('Simplemenu could not create the folder @path in order to save the dynamic CSS data.',
- array('@path' => $css_path)), 'error');
-
- // use a default that cannot react to the dynamic changes...
- drupal_add_css($simplemenu_path .'/simplemenu.css');
+ array('@path' => $css_path)), 'warning');
}
- // we want to put the simplemenu theme CSS first
- // so we can change some CSS entries dynamically
- // but at this time the simplemenu.css is used to
- // reset many of the CSS entries... Hmmm...
- $simplemenu_theme = variable_get('simplemenu_theme', 'original');
- $theme_file = $simplemenu_path .'/themes/'. $simplemenu_theme .'/'. $simplemenu_theme .'.css';
+ // use a default that cannot react to the dynamic changes...
+ drupal_add_css($simplemenu_path .'/simplemenu.css');
+ }
+}
+
+/** \brief Add the module theme.
+ *
+ * This function adds a theme for the Simplemenu look.
+ *
+ * By default, the original theme is used. The module also offers the
+ * blackblue theme. It is also possible to create new themes or use
+ * the theming of the current theme for simplemenu (so the menu fits
+ * perfectly for that theme.)
+ */
+function _simplemenu_add_theme() {
+ // we want to put the simplemenu theme CSS first
+ // so we can change some CSS entries dynamically
+ // but at this time the simplemenu.css is used to
+ // reset many of the CSS entries... Hmmm...
+ $simplemenu_theme = variable_get('simplemenu_theme', 'original');
+ if ($simplemenu_theme != 'custom') {
+ $simplemenu_path = drupal_get_path('module', 'simplemenu');
+ $theme_file = $simplemenu_path . '/themes/' . $simplemenu_theme
+ . '/' . $simplemenu_theme . '.css';
if (is_file($theme_file)) {
drupal_add_css($theme_file);
}
+ }
+}
- switch ($fix) {
- case 'top':
- $element = 'body';
- $placement = 'prepend';
- break;
+/** \brief Add the JavaScript that makes it all work.
+ *
+ * This function adds the Simplemenu JavaScript, the Superfish JavaScript
+ * and settings from the user.
+ */
+function _simplemenu_add_js() {
+ $simplemenu_path = drupal_get_path('module', 'simplemenu');
- case 'bottom':
- $element = 'body';
- $placement = 'append';
- break;
+ // Settings
+ $fix = variable_get('simplemenu_fix', 'scroll');
+ switch ($fix) {
+ case 'top':
+ $element = 'body';
+ $placement = 'prepend';
+ break;
- default: // 'scroll'
- // let user defined other elements when not fixed
- $element = variable_get('simplemenu_element', 'body');
- $placement = variable_get('simplemenu_element_method', 'prepend');
- break;
+ case 'bottom':
+ $element = 'body';
+ $placement = 'append';
+ break;
- }
+ default: // 'scroll'
+ // let user defined other elements when not fixed
+ $element = variable_get('simplemenu_element', 'body');
+ $placement = variable_get('simplemenu_element_method', 'prepend');
+ break;
- $settings = array(
- 'effect' => variable_get('simplemenu_effect', 'opacity'),
- 'effectSpeed' => variable_get('simplemenu_effect_speed', 'fast'),
- 'element' => $element,
- 'placement' => $placement,
- 'hideDelay' => variable_get('simplemenu_hide_delay', 800),
- 'detectPopup' => variable_get('simplemenu_detect_popup', 1),
- );
+ }
+ $settings = array(
+ 'effect' => variable_get('simplemenu_effect', 'opacity'),
+ 'effectSpeed' => variable_get('simplemenu_effect_speed', 'fast'),
+ 'element' => $element,
+ 'placement' => $placement,
+ 'hideDelay' => variable_get('simplemenu_hide_delay', 800),
+ 'detectPopup' => variable_get('simplemenu_detect_popup', 1),
+ );
+ drupal_add_js(array('simplemenu' => $settings), 'setting');
- drupal_add_js(array('simplemenu' => $settings), 'setting');
- drupal_add_js($simplemenu_path . '/simplemenu.js');
- $superfish = variable_get('simplemenu_superfish_version', 'superfish-1.4.1.js');
+ // Simplemenu
+ drupal_add_js($simplemenu_path . '/simplemenu.js');
+
+ // Superfish
+ $superfish = variable_get('simplemenu_superfish_version', 'superfish-1.4.1.js');
+ if ($superfish != 'custom') {
drupal_add_js($simplemenu_path . '/' . $superfish);
}
}
@@ -173,27 +267,6 @@ function simplemnu_get_zindex($name, $default) {
return $zindex;
}
-/**
- * Implementation of hook_footer().
- *
- * This has been broken off of simplemenu_init() because simplemenu_get_menu()
- * calls simplemenu_menu_tree() which calls menu_tree_output() which has several
- * calls to theme(). This initializes the theme system too early causing hard
- * to track bugs.
- *
- * @see http://drupal.org/node/219910
- */
-function simplemenu_footer() {
- if (simplemenu_enabled()) {
- $simplemenu = drupal_to_js(simplemenu_get_menu());
- $path = base_path() . drupal_get_path('module', 'simplemenu');
-
- $output = "\n";
-
- return $output;
- }
-}
-
/**
* Implementation of hook_perm().
*/
@@ -205,27 +278,30 @@ function simplemenu_perm() {
* Render an HTML list of links for a given menu.
*/
function simplemenu_get_menu() {
+ variable_set('simplemenu_running', TRUE);
+
// if a user turned off menu module but SimpleMenu was previously set
// reset variable so a menu appears
$menu_name = module_exists('menu') ? variable_get('simplemenu_menu', 'navigation:0') : 'navigation:0';
- $menu = simplemenu_menu_tree($menu_name);
+ $tree = simplemenu_menu_tree($menu_name);
+ // allow other modules to modify the menu tree
+ drupal_alter('simplemenu_tree', $tree);
+
+ // now generate the output
+ $menu = menu_tree_output($tree);
if (!$menu) {
- $menu = '