You are here

js_injector.module in JS injector 8

js_injector.module

Allows administrators to inject JavaScript into the page output based on configurable rules. Useful for adding simple JavaScript tweaks without modifying a site's official theme.

File

js_injector.module
View source
<?php

/**
 * @file js_injector.module
 *
 * Allows administrators to inject JavaScript into the page output based on
 * configurable rules. Useful for adding simple JavaScript tweaks without
 * modifying a site's official theme.
 */

/**
 * Implements hook_help().
 */
function js_injector_help($path, $arg) {
  $output = '';
  switch ($path) {
    case 'admin/config/development/js-injector':
      $output .= '<p>' . t('Use JavaScript injector rules to add small snippets of JavaScript to the page output when specific criteria are met. For example, a simple rule could change the page background color at night or float a particular div to the right on node editing pages.') . '</p>';
      break;
  }
  return $output;
}

/**
 * Implements hook_permission().
 */
function js_injector_permission() {
  return array(
    'administer js_injector' => array(
      'title' => t('Administer JS injector'),
      'description' => t('Create and delete JS snippets for the site.'),
      'restrict access' => TRUE,
    ),
  );
}

/**
 * Loads the data for a js_injector rule.
 *
 * @param $id
 *   The machine-name of the js_injector rule to load.
 *
 * @return object
 *   If the js_injector rule set exists, an object containing the following
 *   properties:
 *   - 'id': The internal name of the rule.
 *   - 'label': The title of the rule.
 *   If the js_injector rule does not exist, the function returns NULL.
 */
function js_injector_rule_load($id) {
  return entity_load('js_injector_rule', $id);
}

/**
 * Implements hook_page_build().
 *
 * Checks to see whether any JS files should be added to the current page,
 * based on rules configured by the site administrator.
 */
function js_injector_page_build(&$page) {

  // Load all the js_injector rules. These are loaded automatically by weight.
  $rules = entity_load_multiple('js_injector_rule');
  foreach ($rules as $id => $rule) {

    // Check if the rule is disabled in the administrative UI.
    if ($rule->status == FALSE) {
      continue;
    }

    // Check the page visibility settings.
    if (_js_injector_visibility_pages($rule) == FALSE) {
      continue;
    }

    // Add the JavaScript to the page.
    $code = $rule->inline == 1 ? $rule->js : _js_injector_rule_path($id);
    $page['#attached']['js'][$code] = array(
      'type' => $rule->inline == 1 ? 'inline' : 'file',
      'scope' => $rule->position,
      // this group has the highest weight
      'group' => JS_THEME,
      'every_page' => FALSE,
      // safe guard to ensure inline files are never preprocessed
      'preprocess' => $rule->inline == 1 ? FALSE : $rule->preprocess,
      // since we're trying to give the administrator complete control, we'll
      // move JS that this module has added to a high weight, higher even than
      // the theme's JS files. Currently the weight is 250 + the weight, which
      // is currently higher than Bartik's JS.
      'weight' => 250 + $rule->weight,
    );
  }
}

/**
 * Based on visibility setting this function returns TRUE if the JS injector
 * rule code should be added to the current page and otherwise FALSE.
 *
 * Code ported from googleanalytics.module
 */
function _js_injector_visibility_pages($rule) {
  $visibility = $rule->page_visibility;
  $setting_pages = $rule->page_visibility_pages;

  // Match path if necessary.
  if (!empty($setting_pages)) {

    // Convert path to lowercase. This allows comparison of the same path
    // with different case. Ex: /Page, /page, /PAGE.
    $pages = drupal_strtolower($setting_pages);
    if ($visibility < 2) {

      // Convert the Drupal path to lowercase.
      $path = drupal_strtolower(request_path());

      // Compare the lowercase internal and lowercase path alias (if any).
      $page_match = drupal_match_path($path, $pages);
      if ($path != current_path()) {
        $page_match = $page_match || drupal_match_path(current_path(), $pages);
      }

      // When $visibility has a value of 0, the tracking code is displayed on
      // all pages except those listed in $pages. When set to 1, it
      // is displayed only on those pages listed in $pages.
      $page_match = !($visibility xor $page_match);
    }
    else {
      $page_match = FALSE;
    }
  }
  else {
    $page_match = TRUE;
  }
  return $page_match;
}

/**
 * Helper function to get file path for a rule.
 * This will get the path relative to DRUPAL_ROOT,
 * as in 'sites/default/files/js_injector/js_[id].js'.
 *
 * @param $id
 *   The js_injector rule machine name
 */
function _js_injector_rule_path($id) {
  $local_path = file_create_url(_js_injector_rule_uri($id));

  // Now remove the part before the drupal root.
  $local_path = preg_replace('/^' . preg_quote($GLOBALS['base_url'], '/') . '\\//', '', $local_path);
  return $local_path;
}

/**
 * Return the URI for a given rule name.
 *
 * @param $id
 *   The js_injector rule machine name
 */
function _js_injector_rule_uri($id) {
  if (!empty($id)) {
    return file_default_scheme() . '://js_injector/js_' . $id . '.js';
  }
}

Functions

Namesort descending Description
js_injector_help Implements hook_help().
js_injector_page_build Implements hook_page_build().
js_injector_permission Implements hook_permission().
js_injector_rule_load Loads the data for a js_injector rule.
_js_injector_rule_path Helper function to get file path for a rule. This will get the path relative to DRUPAL_ROOT, as in 'sites/default/files/js_injector/js_[id].js'.
_js_injector_rule_uri Return the URI for a given rule name.
_js_injector_visibility_pages Based on visibility setting this function returns TRUE if the JS injector rule code should be added to the current page and otherwise FALSE.