Commit 0b6f0356 authored by Joshua Walker's avatar Joshua Walker
Browse files

Tons of changes!

Added hook_responsive_menus_style_info() to declare new styles.
Params when declaring:
name        : Name displayed when choosing style.
form        : Drupal FAPI callback for admin form.
js_folder   : Folder to include any .js files from.
css_folder  : Folder to include any .css files from.
js_files    : Array of individual JS files to include.
css_files   : Array of individual CSS files to include.
js_settings : Function to generate settings to pass to JS.

Included style: 'responsive_menus_simple_style' now has option to configure text on toggler.
parent e2439785
Loading
Loading
Loading
Loading
+2 −2
Changes for css/responsive_menus_simple.css: 2 added lines, 2 removed lines.
Original line number Diff line number Diff line
@@ -5,7 +5,6 @@

/* Responsive mode, engage! */
.responsive-menus.responsified span.toggler {
  width: 1.4em;
  padding: 1px;
  display: block;
  background: #333;
@@ -15,18 +14,19 @@
  font-size: 1.35em;
  text-align: center;
  cursor: pointer;
  outline: none;
}

.responsive-menus.responsified.responsive-toggled span.toggler {
  border-bottom-left-radius: 0;
  border-bottom-right-radius: 0;
  border-bottom: 1px solid #bbb;
}

