'; } if ($section == 'admin/settings/dynamicload') { $return[] = t('

Full dynamic loading is experimental and may break sites at this point. The options on this page are not recommended for use on production sites. Work is ongoing to identify and fix remaining issues.

Configure dynamic loading of individual blocks on the block configuration pages.

', array('@config' => url('admin/build/block'))); } if (!empty($return)) { return implode('', $return); } } /** * Implementation of hook_menu(). */ function dynamicload_menu($may_cache) { $items = array(); if ($may_cache) { $items[] = array( 'path' => 'dynamicload/js', 'title' => t('Dynamicload page'), 'access' => user_access('access content'), 'type' => MENU_CALLBACK, 'callback' => 'dynamicload_js', ); $items[] = array( 'path' => 'dynamicload/block', 'title' => t('Dynamicload block'), 'access' => user_access('access content'), 'type' => MENU_CALLBACK, 'callback' => 'dynamicload_fetch_block', ); $items[] = array( 'path' => 'admin/settings/dynamicload', 'title' => t('Dynamicload'), 'description' => t('Configuration for dynamic loading'), 'callback' => 'drupal_get_form', 'callback arguments' => array('dynamicload_admin_settings') ); } else { /* if (isset($_COOKIE['has_js']) && $_COOKIE['has_js'] && variable_get('dynamicload_all', 0)) { // If we are on a page other than home, go home, with this page as an anchor/hash. if (!isset($_SESSION['dynamicload_path']) && !drupal_is_front_page() && arg(0) != 'dynamicload') { $query = $_GET; unset($query['q']); $querystring = array(); foreach ($query as $key => $value) { $querystring[] = $key .'='. $value; } $path = drupal_get_path_alias($_GET['q']); $_SESSION['dynamicload_path'] = $path; drupal_goto('', implode('&', $querystring), $path); } elseif (isset($_SESSION['dynamicload_path']) && !(isset($_SESSION['dynamicload_path']) && $_SESSION['dynamicload_path_active'])) { $_SESSION['dynamicload_path_active'] = TRUE; $path = $_SESSION['dynamicload_path']; $_GET['q'] = drupal_get_normal_path($path); _menu_append_contextual_items(); menu_set_active_item($path); unset($_SESSION['dynamicload_path_active']); unset($_SESSION['dynamicload_path']); } } */ dynamicload_load(); } return $items; } /** * Admin settings. */ function dynamicload_admin_settings() { $form = array(); $form['jstools_history_remote'] = array( '#type' => 'radios', '#title' => t('History plugin'), '#description' => t('Load the history_remote plugin, which ties dynamic loading to browser history. Dynamicload will be missing some functionality if this is disabled. However, the plugin can cause errors in combination with certain other Javascript functionality. Disable to avoid such errors. Note that disabling this setting will affect other modules if you enable them: Active Search and Tabs.'), '#default_value' => variable_get('jstools_history_remote', 0), '#options' => array(t('disabled'), t('enabled')), ); $form['dynamicload_all'] = array( '#type' => 'checkbox', '#title' => t('Process all links for dynamic loading'), '#description' => t('Check this option to make all links on the page dynamically load into the main content area. Links processed through block configuraiton will be skipped. You can also configure by paths, below.'), '#default_value' => variable_get('dynamicload_all', 0), ); $form['dynamicload_paths_type'] = array( '#type' => 'radios', '#title' => t('Path processing'), '#options' => array(t('Apply dynamic loading to all links except those to the listed pages.'), t('Apply dynamic loading only on links to the listed pages.')), '#default_value' => variable_get('dynamicload_paths_type', 0), ); $form['dynamicload_paths'] = array( '#type' => 'textarea', '#title' => t('Paths'), '#default_value' => variable_get('dynamicload_paths', 'admin*'), '#description' => t("Enter one page per line as Drupal paths. The '*' character is a wildcard. Example paths are %blog for the blog page and %blog-wildcard for every personal blog and %admin for all admin pages. Put the wildcard at the both ends of a path fragment to match any path containing that fragment. The front page is automatically skipped.", array('%blog' => 'blog', '%blog-wildcard' => 'blog/*', '%admin' => 'admin*')), ); include_once(drupal_get_path('module', 'dynamicload') .'/paths.inc'); $paths = module_invoke_all('dynamicload_paths'); if (is_array($paths) && !empty($paths)) { $form['dynamicload_paths']['#description'] .= t(' If Path processing is set to "Apply dynamic loading to all links except those to the listed pages" above, the following paths will be used automatically and so don\'t need to be entered here: %paths.', array('%paths' => implode(', ', $paths))); } $form['dynamicload_regions'] = array( '#type' => 'checkboxes', '#title' => t('Load region data'), '#description' => t('If you wish to refresh block regions with page loads, select the regions here. Only selected regions will be loaded.'), '#options' => system_region_list(variable_get('theme_default', 'garland')), '#default_value' => variable_get('dynamicload_regions', array()), ); $form = system_settings_form($form); return $form; } /** * Load needed files. */ function dynamicload_load() { static $loaded = FALSE; if (!$loaded) { jstools_modules_includes('dynamicload'); $path = drupal_get_path('module', 'dynamicload'); jstools_add_js(array( $path . '/dynamicload.js', 'misc/progress.js', )); drupal_add_js(drupal_get_path('module', 'jstools') . '/jquery.history_remote.pack.js'); // Insert dummy content that will be used to select the region container. // We need to manually set the left and right _dynamicload_set_region_markers(array('left', 'right')); drupal_add_css(drupal_get_path('module', 'block') .'/block.css'); $loaded = TRUE; } } /** * Send settings to the browser. * * We do this in the footer because some of the settings are theme-dependent. Typically, * hook_footer will be called after the theme is initiated, so we have the correct theme * to load data for. */ function dynamicload_footer() { global $theme; static $loaded = FALSE; if (!$loaded) { // Insert dummy content that will be used to select the region container. $regions = array_keys(system_region_list($theme)); // The left and right regions are handled separately in dynamicload_load(). unset($regions['left'], $regions['right']); _dynamicload_set_region_markers($regions); $settings = dynamicload_block_data(); foreach (module_invoke_all('dynamicload') as $setting) { $settings = array_merge($settings, $setting); } // Allow theme-based overrides. $theme_data = module_invoke('jstools', 'theme_data', 'dynamicload'); if (is_array($theme_data)) { foreach ($theme_data as $key => $selector) { if ($source = array_search($key, $settings)) { $settings[$source] = $selector; } // No theme support, unset. else { unset($settings[$source]); } } } $paths_type = variable_get('dynamicload_paths_type', 0); // Send both admin-configured and module-produced paths. $paths = variable_get('dynamicload_paths', 'admin*'); if ($paths_type == 0) { include_once(drupal_get_path('module', 'dynamicload') .'/paths.inc'); $paths .= "\n". implode("\n", module_invoke_all('dynamicload_paths')); } drupal_add_js(array('dynamicload' => array( 'all' => (bool)variable_get('dynamicload_all', 0), 'paths_type' => $paths_type, 'paths' => $paths, 'content' => $theme_data['content'] ? $theme_data['content'] : '#main', 'settings' => $settings, )), 'setting'); $loaded = TRUE; } return ''; } /** * Set a marker div in a given set of regions. * * These divs can be used from Javascript to update regions with dynamically * loaded content. */ function _dynamicload_set_region_markers($regions) { foreach ($regions as $region) { drupal_set_content($region, '
'); } } /** * Implementation of hook_form_alter(). */ function dynamicload_form_alter($form_id, &$form) { if ($form_id == 'block_admin_configure') { $options = array('content' => t('Main content area')); $result = db_query('SELECT module, delta FROM {blocks} WHERE status = 1 AND NOT (module = "%s" AND delta = "%s")', $form['module']['#value'], $form['delta']['#value']); while ($block = db_fetch_object($result)) { $module_blocks = module_invoke($block->module, 'block', 'list'); $options['#block-' . $block->module . '-' . $block->delta] = t('Block: !info', array('!info' => $module_blocks[$block->delta]['info'])); } $regions = system_region_list(variable_get('theme_default', 'garland')); // Highlight regions on page to provide visual reference. foreach ($regions as $key => $value) { drupal_set_content($key, '
'. $value .'
'); $options['region-'. $key] = t('Region: !name', array('!name' => $value)); } $settings = dynamicload_block_data($form['module']['#value'], $form['delta']['#value']); $form['#submit']['dynamicload_submit'] = array(); $form['dynamicload'] = array( '#type' => 'fieldset', '#title' => t('Dynamic loading'), '#collapsible' => true, '#weight' => -5 ); $form['dynamicload']['dynamicload_apply'] = array( '#type' => 'checkbox', '#title' => t('Apply dynamic loading'), '#description' => t('Check if you want links on this block to be loaded dynamically rather than through a regular page refresh. If you enable this functionality for a block, make sure that you thoroughly test the result, as not all pages will perform as expected when loaded dynamically.'), '#default_value' => $settings['apply'] ? 1 : 0 ); $form['dynamicload']['dynamicload_target'] = array( '#type' => 'select', '#title' => t('Target area'), '#default_value' => $settings['target'] ? $settings['target'] : '#main', '#options' => $options, '#description' => t('Select the page area for this block\'s links to load into. Only enabled blocks are available.'), ); $options = array( DYNAMICLOAD_HTML => t('replace existing content'), DYNAMICLOAD_APPEND => t('append: add at end of existing content'), DYNAMICLOAD_PREPEND => t('prepend: add at beginning of existing content'), DYNAMICLOAD_BEFORE => t('before: add before target element'), DYNAMICLOAD_AFTER => t('after: add after target element'), ); $form['dynamicload']['dynamicload_method'] = array( '#type' => 'select', '#title' => t('Appending method'), '#default_value' => $settings['method'] ? $settings['method'] : 1, '#options' => $options, '#description' => t('Select the way you want newly loaded content to be written to the target area.'), ); $form['dynamicload']['dynamicload_refresh'] = array( '#type' => 'checkbox', '#title' => t('Automatically refresh this block'), '#default_value' => $settings['refresh'] ? 1 : 0 ); $form['dynamicload']['dynamicload_refresh_interval'] = array( '#type' => 'select', '#title' => t('Block refresh interval'), '#description' => t('Select the interval at which this block should refresh.'), '#default_value' => $settings['refresh_interval'] ? $settings['refresh_interval'] : 30000, '#options' => array(5000 => t('five seconds'), 10000 => t('ten seconds'), 30000 => t('thirty seconds'), 60000 => t('one minute'), 120000 => t('two minutes'), 180000 => t('three minutes'), 300000 => t('five minutes'), 600000 => t('ten minutes')), ); $form['dynamicload']['dynamicload_scroll'] = array( '#type' => 'checkbox', '#title' => t('Scroll in new items'), '#description' => t('Check if you want new items for this block to scroll in ticker-style as they arrive (with the oldest item scrolling out). If this option is not checked, the whole block will refresh. Note: only works for items that come in as a list (using an HTML ul element).)'), '#default_value' => $settings['scroll'] ? 1 : 0 ); } } /** * Register settings. */ function dynamicload_submit($form_id, $form_values) { if (db_num_rows(db_query("SELECT * FROM {dynamicload_blocks} WHERE module = '%s' AND delta = '%s'", $form_values['module'], $form_values['delta']))) { db_query("UPDATE {dynamicload_blocks} SET refresh = %d, refresh_interval = %d, scroll = %d, apply = %d, target = '%s', method = %d WHERE module = '%s' AND delta = '%s'", $form_values['dynamicload_refresh'], $form_values['dynamicload_refresh_interval'], $form_values['dynamicload_scroll'], $form_values['dynamicload_apply'], $form_values['dynamicload_target'], $form_values['dynamicload_method'], $form_values['module'], $form_values['delta']); drupal_set_message(t('Dynamic loading block data updated.')); } else { db_query("INSERT INTO {dynamicload_blocks} (module, delta, refresh, refresh_interval, scroll, apply, target, method) VALUES ('%s', '%s', %d, %d, %d, %d, '%s', %d)", $form_values['module'], $form_values['delta'], $form_values['dynamicload_refresh'], $form_values['dynamicload_refresh_interval'], $form_values['dynamicload_scroll'], $form_values['dynamicload_apply'], $form_values['dynamicload_target'], $form_values['dynamicload_method']); drupal_set_message(t('Dynamic loading block data saved.')); } } /** * Load dynamicload settings for a block or all blocks. */ function dynamicload_block_data($module = NULL, $delta = NULL) { static $blocks = NULL; if ($blocks == NULL) { $blocks = array(); $result = db_query("SELECT * FROM {dynamicload_blocks}"); while ($block = db_fetch_array($result)) { foreach (array('refresh', 'apply') as $key) { $block[$key] = (bool) ($block[$key]); } $block['type'] = 'block'; $block['selector'] = '#block-'. $block['module'] .'-'. $block['delta']; $blocks[$block['module'] .'_'. $block['delta']] = $block; } } if ($module !== NULL && $delta !== NULL) { return $blocks[$module .'_'. $delta] ? $blocks[$module .'_'. $delta] : array(); } else { return $blocks; } } /** * List blocks available to the current user on the current page. */ function dynamicload_block_list() { global $theme_key; $blocks = array(); if ($theme_key) { $regions = system_region_list($theme_key); foreach (array_keys($regions) as $region) { $block_list = block_list($region); $blocks = array_merge($blocks, $block_list); } } return $blocks; } /** * Menu callback to return a rendered block in JSON format. */ function dynamicload_fetch_block($module, $delta) { global $theme_key; if (!isset($theme_key)) { init_theme(); } $region = db_result(db_query("SELECT region FROM {blocks} WHERE module = '%s' AND delta = %d AND theme = '%s'", $module, $delta, $theme_key)); $blocks = block_list($region); if (isset($blocks[$module .'_'. $delta])) { print drupal_to_js(array( 'result' => TRUE, 'content' => theme('block', $blocks[$module .'_'. $delta]), )); } else { print drupal_to_js(array( 'result' => FALSE, 'content' => NULL, )); } exit; } /** * Menu callback to return a rendered page in JSON format. */ function dynamicload_js() { // The path requested is the current q arg minus the 'dynamicload/js/'. if ($path = substr($_GET['q'], 15)) { $return = module_invoke('pagearray', 'page', $path); if ($return['status'] === FALSE) { switch ($return['value']) { case MENU_NOT_FOUND: case NULL: $result = array( 'result' => FALSE, 'message' => t('Item was not found.'), ); break; case MENU_ACCESS_DENIED: $result = array( 'result' => FALSE, 'message' => t('Access denied.'), ); break; case MENU_SITE_OFFLINE: $result = array( 'result' => FALSE, 'message' => t('Site offline.'), ); break; } } else { // Generate 'extra' for outputting in main content area. $extra = '

'. $return['page']['title'] .'

'; $extra = $return['page']['breadcrumb'] . $extra; if ($tabs = theme('menu_local_tasks')) { $extra .= $tabs; } $extra .= $return['page']['help']; $extra .= theme('status_messages'); // Load scripts $result = array( 'result' => TRUE, 'extra' => $extra, 'content' => $return['page']['content'], 'title' => $return['page']['head_title'], 'scripts' => $return['page']['raw_scripts'], 'css' => $return['page']['css'], ); $regions = array_filter(variable_get('dynamicload_regions', array())); if (!empty($regions)) { $result['regions'] = array(); foreach ($regions as $region) { if (isset($return['page']['regions'][$region])) { $result['regions'][$region] = $return['page']['regions'][$region]; } } } } } else { $result = array( 'result' => FALSE, 'message' => t('No request found.'), ); } print drupal_to_js($result); exit(); }