You are here

jqmulti.module in jQuery Multi 6

Same filename and directory in other branches
  1. 7 jqmulti.module

Code for the jQuery Multi module.

File

jqmulti.module
View source
<?php

/**
 * @file 
 * Code for the jQuery Multi module.
 */

/**
 * Implements hook_menu().
 */
function jqmulti_menu() {
  $items = array();
  $items['admin/settings/jqmulti'] = array(
    'title' => t('jQuery Multi Settings'),
    'description' => t('Settings for jQuery Multi module'),
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'jqmulti_admin_form',
    ),
    'access arguments' => array(
      'access administration pages',
    ),
    'type' => MENU_NORMAL_ITEM,
    'file' => 'jqmulti.admin.inc',
  );
  return $items;
}

/**
 * Implements hook_jquery_update_alter().
 * This takes care of the alterations in the case that jQuery Update is installed.
 */
function jqmulti_jquery_update_alter(&$scripts) {
  $scripts = jqmulti_alter_scripts($scripts);
}

/**
 * Implements hook_theme_registry_alter().
 *
 * - If jQuery Update is not present, it makes sure our preprocess function runs
 *   after everything else. 
 * - If jQuery Update is present, it removes our preprocess function, so that 
 *   hook_jquery_update() can do the work.
 */
function jqmulti_theme_registry_alter(&$theme_registry) {
  if (isset($theme_registry['page'])) {
    if (count($theme_registry['page']['preprocess functions']) > 0) {

      // If our preprocess function is there already, remove it.
      if ($key = array_search('jqmulti_preprocess_page', $theme_registry['page']['preprocess functions'])) {
        unset($theme_registry['page']['preprocess functions'][$key]);
      }
    }

    // Now tack it on at the end so it runs after everything else.
    if (!module_exists('jquery_update')) {
      $theme_registry['page']['preprocess functions'][] = 'jqmulti_preprocess_page';
    }
  }
}

/**
 * Implements hook_preprocess_page().
 *
 * Rearrange the scripts and add the new jQuery (only runs if jQuery Update is not present).
 */
function jqmulti_preprocess_page(&$variables) {

  // Only do this for pages that have JavaScript on them.
  if (!empty($variables['scripts'])) {
    $scripts = drupal_add_js();
    $scripts = jqmulti_alter_scripts($scripts);
    $variables['scripts'] = drupal_get_js('header', $scripts);
  }
}

/**
 * This is where the magic happens. The new jQuery is added and noConflict() is run.
 * Finally, scripts are rearranged or added so that the targeted scripts run with
 * the newer jQuery.
 */
function jqmulti_alter_scripts($scripts) {
  $modulejs =& $scripts['module'];
  $options = array(
    'cache' => TRUE,
    'defer' => FALSE,
    'preprocess' => TRUE,
  );
  $prepend = array();
  $jquery = jqmulti_jquery_path();
  if (!$jquery) {
    return $scripts;
  }

  // Get info about which files are needed.
  $files = jqmulti_get_files();

  // Check if we need to add libraries even if they have not been explicitly added.
  if (!variable_get('jqmulti_load_libraries_always', FALSE)) {
    $files = array_intersect_key($files, $modulejs);
  }

  // If there are no files, check if we are to add jQuery anyway.
  if (empty($files)) {
    if (!variable_get('jqmulti_load_always', FALSE)) {
      return $scripts;
    }
  }

  // Add the new version of jQuery.
  $prepend[$jquery] = $options;

  // Rearrange JS array accordingly.
  foreach ($files as $file) {

    // add the files
    if (isset($modulejs[$file])) {
      $prepend[$file] = $modulejs[$file];
      unset($modulejs[$file]);
    }
    else {
      $prepend[$file] = $options;
    }
  }

  // Add the switch script to return jQuery to Drupal's default and save the new jQuery for later use.
  $switch = jqmulti_switch_path();
  $prepend[$switch] = $options;

  // Prepend the $prepend array.
  $modulejs = array_merge($prepend, $modulejs);
  return $scripts;
}

/**
 * Returns a list of files that should be loaded with the second jQuery.
 */
function jqmulti_get_files($reset = FALSE) {

  // We store the file list in cache, since it's not going to change much.
  if (!$reset && ($cache = cache_get('jqmulti_files'))) {
    return $cache->data;
  }
  else {

    // Build files array.
    $files = module_invoke_all('jqmulti_files');
    if (!empty($files)) {
      $files = array_combine($files, $files);
    }
    $libraries = module_invoke_all('jqmulti_libraries');

    // Get also any libraries added by UI.
    $ui_libs = variable_get('jqmulti_libraries', array());
    foreach ($ui_libs as $ui_lib => $on) {
      if ($on && !in_array($ui_lib, $libraries)) {
        $libraries[] = $ui_lib;
      }
    }

    // Add library files.
    foreach ($libraries as $library) {
      $files = array_merge($files, jqmulti_get_library_files($library));
    }
    cache_set('jqmulti_files', $files);
    return $files;
  }
}

