Posts Tagged ‘drupal 7’

Manipulating the response from Drupal Views’ AJAX mechanism

When there is a requirement to plug any sort of AJAX-y mechanism into your Views, I always find it’s advantageous to create the functionality from scratch, utilising hook_menu (including 'type' => MENU_CALLBACK), or using the Services module, to estabish the RESTful service(s). However, there are occasions when using Views’ built-in AJAX mechanism (‘Use AJAX’) is a prequisite for what you’re trying to achieve. The immediate assumption is that this technique wouldn’t give you enough granularity and control over response output. This is in fact incorrect, as the response can be interecepted relatively easily.

Case study

I recently needed to create a block-display View that incorporates an exposed filter (filtering on taxonomy term). As merlinofchaos points out, exposed filters make GET requests in order to return responses, and they can’t do so without the AJAX option turned on. Turning on the AJAX option makes the filters appear – and better still, makes them work – but out of the box, a subsequent data response will simply replace the current data response that’s already in the DOM (using JQuery’s replaceWith). I’d like to have full control of the response, like I would do if I was to construct the AJAX functionality from scratch.

A how-to guide

Subsequent to my own findings, I that details the same method pretty well, although I feel it does miss out a few key points.

Views allows us to intercept the response using hook_ajax_data_alter (implemented on line 79 of views/includes/ajax.inc), which is a hook originating from drupal_alter.  If you check on line 77 of the same file, you’ll see that out of the box, Views already establishes a callback (Drupal.Views.Ajax.ajaxViewResponse) that can be parsed into javascript as an object method. However, this method will apply to all Views that use the built-in ‘Use AJAX’ option. In most cases, this isn’t preferential since if you’re wanting to manipulate the response data, you’ll want to do it on a per-View basis.

In order to establish a callback on a per-View basis, we need to extract details of the view from the $view object specified in the hook callback, with the objective being to specify a specific callback for each View display. Since hook_ajax_data_alter is a non-persistent function (it’s only called right before the response data is sent through any javascript callbacks), on the surface it’s difficult to debug using conventional means. Fortunately, Watchdog can help here (albeit, tediously). Inside the $view object, you can determine the view name ($view->ajax_path[1]['view_name']) and display ($view->ajax_path[1]['view_display_id']), which when used together, can construct an appropriate if() statement, like the following:

function hook_ajax_data_alter(&$object, $module, $view) {
        /*
         * Overwrite the 'Drupal.Views.Ajax.ajaxViewResponse' callback that's in Views core
         * as we don't want both callbacks running concurrently.
         */

        $view_details = $view->ajax_path[1];

        if ($view_details['view_name'] == 'viewName' && $view_details['view_display_id'] == 'viewId'){
         $object->__callbacks = array('Drupal.moduleName.methodName');
        }

}

You’ll notice that I’ve added a comment which explains that I’m choosing to override the default Drupal.Views.Ajax.ajaxViewResponse
callback method by writing the __callbacks array key value explicitly. Obviously, you can use multiple callbacks (including the default one), if you wish.

And that should work!

Running Drupal 7 on shared hosting

As I’ve recently disovered to my cost, a pretty bog-standard Drupal 7 install doesn’t play nice with a shared hosting package I’m using – and it doesn’t appear I’m alone in the situation I find myself in.

I’ve used Drupal 6 for my last 5-6 jobs (on many different types of large-scale hosting environments), as well as many freelance projects that are predominantly hosted on shared environments. Load times for the latter (with Drupal cache_page enabled) were surprisinly impressive. I recently undertook a re-design of my Mum’s (who practices , UK) site, and decided to give Drupal 7 a go, after reading some of the theming improvements. However, load times were extremely poor; around 2-3 second page generation, and 2 seconds through cache_page. But surely you could use a caching module to improve performance, no?

The Boost module

I’ve used Boost a couple of times before when embarking on freelance projects. I can categorically say, that apart from the modules for D6 that have since made core in D7 (CCK, image cache, etc), it’s one of the most useful modules available. Essentially, it supersedes the core Drupal cache_page mechanism, by bypassing the need for PHP processing and associated database calls altogether, by caching page requests into static HTML files (gzip’ped versions are also generated for browsers that support gunzip). Requests are served purely through mod_rewrite (Drupal clean URLs is a prerequisite for the module), meaning that anonymous users are served static files.

One really useful feature of the D6 version of Boost, is that it incorporates it’s own crawler, giving you the ability to preemptively cache pages in your url_alias table on cron jobs. The issues with the Drupal 7 version, is that it doesn’t include a crawler, meaning that unless you hack a makeshift script, then you’re reliant on anonoymous users hitting your pages, thus invoking Boost’s caching mechanism. This wouldn’t be such an issue if load times weren’t so hideous, but I’m simply not prepared for any user to wait around 2 seconds per page load.

Of course, my mother could invest in a small-scale VPS, but I’m of the opinion that version releases of a CMS shouldn’t dictate the specification of the environments they can run on. Drupal has of course got a lot more enterprise-level exposure recently, and that’s no doubt a good thing, but it needs to remain a viable solution for small-scale sites too.