Installing the module follows the typical process: Extract MkDru into an appropriate modules/ directory within your Drupal installation and, if you don’t already have it, the Libraries API module. Once that’s done, you can enable the MkDru module from the administration menu on the site itself.

Enabling MkDru makes a new Content Type available: Pazpar2 metasearch interface. You can create multiple nodes of this type to provide front ends for different sets of targets configured on the web service, or different web service instances entirely.

MkDru works out of the box with the URL to our demo service as the default on a new search node. To use MasterKey Connect you just create a search node with the provided URL.

Host your own

You can also host your own metasearch engine with either Pazpar2 or Service Proxy. Because MkDru fetches results via AJAX it needs to be able to send an XMLHttpRequest to your server. To prevent malicious use, web browsers will only send these requests to hosts on the same domain or those that expressly permit it via cross-origin resource sharing (CORS). A common approach if you’re using the Apache web server is forwarding a local path to another host via mod-proxy and sample Apache configuration is distributed with Pazpar2.

Keeping all HTTP connections going to the same domain also saves the client from another DNS request to look up the web service host. For similar reasons, it is advantageous for production sites to host their own copy of the Pazpar2 Javascript Library. This is included via Libraries API if you place the Javascript in sites/all/pazpar2-js or sites//pazpar2-js.


The node configuration form exposes several options:

  • autocomplete toggle and alternate URL to use when you wish to use a different web service instance for autocompletion in the search box
  • mergekey override is a comma separated list of fields that, if identical, indicate the records refer to the same resource, overriding the service configuration. Requires Pazpar2 > 1.6.31.
  • ranking weight override is a list of metadata fields and multipliers following the format field1=weight,field2=weight.... with the weight factor overriding the rank specified for that field in the service definitiion. Requires Pazpar2 > 1.6.31.


Any termlist you’ve configured in the web service can be exposed as a facet in the node configureation.

  • The name of the termlist and string to use in the query need to be exactly as represented in the service config.
  • Allow multiple limits? determines if users be given the option to further refine their query and, for example, display only results with both a subject term “drupal” and “metasearch”. Requires Pazpar2 > 1.6.31.
  • Facet weight is not used in the core mkdru, but can be helpful to set the order of facets in custom themes that, rather than use blocks or position facets explicitly,take the values in mkdru.facets to render a sequence of facet containers. Requires Pazpar2 > 1.6.31.


For each MkDru node created a block becomes available that displays a search form tied to that node. There are also blocks to contain the facet terms and their counts. These default to only being visible on the search page.


MkDru can be themed like any Drupal module. The search page and facet blocks are HTML generated by Drupal on the server with templates you can override in PHP. The search is performed by Javascript running in the browser that connects directly to Pazpar2. Drupal and the server’s PHP never see the search results, but the templates on the server return markup that is subsequently populated by the Javascript client. provides full detail. What follows is a quick guide to get started with this sample subtheme and a summary of the theme functions available in MkDru.

Themes are stored under themes/ at either sites/all/ or sites/yoursite/ under your Drupal installation. To test out this subtheme you need only place it there and make the theme active. It will have a new panel of settings that supercede the parent theme, others are inherited.

Theme Structure

Each theme stored in a directory under this which contains, at a minimum, a file of the same name with an extension of .info. The directory name is the canonical name used to refer to the theme in various other contexts.

While it is common for Drupal sites to have bespoke themes, there are many generic ones available to use as a base. In this case, the .info file can specify the parent theme and thus form a subtheme that need only contain those files that differ.

A file named template.php contains implementations of specific functions prefixed with nameoftheme_ that allow PHP code to be run against content on the server-side before it is sent to the browser. One of the most commonly used is _preprocess_page that is called before any page is sent out and passed references to a variety of useful code objects related to the page currently being rendered.

The provided example uses _preprocess_page to conditionally include its Javascript theme functions only on MkDru search pages.


Along with the name, description, version and other metadata, the theme’s .info file can specify CSS stylesheets to include (paths relative to the theme) like so:

stylesheets[all][] = css/somestyle.css

You can override mkdru.css by specifying a file with that same name. You can similarly override other css from modules and parent themes with some caveats, see


The templates/ directory contains files with the extension .tpl.php that are used to render the markup of different components of the system to create the output sent to the browser. A custom theme would commonly implement at least page.tpl.php and likely block.tpl.php and others.

