Embedding the Drupal 7 search form in another site with jQuery
A section of my current project will be hosted by an external server/service. I hand them a HTML file, and they build their content within it. One problem is that the header search form must still work. For security reasons, Drupal won’t accept a Form Post without the correct Form ID, so we need Drupal to generate the form.
I quickly located: Embedding a Drupal search form on another site using jQuery. It described exactly what I wanted to do, but was written for Drupal 6. So, I used it as a basis to write a Drupal 7 version. Thanks Eric! Note: This requires you create a custom module for your site.
hook_menu() implementation:
/**
* Implements hook_menu().
*
* Creates page callbacks for the JSON calls
*/
function module_menu() {
$items = array();
// Add a page callback for the url: "external-search.js".
$items['external-search.js'] = array(
'title' => 'External search',
'page callback' => '_module_search',
'type' => MENU_CALLBACK,
'access arguments' => array('search content'),
);
return $items;
}
hook_menu() implementation:
/**
* Implements hook_menu().
*
* Creates page callbacks for the JSON calls
*/
function module_menu() {
$items = array();
// Add a page callback for the url: "external-search.js".
$items['external-search.js'] = array(
'title' => 'External search',
'page callback' => '_module_search',
'type' => MENU_CALLBACK,
'access arguments' => array('search content'),
);
return $items;
}
JSON-generating page callback:
/**
* Format JSON
*/
function _module_search($html) {
// Create a JSON string of the search block form html.
$json = drupal_json_encode(drupal_render(drupal_get_form('search_block_form')));
// Format the json as a callback function.
// See: http://docs.jquery.com/Ajax/jQuery.getJSON for more information.
if (isset($_GET['jsoncallback'])) {
$json = $_GET['jsoncallback'] . "(" . $json . ");";
}
// Output the JSON.
print $json;
// Stop the script, so the theme layer is not applied.
die;
}
JSON-generating page callback:
/**
* Format JSON
*/
function _module_search($html) {
// Create a JSON string of the search block form html.
$json = drupal_json_encode(drupal_render(drupal_get_form('search_block_form')));
// Format the json as a callback function.
// See: http://docs.jquery.com/Ajax/jQuery.getJSON for more information.
if (isset($_GET['jsoncallback'])) {
$json = $_GET['jsoncallback'] . "(" . $json . ");";
}
// Output the JSON.
print $json;
// Stop the script, so the theme layer is not applied.
die;
}
The external service is mimicking the real site; everything(CSS, images, JS) is loading from the real server, except the HTML itself. We’ve got access to jQuery and Drupal Behaviors! This makes it straightfoward. I removed everything within the #block-search-form .content
from the HTML file, so there wouldn’t be two forms. The following was named external_search.js
, and added to the HTML file with a <script>
tag.
//This JS should be loaded by external websites, never by the actual Drupal installation.
(function ($) {
Drupal.behaviors.external_search = {
attach: function(context) {
$('#block-search-form .content', context).once(function () {
// make the ajax request
$.getJSON("http://YOURSITE/external-search.js?jsoncallback=?",
function(data){
// append the form to the container
$('#block-search-form .content').append(data);
//Drupal.attachBehaviors(); //un-comment if there are Behaviors to attach
}
);
});
}
}
})(jQuery);
If you need to embed the form in a non-Drupal non-jQuery site, Eric’s code will work as is:
<!-- Include jQuery (as necessary) -->
<script type='text/javascript' src='http://YOURSITE/misc/jquery.js' ></script>
<!-- create a div container to contain the search form -->
<div id='embedded_search'></div>
<!-- add the jQuery to embed the form -->
<script type='text/javascript'>
$(document).ready(function(){
// make the ajax request
$.getJSON("http://YOURSITE/external-search.js?jsoncallback=?",
function(data){
// append the form to the container
$('#embedded_search').append(data);
}
);
});
</script>
Any Drupal content can be externally embedded using this method. For example: Once this initial functionality was complete, I created a new JSON call to load data from a View using views_embed_view()
. The only limit is yourself.