/**
 * Returns a list of files for a given library.
 * This is not a part of Libraries API for D6.
 */
function jqmulti_get_library_files($library, $reset = FALSE) {
  $base_path = 'sites/all/libraries';
  $path = $base_path . '/' . $library;

  // check whether list of files is in cache
  if (!$reset && ($cache = cache_get('jqmulti_files_' . $library))) {
    return $cache->data;
  }

  // find list of js files for that library
  $files = jqmulti_find_all_js_files($path);
  cache_set('jqmulti_files_' . $library, $files);
  return $files;
}

/**
 * Returns available libraries to be used in the admin form.
 */
function jqmulti_get_available_libraries() {
  $libs = libraries_get_libraries();
  unset($libs['jquery']);
  foreach ($libs as $key => $value) {
    $libs[$key] = $key;
  }
  return $libs;
}

/**
 * Returns the path to the switch script.
 */
function jqmulti_switch_path() {
  return drupal_get_path('module', 'jqmulti') . '/js/switch.js';
}

/**
 * Returns the path to the currently selected version of jQuery.
 */
function jqmulti_jquery_path() {
  $version = jqmulti_get_version();
  if ($version) {
    return libraries_get_path('jquery') . '/jquery-' . $version . '.min.js';
  }
  return FALSE;
}

/**
 * Recursive function that returns a list of all JS files in a directory.
 * @param $dir the full path to the directory
 */
function jqmulti_find_all_js_files($dir) {
  $result = array();
  $root = scandir($dir);
  foreach ($root as $value) {
    if ($value === '.' || $value === '..') {
      continue;
    }
    $path = "{$dir}/{$value}";
    if (is_file($path)) {
      if (preg_match('/.js$/', $value)) {
        $result[$path] = $path;
      }
      continue;
    }
    foreach (jqmulti_find_all_js_files($path) as $value) {
      $result[$value] = $value;
    }
  }
  return $result;
}

/**
 * Gets the version of jQuery to load.
 * @param $reset whether to reset the cached version number
 */
function jqmulti_get_version($reset = FALSE) {
  if (!$reset && ($cache = cache_get('jqmulti_version'))) {
    return $cache->data;
  }
  else {
    $libraries = libraries_get_libraries();
    if (isset($libraries['jquery'])) {
      $files = jqmulti_get_library_files('jquery', TRUE);
      if ($files) {
        foreach ($files as $file) {

          // Get the file name.
          $version = jqmulti_jquery_version_from_path($file);
          if ($version) {
            cache_set('jqmulti_version', $version);
            return $version;
          }
        }
      }
    }
  }
  return FALSE;
}

/**
 * Gets the jQuery version from the properly formatted filename.
 * @param $path the full path to the jQuery library file
 */
function jqmulti_jquery_version_from_path($path) {
  $parts = explode('/', $path);
  $filename = array_pop($parts);
  $matches = array();
  preg_match('/jquery-(.*)\\.min\\.js/', $filename, $matches);
  if (count($matches) == 2) {
    return $matches[1];
  }
  else {
    return FALSE;
  }
}

Functions

Namesort descending Description
jqmulti_alter_scripts This is where the magic happens. The new jQuery is added and noConflict() is run. Finally, scripts are rearranged or added so that the targeted scripts run with the newer jQuery.
jqmulti_find_all_js_files Recursive function that returns a list of all JS files in a directory.
jqmulti_get_available_libraries Returns available libraries to be used in the admin form.
jqmulti_get_files Returns a list of files that should be loaded with the second jQuery.
jqmulti_get_library_files Returns a list of files for a given library. This is not a part of Libraries API for D6.
jqmulti_get_version Gets the version of jQuery to load.
jqmulti_jquery_path Returns the path to the currently selected version of jQuery.
jqmulti_jquery_update_alter Implements hook_jquery_update_alter(). This takes care of the alterations in the case that jQuery Update is installed.
jqmulti_jquery_version_from_path Gets the jQuery version from the properly formatted filename.
jqmulti_menu Implements hook_menu().
jqmulti_preprocess_page Implements hook_preprocess_page().
jqmulti_switch_path Returns the path to the switch script.
jqmulti_theme_registry_alter Implements hook_theme_registry_alter().