jqp.module in jQuery Plugin Handler (JQP) 6.2
Same filename and directory in other branches
Used to register and load javascript libraries and plugins from a cetral point
File
jqp.moduleView source
<?php
/**
* @file
* Used to register and load javascript libraries and plugins from a cetral point
*/
/**
* Implementation of hook_help().
*/
function jqp_help($path, $arg) {
switch ($path) {
case 'admin/help#jqp':
$output[] = '<p>' . t('Javascript libraries can either be built up from an single javascript file, a javascript plugin or a set of javascript files, sometimes with stylesheets included. These libraries can be used to extend the look and feel of modules.') . '</p>';
$output[] = '<p>' . t('Libraries can be registered in several ways:') . '</p>';
$output[] = '<ul>';
$output[] = ' <li>';
$output[] = '<h4>' . t('.info files') . '</h4>';
$output[] = '<p>' . t('This is the preferred way of registering a library into javascript libraries\' cache. During installation, jQp module will check for the presence of a js_libraries folder in one of the following directories:') . '</p>';
$output[] = '<ul>';
$output[] = ' <li>js_libraries</li>';
$output[] = ' <li>sites/all/js_libraries</li>';
$output[] = ' <li>$profile/install_profile/js_libraries</li>';
$output[] = ' <li>$conf_path/js_libraries</li>';
$output[] = ' <li>$file_directory_path/js_libraries</li>';
$output[] = '</ul>';
$output[] = '<p>' . t('If this directory exists, this should be the place to place all libraries as separate folders, containing all required files for the library. If a library folder contains a .info file, this will be used to register the library. Here\'s an example of how a .info file should be written:', $replacements) . '</p>';
$output[] = '<pre>';
$output[] = '; $Id$';
$output[] = 'name = Library Name';
$output[] = 'description = Description of the library';
$output[] = 'project_url = http://www.library_project_page.org';
$output[] = 'stylesheets[][] = style.css';
$output[] = 'scripts[][] = jquery.test.min.js';
$output[] = 'scripts[1.4.4][] = jquery.test[1.4.4].min.js';
$output[] = 'scripts[1.4.4][] = drupal.js';
$output[] = '</pre>';
$output[] = '<p>' . t('This .info file will register two versions of this library (default and 1.4.4). style.css is added as a first element of the stylesheets array, and will therefore will have 0 as key. All elements of both the stylesheets and scripts array with a 0 key will be treated as the default version. Files with other keys, such as 1.4.4, will be handled as separate versions. If a specific version of a library is loaded, and there\'s no file type which overrides the default one, the default one is included automatically. Note that versions can include several files!') . '</p>';
$output[] = '</li>';
$output[] = '<li>';
$output[] = '<h4>' . t('hook_jqp()') . '</h4>';
$output[] = '<p>' . t('Modules can also register their own libraries using the provided hook function.') . '</p>';
$output[] = '<p><strong>' . t('Definition') . ':</strong></p>';
$output[] = '<p><code>hook_jqp(&$js_libraries)</code></p>';
$output[] = '<p><strong>' . t('Description') . ':</strong></p>';
$output[] = '<p>' . t('Provide other modules a hook to add custom libraries or alter already registered libraries.') . '</p>';
$output[] = '<p><strong>' . t('Parameters') . ':</strong></p>';
$output[] = '<p><code>$js_libraries</code>: ' . t('An associative array in which the library register is built up.') . '</p>';
$output[] = '<p><strong>' . t('Code') . ':</strong></p>';
$output[] = '<pre class="php">';
$output[] = '/**';
$output[] = ' * Implemantation of hook_jqp().';
$output[] = ' */';
$output[] = 'function hook_jqp(&$js_libraries) {';
$output[] = ' $js_libraries[\'plugin1\'] = array(';
$output[] = ' \'name\' => \'Plugin 1\',';
$output[] = ' \'description\' => \'This plugin is registered by a module.\',';
$output[] = ' \'project_url\' => \'http://www.library_project_page.org\',';
$output[] = ' \'scripts\' => array(';
$output[] = ' array(\'jquery.hoi.min.js\'), // This will have key 0, so it is the default version';
$output[] = ' \'1.4.3-BETA-3\' => array(\'jquery.hoi[2].min.js\'),';
$output[] = ' ),';
$output[] = ' \'stylesheets\' => array(';
$output[] = ' array(\'plugin1.css\'),';
$output[] = ' \'1.4.3-BETA-3\' => array(';
$output[] = ' \'plugin1[1.4.3-BETA-3].css\'';
$output[] = ' ),';
$output[] = ' ),';
$output[] = ' );';
$output[] = '}';
$output[] = '</pre>';
$output[] = '</li>';
$output[] = '<li>';
$output[] = '<h4>' . t('Loading a javascript library') . '</h4>';
$output[] = '<p>' . t('Loading a javascript library or plugin can be done using drupal_add_js_library().') . '</p>';
$output[] = '<p><strong>' . t('Definition') . ':</strong></p>';
$output[] = '<p><code>drupal_add_js_library($name, $version = 0, $options = array())</code></p>';
$output[] = '<p><strong>' . t('Description') . ':</strong></p>';
$output[] = '<p>' . t('Load a shared library from the javascript library directory.') . '</p>';
$output[] = '<p><strong>' . t('Parameters') . ':</strong></p>';
$output[] = '<p><code>$name</code>: ' . t('(required)') . " " . t('the name of the library or plugin to load.') . '</p>';
$output[] = '<p><code>$version</code>: ' . t('(optional)') . " " . t('the version of the library to load. If omitted the default version is loaded.') . '</p>';
$output[] = '<p><code>$options</code>: ' . t('(optional)') . " " . t('Array containing additional options to pass to drupal_add_js or drupal_add_css.') . '</p>';
$output[] = '<pre class="php">';
$output[] = ' array(';
$output[] = ' \'css\' => array($type = \'module\', $media = \'all\', $preprocess = TRUE),';
$output[] = ' \'js\' => array($type = \'module\', $scope = \'header\', $defer = FALSE, $cache = TRUE, $preprocess = TRUE),';
$output[] = ' );';
$output[] = '</pre>';
$output[] = '<p><strong>' . t('Example') . ':</strong></p>';
$output[] = '<p><code>drupal_add_js_library(\'beautytips\', \'0.9\', array(\'css\' => array(\'theme\', \'all\', FALSE)));</code></p>';
$output[] = '</li>';
$output[] = '<li>';
$output[] = '<h4>' . t('Administration pages') . '</h4>';
$output[] = '<p>' . t('After registering a library, the paths of the attached files can be changed at the !admin_pages. It is also possible to attach an detach files per version.', array(
'!admin_pages' => l('administration pages', 'admin/build/jqp'),
)) . '</p>';
$output[] = '</li>';
$output[] = '</ul>';
return join("\n", $output);
case 'admin/build/jqp':
$output[] = '<p>' . t('Javascript libraries can either be built up from an single javascript file, a javascript plugin or a set of javascript files, sometimes with stylesheets included. These libraries can be used to extend the look and feel of modules.') . '</p>';
$output[] = '<p>' . t('After registering a library, the paths of the attached files can be changed here. It is also possible to attach and detach files per version by clicking on the configure link.') . '</p>';
$output[] = '<p>' . t('You can completely rebuild the cache by clicking !rebuild link.', array(
'!rebuild' => l(t('this'), 'admin/build/jqp/rebuild_confirm'),
)) . '</p>';
return join("\n", $output);
}
}
/**
* Implementation of hook_perm().
*/
function jqp_perm() {
return array(
'administer javascript libraries',
);
}
/**
* Implementation of hook_menu().
*/
function jqp_menu() {
$items['admin/build/jqp'] = array(
'title' => 'Javascript libraries',
'description' => "Administer javascript libraries.",
'page callback' => 'jqp_status_page',
'access arguments' => array(
'administer javascript libraries',
),
'file' => 'jqp.admin.inc',
);
$items['admin/build/jqp/rebuild_confirm'] = array(
'title' => 'Reset all libraries',
'page callback' => 'drupal_get_form',
'page arguments' => array(
'jqp_confirm_form',
),
'access arguments' => array(
'administer javascript libraries',
),
'type' => MENU_CALLBACK,
'file' => 'jqp.admin.inc',
);
$items['admin/build/jqp/%js_library/%'] = array(
'title callback' => 'jqp_overview_title',
'title arguments' => array(
3,
4,
),
'page callback' => 'drupal_get_form',
'page arguments' => array(
'js_library_edit',
3,
4,
),
'access arguments' => array(
'administer javascript libraries',
),
'type' => MENU_CALLBACK,
'file' => 'jqp.admin.inc',
);
$items['admin/build/jqp/%js_library/%/list'] = array(
'title' => 'List files',
'type' => MENU_DEFAULT_LOCAL_TASK,
'weight' => -10,
'file' => 'jqp.admin.inc',
);
$items['admin/build/jqp/%js_library/%/reset'] = array(
'title' => 'Reset library',
'page callback' => 'drupal_get_form',
'page arguments' => array(
'jqp_confirm_form',
3,
4,
),
'access arguments' => array(
'administer javascript libraries',
),
'type' => MENU_CALLBACK,
'file' => 'jqp.admin.inc',
);
$items['admin/build/jqp/%js_library/%/remove_file'] = array(
'title' => 'Reset library',
'page callback' => 'drupal_get_form',
'page arguments' => array(
'jqp_confirm_form',
3,
4,
),
'access arguments' => array(
'administer javascript libraries',
),
'type' => MENU_CALLBACK,
'file' => 'jqp.admin.inc',
);
$items['admin/build/jqp/%js_library/%/add'] = array(
'title' => 'Add file',
'page callback' => 'drupal_get_form',
'page arguments' => array(
'js_library_edit',
3,
4,
5,
),
'access arguments' => array(
'administer javascript libraries',
),
'type' => MENU_LOCAL_TASK,
'file' => 'jqp.admin.inc',
);
$items['jqp_ajax_check_file'] = array(
'page callback' => '_jqp_ajax_check_file',
'access arguments' => array(
'administer javascript libraries',
),
'type' => MENU_CALLBACK,
'file' => 'jqp.admin.inc',
);
$items['jqp_autocomplete'] = array(
'page callback' => '_jqp_autocomplete',
'access arguments' => array(
'administer javascript libraries',
),
'type' => MENU_CALLBACK,
'file' => 'jqp.admin.inc',
);
return $items;
}
/**
* Implementation of hook_theme().
*/
function jqp_theme() {
return array(
'js_library_edit' => array(
'arguments' => array(
'form' => array(),
'js_library' => array(),
'version' => 0,
),
),
);
}
/**
* Title callback.
*/
function jqp_overview_title($js_library, $version = NULL) {
return $js_library->info['name'] . ($version ? " v.{$version}" : "");
}
/**
* Add a shared library from the javascript library directory
*
* @param $name
* the name of the library to add
*
* @param $version
* the version of the library to add
*
* @param $options
* Array containing additional options to pass to drupal_add_js or drupal_add_css.
* array(
* 'css' => array($path = NULL, $type = 'module', $media = 'all', $preprocess = TRUE),
* 'js' => array($data = NULL, $type = 'module', $scope = 'header', $defer = FALSE, $cache = TRUE, $preprocess = TRUE),
* );
*
* @see drupal_add_js()
* @see drupal_add_css()
*/
function drupal_add_js_library($name, $version = 0, $options = array()) {
// Get the library
$js_library = js_library_load($name);
$types = array(
'js' => 'scripts',
'css' => 'stylesheets',
);
$files = array();
// Loop trough the file types
foreach ($types as $key => $type) {
// Add the files of the default version, if exist
if ($version !== 0 && is_array($js_library->info[$type][0])) {
$files[$key] = $js_library->info[$type][0];
}
if (is_array($js_library->info[$type][$version])) {
$files[$key] = $js_library->info[$type][$version];
}
}
// Load all files using drupal_add_js and drupal_add_css
foreach ($types as $key => $type) {
if (!$files[$key]) {
continue;
}
foreach ($files[$key] as $path) {
//trace("$path $key");
$args[0] = $path;
$args = array_merge($args, $options);
call_user_func_array("drupal_add_{$key}", $args);
}
}
}
/**
* Scan the 'js_libraries', 'modules' and 'themes' directories for .js and .css files
*
* @return an array where key is file name and value is file path
*
* Example:
* array('sites/all/modules/cck/content.js' => (object)array(
* 'filename' => 'sites/all/modules/cck/content.js',
* 'basename' => 'content.js',
* 'name' => 'content',
* );
*
* LIKE MODULES, javascript libraries should have unique file names
*
* @see _jqp_autocomplete()
*/
function jqp_scan_dir() {
static $files;
if (!isset($files)) {
if ($cache = cache_get('jqp')) {
$files = $cache->data;
}
else {
$profile = variable_get('install_profile', 'default');
$config = conf_path();
$file_dir = file_directory_path();
$files = array();
foreach (array(
'modules',
'js_libraries',
'themes',
) as $directory) {
$searchdir[] = "{$directory}";
$searchdir[] = "sites/all/{$directory}";
$searchdir[] = "profiles/{$profile}/{$directory}";
$searchdir[] = "{$config}/{$directory}";
$searchdir[] = "{$file_dir}/{$directory}";
}
foreach ($searchdir as $dir) {
if (file_exists($dir)) {
$files = array_merge($files, file_scan_directory($dir, '(\\.js$|\\.css$)', array(
'.',
'..',
'CVS',
), 0, TRUE, 'filename', 0));
}
}
cache_set('jqp', $files);
}
}
return $files;
}
/**
* Implementation of hook_requirements().
*
* Checks if a js_libraries directory is present at install
*/
function jqp_requirements($phase) {
// Ensure translations don't break at install time
$t = get_t();
// Report Drupal version
if ($phase == 'runtime') {
$library_exists = _check_js_library_directory('js_libraries');
$requirements['jqp'] = array(
'title' => $t('Javascript libraries directory'),
'value' => $library_exists ? $t('Exists') : $t('Not present'),
'severity' => $library_exists ? REQUIREMENT_OK : REQUIREMENT_WARNING,
);
if (!$library_exists) {
$requirements['jqp']['description'] = $t('There\'s no javascript libraries folder present yet! Please create a directory called "js_libraries" at sites/all/js_libraries or sites/[example.com]/js_libraries or similar.');
}
}
return $requirements;
}
/**
* Searches for a js_libraries directory
*/
function _check_js_library_directory($directory) {
global $profile;
$config = conf_path();
$searchdir = array(
"{$directory}",
"sites/all/{$directory}",
"profiles/{$profile}/{$directory}",
"{$config}/{$directory}",
);
foreach ($searchdir as $dir) {
if (file_exists($dir)) {
variable_set('jqp_directory', $dir);
return TRUE;
}
}
return FALSE;
}
/**
* Rebuilds the javascript libraries cache.
*
* It registers both all libraries defined in library info files,
* as well as libraries defined in hook_jqp.
*
* @param $reset
* If true, all javascript libraries are completely reindexed.
* Otherwise only libraries which havent been costumized by administrators are reindexed.
*/
function jqp_rebuild_cache($reset = FALSE) {
cache_clear_all('jqp', 'cache');
// Set defaults for library info
$defaults = array(
'description' => '',
'version' => NULL,
);
// The following code is merely copied from drupal_system_listing.
// Added the file_directory to be a possible location for the library directory.
$profile = variable_get('install_profile', 'default');
$directory = 'js_libraries';
$config = conf_path();
$file_dir = file_directory_path();
$js_libraries = array();
$searchdir = array(
"{$directory}",
"sites/all/{$directory}",
"profiles/{$profile}/{$directory}",
"{$config}/{$directory}",
"{$file_dir}/{$directory}",
);
// Get current list of libraries registerd by dot-info files
foreach ($searchdir as $dir) {
if (file_exists($dir)) {
$js_libraries = array_merge($js_libraries, file_scan_directory($dir, '\\.info$', array(
'.',
'..',
'CVS',
), 0, TRUE, 'name', 0));
}
}
// Get all libraries registerd by modules
$module_libraries = module_invoke_all('jqp');
if (is_array($module_libraries)) {
foreach ($module_libraries as $module_library_name => $module_library) {
$js_libraries[$module_library_name] = (object) ($module_library + array(
'type' => 'javascript library',
));
}
}
// Extract current files from database.
system_get_files_database($js_libraries, 'javascript library');
ksort($js_libraries);
foreach ($js_libraries as $name => $library) {
$versions_changed = array();
// Look for the info file.
$library->info = drupal_parse_info_file(dirname($library->filename) . '/' . $library->name . '.info');
// If the library doesn't provide info, we're dealing with an module registered library.
// We'll create the info manually.
if (empty($library->info)) {
$info = clone $library;
unset($info->type, $info->info, $js_libraries[$name]->scripts, $js_libraries[$name]->styles);
$js_libraries[$name]->info = (array) $info;
$js_libraries[$name]->name = $name;
$js_libraries[$name]->filename = "{$name}-module-jqp";
}
// Merge in defaults and save.
$js_libraries[$name]->info = $library->info + $defaults;
// Used to merge saved data with loaded data
$old_library = js_library_load($name);
// Loop trough each file type
foreach (array(
'stylesheets',
'scripts',
) as $type) {
// Continue if no data is found for this file type
if (empty($js_libraries[$name]->info[$type])) {
continue;
}
$files = array();
// Get the data of each file type per version
foreach ($js_libraries[$name]->info[$type] as $version => $data) {
// Check whether this version have been madified and saved before
if (isset($old_library->info[$type][$version]['changed']) && $reset === FALSE) {
$versions_changed[] = $version;
}
foreach ($data as $file_name) {
$dirname = file_exists($js_libraries[$name]->filename) ? dirname($js_libraries[$name]->filename) : '';
$files[$version][$file_name] = $dirname ? "{$dirname}/{$file_name}" : $file_name;
// Let's store the basepath of the dot-info file
$library->info['base'] = $dirname ? $dirname : NULL;
}
}
$js_libraries[$name]->info[$type] = $files;
}
if (!empty($versions_changed)) {
foreach ($versions_changed as $version_changed) {
if (isset($js_libraries[$name]->info['scripts'][$version_changed])) {
$js_libraries[$name]->info['scripts'][$version_changed] = $old_library->info['scripts'][$version_changed];
}
if (isset($js_libraries[$name]->info['stylesheets'][$version_changed])) {
$js_libraries[$name]->info['stylesheets'][$version_changed] = $old_library->info['stylesheets'][$version_changed];
}
}
}
// Invoke hook_system_info_alter() to give installed modules a chance to
// modify the data in the .info files if necessary.
drupal_alter('system_info', $js_libraries[$name]->info, $js_libraries[$name]);
// Update the contents of the system table:
if (isset($library->status) || isset($library->old_filename) && $library->old_filename != $library->filename) {
db_query("UPDATE {system} SET info = '%s', name = '%s', filename = '%s', bootstrap = %d WHERE filename = '%s'", serialize($js_libraries[$name]->info), $library->name, $library->filename, $bootstrap, $library->old_filename);
}
else {
// This is a new library.
db_query("INSERT INTO {system} (name, info, type, filename, status, throttle, bootstrap) VALUES ('%s', '%s', '%s', '%s', %d, %d, %d)", $name, serialize($js_libraries[$name]->info), 'javascript library', $js_libraries[$name]->filename, 0, 0, $bootstrap);
}
}
return $js_libraries;
}
/**
* Fetches all cached libraries from the system table
*/
function jqp_list($refresh = FALSE) {
static $list;
if ($refresh) {
$list = array();
}
if (empty($list)) {
$list = array();
$js_libraries = array();
$result = db_query("SELECT * FROM {system} WHERE type = '%s'", 'javascript library');
while ($library = db_fetch_object($result)) {
$library->info = unserialize($library->info);
$js_libraries[] = $library;
foreach (array(
'stylesheets',
'scripts',
) as $type) {
if (empty($library->info[$type])) {
continue;
}
foreach ($library->info[$type] as $version => $data) {
foreach ($data as $file_name => $path) {
if (file_exists($path)) {
$library->{$type}[$version][$file_name] = $path;
}
}
}
}
$list[$library->name] = $library;
}
}
return $list;
}
/**
* Loads a single library
*
* @param $name
* the name of the library to add
*/
function js_library_load($name) {
static $js_libraries;
if (empty($js_libraries)) {
$js_libraries = jqp_list();
}
return $js_libraries[$name];
}
/**
* Implementation of hook_jqp().
*
* ONLY FOR TESTING PURPOSES!!!
*/
function jqp_jqp() {
$js_libraries['dummy_plugin1'] = array(
'name' => 'Dummy plugin 1',
'description' => 'This plugin is registered by the jqp module.',
'project_url' => 'http://www.library_project_page.org',
'scripts' => array(
array(
'jquery.dummy.min.js',
),
'1.4.3-BETA-3' => array(
'jquery.dummy[1.4.3-BETA-3].min.js',
),
),
'stylesheets' => array(
array(
'styles.css',
),
'1.4.3-BETA-3' => array(
'styles[1.4.3-BETA-3].css',
),
),
);
$js_libraries['dummy_plugin2'] = array(
'name' => 'Dummy plugin 2',
'description' => 'This plugin is also registered by the jqp module.',
'project_url' => 'http://www.library_project_page.org',
'scripts' => array(
array(
'jquery.dummy2.min.js',
),
'2' => array(
'jquery.dummy2[2].min.js',
),
),
);
return $js_libraries;
}
Functions
Name![]() |
Description |
---|---|
drupal_add_js_library | Add a shared library from the javascript library directory |
jqp_help | Implementation of hook_help(). |
jqp_jqp | Implementation of hook_jqp(). |
jqp_list | Fetches all cached libraries from the system table |
jqp_menu | Implementation of hook_menu(). |
jqp_overview_title | Title callback. |
jqp_perm | Implementation of hook_perm(). |
jqp_rebuild_cache | Rebuilds the javascript libraries cache. |
jqp_requirements | Implementation of hook_requirements(). |
jqp_scan_dir | Scan the 'js_libraries', 'modules' and 'themes' directories for .js and .css files |
jqp_theme | Implementation of hook_theme(). |
js_library_load | Loads a single library |
_check_js_library_directory | Searches for a js_libraries directory |