.responsive-menus.responsified .responsive-menus-simple {
  display: none;
  width: 100%;
  background: #333;
  border-top-right-radius: 4px;
  border-bottom-right-radius: 4px;
  border-bottom-left-radius: 4px;
  box-shadow: 2px 2px 2px #000;
+5 −4
Changes for js/responsive_menus_simple.js: 5 added lines, 4 removed lines.
Original line number Diff line number Diff line
@@ -15,7 +15,7 @@
  Drupal.behaviors.responsive_menus = {
    attach: function (context, settings) {
      settings.responsive_menus = settings.responsive_menus || {};
      if (!settings.responsive_menus.css_selectors.length) {
      if (!settings.responsive_menus.selectors.length) {
        return;
      }
      if (!settings.responsive_menus.media_size.length) {
@@ -23,9 +23,10 @@
      }
      // Handle clicks & toggling.
      var toggler_class = '';
      var toggler_text = settings.responsive_menus.toggler_text;
      $('.responsive-menus .toggler').unbind('click');
      // Iterate through our selectors.
      $.each(settings.responsive_menus.css_selectors, function(index, value) {
      $.each(settings.responsive_menus.selectors, function(index, value) {
        if ($(value).length > 1) {
          // Handle nested menus.  Make sure we get the first, but not children.
          $(value).each(function(val_index) {
@@ -33,7 +34,7 @@
              if (!$(this).hasClass('responsive-menus-simple')) {
                toggler_class = 'responsive-menus-' + index + '-' + val_index;
                $(this).addClass('responsive-menus-simple').wrap('<div class="responsive-menus ' + toggler_class + '" />');
                $('.' + toggler_class).prepend('<span class="toggler">&#9776;</span>');
                $('.' + toggler_class).prepend('<span class="toggler">' + toggler_text + '</span>');
              }
            }
          });
@@ -43,7 +44,7 @@
          if (!$(value).hasClass('responsive-menus-simple')) {
            toggler_class = 'responsive-menus-' + index;
            $(value).addClass('responsive-menus-simple').wrap('<div class="responsive-menus ' + toggler_class + '" />');
            $('.' + toggler_class).prepend('<span class="toggler">&#9776;</span>');
            $('.' + toggler_class).prepend('<span class="toggler">' + toggler_text + '</span>');
          }
        }
      });
+278 −36
Changes for responsive_menus.module: 278 added lines, 36 removed lines.
Original line number Diff line number Diff line
@@ -34,52 +34,221 @@ function responsive_menus_permission() {
  );
}

/**
 * Implements hook_help().
 */
function responsive_menus_help($path, $arg) {
  switch ($path) {
    // On the help overview page.
    case 'admin/help#responsive_menus':
      return '<p>' . t('Responsify your menus! Using any jQuery compatible selector, make elements mobile friendly. Technically you could use this on more than menus... The <a href="@admin">administration page</a> provides settings to control which menus to control, what screen size to react to, and a few other options.', array('@admin' => url('admin/config/user-interface/responsive_menus'))) . '</p>';
    // On the admin settings page.
    case 'admin/config/user-interface/responsive_menus':
      return '<p>' . t('This page provides configuration options for responsive menus. You may configure any amount of menus to respond to any screen size by simply adding a jQuery compatible selector to the list below. There is also an option to ignore admin pages where you might not want responsive menus.') . '</p>';
  }
}

/**
 * Admin settings form for which menus to responsify.
 */
function responsive_menus_admin_form($form, &$form_state) {
  $form['responsive_menus_css_selectors'] = array(
    '#type' => 'textarea',
    '#title' => t('CSS selectors for which menus to responsify'),
    '#default_value' => variable_get('responsive_menus_css_selectors', '.main-menu'),
    '#description' => 'Enter CSS selectors of menus to responsify.  Comma separated or 1 per line',
  );
  // Gather enabled styles.
  $styles = responsive_menus_styles();
  foreach ($styles as $style => $values) {
    $style_options[$style] = $values['name'];
  }
  // Get style settings form elements from ajax or currently set style.
  if (!empty($form_state['values']['responsive_menus_style'])) {
    $current_style = $form_state['values']['responsive_menus_style'];
  }
  else {
    $current_style = variable_get('responsive_menus_style', 'responsive_menus_simple');
  }

  $form['responsive_menus_style'] = array(
    '#type' => 'select',
    '#title' => t('Responsive menu style'),
    '#options' => array(
      'responsive_menus_simple' => t("Simple 3-bar (!bars) expanding.", array('!bars' => '☰')),
    '#options' => $style_options,
    '#default_value' => $current_style,
    '#ajax' => array(
      'callback' => 'responsive_menus_style_settings_form',
      'wrapper' => 'rm-style-options',
      'method' => 'replace',
      'effect' => 'fade',
    ),
    '#description' => '<small>More options to come.  Submit your suggestions!</small>',
  );
  $form['responsive_menus_media_size'] = array(
    '#type' => 'textfield',
    '#title' => t('Screen width to respond to'),
    '#size' => 10,
    '#default_value' => variable_get('responsive_menus_media_size', 768),
    '#description' => 'Width in pixels when we swap out responsive menu e.g. 768',

  $form['responsive_menus_style_settings'] = array(
    '#title' => t('Style settings'),
    '#description' => t('Settings for chosen menu style.'),
    '#prefix' => '<div id="rm-style-options">',
    '#suffix' => '</div>',
    '#type' => 'fieldset',
    '#tree' => TRUE,
  );

  if (!empty($styles[$current_style]['form']) && function_exists($styles[$current_style]['form'])) {
    $styles_function = $styles[$current_style]['form'];
    foreach ($styles_function() as $name => $element) {
      $form['responsive_menus_style_settings'][$name] = $element;
    }
  }

  $form['responsive_menus_ignore_admin'] = array(
    '#type' => 'checkboxes',
    '#options' => array(1 => t('Ignore admin pages?')),
    '#default_value' => variable_get('responsive_menus_ignore_admin', array(1 => 1)),
  );

  return system_settings_form($form);
  $form['actions']['#type'] = 'actions';
  $form['actions']['submit'] = array(
    '#type' => 'submit',
    '#value' => t('Save configuration'),
  );

  if (!empty($_POST) && form_get_errors()) {
    drupal_set_message(t('The settings have not been saved because of the errors.'), 'error');
  }
  $form['#submit'][] = 'responsive_menus_admin_form_submit';

  return $form;
}

/**
 * Implements hook_help().
 * Ajax callback for switching styles.
 */
function responsive_menus_help($path, $arg) {
  switch ($path) {
    // On the help overview page.
    case 'admin/help#responsive_menus':
      return '<p>' . t('Responsify your menus! Using any jQuery compatible selector, make elements mobile friendly. Technically you could use this on more than menus... The <a href="@admin">administration page</a> provides settings to control which menus to control, what screen size to react to, and a few other options.', array('@admin' => url('admin/config/user-interface/responsive_menus'))) . '</p>';
    // On the admin settings page.
    case 'admin/config/user-interface/responsive_menus':
      return '<p>' . t('This page provides configuration options for responsive menus. You may configure any amount of menus to respond to any screen size by simply adding a jQuery compatible selector to the list below. There is also an option to ignore admin pages where you might not want responsive menus.') . '</p>';
function responsive_menus_style_settings_form($form, $form_state) {
  return $form['responsive_menus_style_settings'];
}

/**
 * Submit handler for resopnsive_menus_admin_form.
 */
function responsive_menus_admin_form_submit($form, &$form_state) {
  // Exclude unnecessary elements.
  form_state_values_clean($form_state);

  foreach ($form_state['values'] as $key => $value) {
    if (is_array($value) && isset($form_state['values']['array_filter'])) {
      $value = array_keys(array_filter($value));
    }
    if ($key == 'responsive_menus_style_settings') {
      foreach ($value as $style_key => $style_value) {
        variable_set($style_key, $style_value);
      }
    }
    else {
      variable_set($key, $value);
    }
  }

  drupal_set_message(t('The configuration options have been savedz.'));
}

/**
 * Gather available styles for Responsive Menus.
 *
 * @return array
 *   Array of available styles.
 */
function responsive_menus_styles() {
  $data = &drupal_static(__FUNCTION__, array());
  if (!isset($data['styles'])) {
    $data['styles'] = module_invoke_all('responsive_menus_style_info');
    drupal_alter('responsive_menus_styles', $data['styles']);
  }

  return $data['styles'];
}

/**
 * Load a single style.
 *
 * @param string $style
 *   Style id to be loaded.
 */
function responsive_menus_style_load($style) {
  $styles = responsive_menus_styles();
  if (!empty($styles[$style])) {
    return $styles[$style];
  }

  return FALSE;
}

/**
 * Example implementation of hook_responsive_menus_style_info().
 *
 * You can use js/css_folder to load a whole directory's files, or
 * js/css_files to load individual files.
 *
 * The parameters 'form' & 'js_settings' are callbacks to functions.
 */
function hook_responsive_menus_style_info() {
  $path = drupal_get_path('module', 'responsive_menus');
  $styles = array(
    'example_style' => array(
      'name' => t('Example Responsive Menus style'),
      'form' => 'example_style_settings',
      'js_folder' => drupal_get_path('module', 'responsive_menus') . '/js',
      'css_folder' => drupal_get_path('module', 'responsive_menus') . '/css',
      'js_files' => array(
        $path . '/js/example1.js',
        $path . '/js/example2.js'
      ),
      'css_files' => array($path . '/css/example.css'),
      'js_settings' => 'example_style_js_settings',
    ),
  );

  return $styles;
}

/**
 * Implements hook_responsive_menus_style_info().
 */
function responsive_menus_responsive_menus_style_info() {
  $path = drupal_get_path('module', 'responsive_menus');
  $styles = array(
    'responsive_menus_simple' => array(
      'name' => t("Simple 3-bar (!bars) expanding.", array('!bars' => '☰')),
      'form' => 'responsive_menus_simple_style_settings',
      'js_folder' => $path . '/js',
      'css_folder' => $path . '/css',
      'js_settings' => 'responsive_menus_simple_style_js_settings',
    ),
  );

  return $styles;
}

/**
 * Additional form settings for style responsive_menus_simple.
 *
 * @return array
 *   Drupal FAPI formatted array.
 */
function responsive_menus_simple_style_settings() {
  $form['responsive_menus_css_selectors'] = array(
    '#type' => 'textarea',
    '#title' => t('CSS selectors for which menus to responsify'),
    '#default_value' => variable_get('responsive_menus_css_selectors', '.main-menu'),
    '#description' => 'Enter CSS selectors of menus to responsify.  Comma separated or 1 per line',
  );
  $form['responsive_menus_simple_text'] = array(
    '#type' => 'textfield',
    '#title' => t('Text to display for menu toggle button'),
    '#default_value' => variable_get('responsive_menus_simple_text', '☰ Menu'),
  );
  $form['responsive_menus_media_size'] = array(
    '#type' => 'textfield',
    '#title' => t('Screen width to respond to'),
    '#size' => 10,
    '#default_value' => variable_get('responsive_menus_media_size', 768),
    '#description' => 'Width in pixels when we swap out responsive menu e.g. 768',
  );

  return $form;
}

/**
@@ -90,7 +259,6 @@ function responsive_menus_help($path, $arg) {
 */
function responsive_menus_build_selectors() {
  $selectors = variable_get('responsive_menus_css_selectors', '.main-menu');
  $js_settings = array();
  $delimiter = ', ';
  // Strip out carriage returns.
  $selectors = str_replace("\r", '', $selectors);
@@ -99,11 +267,58 @@ function responsive_menus_build_selectors() {
  // Explode to include original delimited.
  $values = explode($delimiter, $selectors);
  $values = array_filter($values);
  $js_settings['css_selectors'] = $values;

  return $values;
}

/**
 * Callback from hook_responsive_menus_style_info() for JS settings to pass.
 */
function responsive_menus_simple_style_js_settings() {
  $js_settings = array();
  $js_settings['toggler_text'] = variable_get('responsive_menus_simple_text', '☰ Menu');
  $js_settings['selectors'] = responsive_menus_build_selectors();
  $js_settings['media_size'] = variable_get('responsive_menus_media_size', 768);

  return $js_settings;
}

/**
 * Recursively glob for directories.
 *
 * @param string $directory
 *   Directory to glob.
 * @param array $directories
 *   Increasing array of matching directories.
 */
function responsive_menus_glob_recursive($directory, &$directories = array()) {
  foreach (glob($directory, GLOB_ONLYDIR | GLOB_NOSORT) as $folder) {
    $directories[] = $folder;
    responsive_menus_glob_recursive("{$folder}/*", $directories);
  }
}

/**
 * Recursively search through directories for files with given extension.
 *
 * @param string $directory
 *   Directory to search.
 * @param string $extension
 *   File extensions to look for.
 *
 * @return array
 *   Array of matching files.
 */
function responsive_menus_glob_files($directory, $extension) {
  responsive_menus_glob_recursive($directory, $directories);
  $files = array();
  foreach($directories as $key => $directory) {
    $files = array_merge($files, glob("{$directory}/*.{$extension}"));
  }

  return $files;
}

/**
 * Implements hook_init().
 */
@@ -112,16 +327,43 @@ function responsive_menus_init() {
  if ($ignore_admin[1] && path_is_admin(current_path())) {
    return;
  }
  // Load our style.
  $style = variable_get('responsive_menus_style', 'responsive_menus_simple');
  $style_info = responsive_menus_style_load($style);

  $js_settings = array();
  // @todo Will do libraries lookup later when other responsive styles added.
  $included_libraries = array('responsive_menus_simple');
  if (in_array($style, $included_libraries)) {
    drupal_add_css(drupal_get_path('module', 'responsive_menus') . "/css/{$style}.css");
    drupal_add_js(drupal_get_path('module', 'responsive_menus') . "/js/{$style}.js");
  }
  // Add selectors to JS settings.
  $js_settings += responsive_menus_build_selectors();
  $js_settings['media_size'] = variable_get('responsive_menus_media_size', 768);
  $js_files = array();
  $css_files = array();
  // Load JS files from folder.
  if (!empty($style_info['js_folder'])) {
    $js_files = responsive_menus_glob_files($style_info['js_folder'], 'js');
  }
  // Load CSS files from folder.
  if (!empty($style_info['css_folder'])) {
    $css_files = responsive_menus_glob_files($style_info['css_folder'], 'css');
  }
  // Load individual JS files.
  if (!empty($style_info['js_files'])) {
    $js_files = array_unique(array_merge($js_files, $style_info['js_files']));
  }
  // Load individual CSS files.
  if (!empty($style_info['css_files'])) {
    $css_files = array_unique(array_merge($css_files, $style_info['css_files']));
  }
  // Add JS files.
  if (!empty($js_files)) {
    foreach ($js_files as $js_file) {
      drupal_add_js($js_file);
    }
  }
  // Add CSS files.
  if (!empty($css_files)) {
    foreach ($css_files as $css_file) {
      drupal_add_css($css_file);
    }
  }
  // Add JS settings.
  $js_settings = $style_info['js_settings']();
  drupal_alter('responsive_menus_init', $js_settings);
  drupal_add_js(array('responsive_menus' => $js_settings), 'setting');
}