Render/embed a Panels Page in a jQuery Dialog Box
I need a page on my Drupal 7 project site to display within a jQuery modal dialog box. Adding content to a jQuery dialog is straightforward with the Dialog module. The issue was the dialog box needed to contain the contents of a Panel. Previously I’ve embeded Views using views_embed_view(), but I’ve never tried to embed a Panel. A web search wouldn’t give me a quick answer, so I worked it out. Note: This article skims the initial implementation of a jQuery Dialog with the Dialog module, plus assumes you understand how to create a custom module.
Implementing hook_menu_alter() with dvm(), told me everything I needed to know. Temporary hook_menu_alter()
:
function module_menu_alter(&$items) {
dvm($items);
}
Important part of the output is the menu definition for the page needed in the dialog:
'[page_url]/panel' => array(
'access callback' => 'ctools_access_menu',
'access arguments' => array(
array(
'type' => 'none',
'settings' => NULL,
),
),
'page callback' => 'page_manager_page_execute',
'page arguments' => array(
'[page_machine_name]',
),
'load arguments' => array(
'[page_machine_name]',
'%index',
'%map',
),
'file' => 'plugins/tasks/page.inc',
'type' => 0,
'module' => 'page_manager',
),
The response from a menu item function is a string, perfect for AJAX output. So, we’ll make the Page Manager think my new menu callback is the Drupal menu system. The original simple hook_menu()
item from my module:
$items['[page_url]/%ctools_js'] = array(
'page callback' => 'module_ajax_callback',
'page arguments' => array(1),
'access arguments' => array('access content'),
);
The new menu item mimics the Page Manager menu item becoming:
$items['[page_url]/%ctools_js'] = array(
'access arguments' => array('access content'),
'page callback' => '[module_name]_ajax_callback',
'page arguments' => array(
1,
'[page_machine_name]',
),
'load arguments' => array(
'[page_machine_name]',
'%index',
'%map',
),
);
We’ll pass the all information page_manager_page_execute()
expects, plus whether JavaScript is available to the new callback function. Notice, ctools_access_menu()
, the original ctools page access access function will no longer be called. I am implementing hook_permissions()
for my use, but you may need to consider other options to manage access.
The AJAX Panels page jQuery Dialog Drupal Menu callback function:
function [module_name]_ajax_callback($js, $subtask_id, &$map, $index) {
// Be sure the inc file containing page_manager_page_execute is loaded
ctools_include('page', 'page_manager', 'plugins/tasks');
// Fake menu call to Page Manager to render panel
$param_arr = array($subtask_id, &$map, $index);
$output = call_user_func_array('page_manager_page_execute', $param_arr);
//If JS is enabled, output as JSON
if ($js) {
$options = array(
// Get the stored title and set to the dialog title.
'title' => drupal_set_title(),
// Adding dialog customizations.
'resizable' => false,
'dragable' => false,
);
$commands = array(dialog_command_display($output, $options));
print ajax_render($commands);
// Stop further output.
exit;
}
// No JS, output a regular page.
return $output;
}
This function should work for most uses. Let me know if you run into any issues with it.
When I can find some time, I think I’ll implement this as a real module…
Update 2020-10-12: I didn’t find the time.