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...
Add new comment