MkDru defines four templates which lay out the containers for the Javascript-based search client to populate:

  • mkdru-block-facet.tpl.php – Facet blocks. Passed an identifier indicating the facet being rendered to include in the container element’s class attribute so it can be found and updated. This also allows for per-facet exceptions as you can output different markup depending on which facet is being rendered. By default the facet blocks are set to display only on search nodes.
  • mkdru-block-search.tpl.php – Search block. Default provides a form with a Javascript that takes a query and submits it to whichever node it is enabled for by redirecting to that node’s url with the query in a hash tag. For example, a search for whatever on node 23 would be: /node/23#query=whatever. This defaults to being displayed on all nodes.
  • mkdru-form.tpl.php – The search form and drop downs to select sort order and results per page.
  • mkdru-results.tpl.php – Holds the containers for the pager, result counts, and the results themselves.

Class Names

These can help you set up the CSS for your theme, though it may be most illustrative to inspect the markup output from the defaults to see how it all goes together.

  • mkdru-counts -> Current position in result list and total number of results present/available.
  • mkdru-facet-* -> Each facet has a class to facilitate positioning them within your layout. For example, mkdru-facet-subject
  • mkdru-pager -> Links to the next and previous page of results and pages in the vicinity of the one currently displayed.
  • mkdru-results -> Holds result list, pager, counts, and status and is hidden until search results start coming in.
  • mkdru-result-list -> Result elements are appended here.
  • mkdru-status -> Number of targets in the search and how many have reported thus far.

Beyond styling, the CSS classes also indicate which elements will receive the output from the Javascript metasearch client. For example:

  • place a second pager display to the top of the result list by adding the class mkdru-pager to an appropriately positioned element in mkdru-results.tpl.php
  • display the facets inline instead of in Drupal blocks with elements of class mkdru-facet-nameoffacet


The labelled classes are not populated directly by MkDru’s Javascipt Pazpar2 client. Instead, Drupal theme functions are provided which are provided with input parameters and return the finished markup to be placed in the appropriate class (see for detail and usage).

You can override one or all of the functions. See mkdru.theme.js for the defaults. What follows is a guide to the parameters:

Drupal.theme.prototype.mkdruResult(hit, num, detailLink)

  • hit -> object containing the fields returned by pazpar2 for one result in the result list. The structure of this is determined by your Pazpar2 configuration and it is probably easiest to inspect this object with Firebug by setting a breakpoint in mkdru.theme.js to see the full extent of data available.
  • num -> number of this hit within the result list.
  • detailLink -> link target for the detailed view of this record.

Drupal.theme.prototype.mkdruDetail(data, linkBack)

  • data -> similar to the hit object in result, this contains all the data from Pazpar2 for the result in question.
  • linkBack -> this contains the link target to return to the result list

Drupal.theme.prototype.mkdruPager(pages, start, current, total, prev, next)

  • pages -> array of anchor targets to link page numbers to.
  • start -> number of the first page in the array.
  • current -> current page.
  • total -> total number of pages.
  • prev -> link to previous page.
  • next -> link to next page.

Drupal.theme.prototype.mkdruCounts(first, last, available, total)

  • first -> first result displayed.
  • last -> last result displayed.
  • available -> number of results available from the metasearch engine.
  • total -> total results reported by all targets.

Drupal.theme.prototype.mkdruStatus(activeClients, clients)

  • activeClients -> number of targets that have reported search results.
  • clients -> total number of targets being searched.

Drupal.theme.prototype.mkdruFacet(terms, facet, max, selections)

  • terms -> objects for each term for this facet in the current result set for this facet. Each term has these properties:
    • toggleLink -> link to limit the query to this facet term or remove the limit if already in place.
    • selected -> true if the query is already limited to this term.
    • name -> value to display for the term.
    • freq -> number of occurences of records with this value for this facet.
  • facet -> name of the facet.
  • max -> maximum number of facet terms to display.
  • selections -> value of current limits in place for this facet ie. selected terms. These are to be displayed even if there are no terms for this facet to give the user an opportunity to remove the limits.

Embedding and URL

The Javascript client is largely decoupled from the node structure and will draw the interface into all elements with the appropriate class. Any page with MkDru’s scripts included will initialise a search session (Pazpar2 only, Service Proxy is sessionless) and execute any query in the URL.

The query and other URL parameters are set much like HTTP GET but with a # instead of a ?, such as in this example:


The available parameters are:

  • limit__facetname_ -> limit results to those with a matching facetname facet
  • page -> current page of search results
  • perpage -> number of results per page
  • query -> search query
  • recid -> display details of record matching the given id
  • sort -> sort string passed to pazpar2

The initial state of the search can also be set by using drupal_add_js to store an object with keys corresponding to the URL parameters in Drupal.settings.mkdru.state. This is primarily useful for embedding with other modules.