Two major Views related bugs in Drupal 7

Whilst some might interpet the somewhat pessimistic RC1 status of Views 7.x-3.x as a bit of a turn-off, the module is actually pretty solid; from what I can remember, the upgrade path is the only thing stopping the module from advancing in maturity further, for the time being.

There are however, a couple of pretty major bugs that have come about from changes outside the module itself:

Theme preprocess functions which attempt to add template suggestions, aren’t invoked

I managed to find this bug pretty quickly, since it’s standard procedure from a theming perspective, to abstract processing logic from markup. It appears that the problem originates from a change to the theme registry, where you can’t specify template suggestions from a preprocess anymore, rather than traditionally invoking them from theme().

Barring actually patching core, there doesn’t seem to be an elegant solution for the time being. As an interim solution, I decided to use a preprocess function that doesn’t try to invoke a template suggestion (i.e preprocess_views_view()), and use a switch() to target individual Views.

views_get_view_result() doesn’t return Field API field values

This is a pretty major issue; put simply, when using views_get_view_result() to return values from a View, values from any non-core fields won’t be rendered.

Exporting block positioning into code in Drupal

On most occasions, exporting configuration settings in code can be managed by the Features module, however, there are some scenarios where it can’t handle particular requirements. One particular instance, in my experience, is exporting block positioning (in relation to theme regions).

Fortunately, the block module gives us the hook_block_info_alter function that allows us to specify the region to which a certain should be placed. Since one of the function’s parameters is the $theme variable (formatted as a string), it allows us to specify block-to-region placement on a per-theme basis. An example of a block position export would be:

function hook_block_info_alter(&$blocks, $theme, $code_blocks) {
  if($theme == THEMENAME) {
    $blocks['search']['form']['region'] = 'header';
    $blocks['search']['form']['status'] = 1;
  }
}

Importance of exporting block positioning in Drupal 7

You’ll notice from code above, that I’ve used the search block as an example.

One of the theming-related changes that Drupal 7 introduces is that the rendered output of the search box is no longer available as the $search_box variable in the theme, as it once was in Drupal 6. Instead, the search form is incorporated into the block system, meaning that its position should be controlled via this mechanism.

Manipulating the response from Drupal Views’ AJAX mechanism

Tagged in:

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 found an article 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

Tagged in:

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 counselling in Surrey, 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.

Clear ‘cache_page’ once new node comment has been saved in Drupal 7

Slightly surprised this hasn’t been covered anywhere before. Building upon the answer to a similar problem in Drupal 5, I thought it would be beneficial to post how to achieve the same thing in Drupal 7.

Since hook_comment is now unavailable in Drupal 7 (in favour of some more explicit interception-based hooks), I’ve decided to utilise hook_comment_insert for this purpose. Together with a revised url() syntax, the hook looks as follows:

function hook_comment_insert($comment) {
// Clear page-specific cache after comment has been saved for that page
$url = url('node/' . $comment->nid, array('absolute' => TRUE));
cache_clear_all($url, 'cache_page');
}

An apology

I’d like to apologise to those who have taken the time to contact me (either by email or Twitter) regarding IE8 bugs

A few months ago, I embarked on a work project that has ultimately left me with no time to keep on top of incoming mails, let alone bug reports from contributors. If you haven’t received a reply from me regarding your correspondence, then I could easily see how you may think I can’t be bothered to reply – rest assured, this isn’t the case at all.

I’ve had a truly great response from authors ever since I requested they write in about potential bugs they’ve found. For me to not respond to the more recent emails in an adequate time frame is completely unprofessional and I apologise profusely for this. I still have a complete archive of all emails sent to me, and I endeavour to respond appropriately to all of these in the coming month.

Some people may argue that since IE9 is now starting to be exposed publicly, that maintaining an IE8 bug list such as mine is worthless. I disagree strongly with this view. I like to think the list in it’s current form is providing developers with a much needed knowledge base that Microsoft Connect is lacking (filtering, clear UI, etc). My aim is to carry on maintaining the list into the near future, and for it to become a permanent resource to developers.

IE9, and associated bug reporting

Apart from reading the majority of IEBlog articles on IE9’s rendering capabilities, I’ve been completely out of the loop as to what IE9 has in store for developers when it’s finally released. You may be wondering, since I’m an IE MVP, why I wasn’t informed on a product group level; I don’t have an answer for you. There’s been absolutely no PGIs for Internet Explorer and the IE MVP newsgroup has been extremely quiet- so quiet in fact I’ve now removed Unison from opening at startup, and I now don’t pay attention to the newsgroups at all.

I for one was astounded after finding out that IE9 won’t be released for WIndows XP – limiting a browser version to certain platform versions is absurd on so many different levels. I do all my browser testing on my Macbook Pro and I have two VM’s installed (one for IE6/7, and one for IE8). I’ve decided to bit the bullet and purchase Windows 7 tomorrow so that I can test drive IE9 for the first time, albeit on ‘Platform Preview’.

In terms of IE9 bug testing, like with IE8, my aim is to create an initial list and would open up participation to authors that are inclined to do so. I see a far greater need to establish a prominent list of IE9 issues than with IE8, since IE9 attempts to include complete implementations of several CSS3 modules, that they haven’t embarked on before with IE8. For this reason, I can evisage there being far more bugs with IE9 than with IE8.

Coming back to outstanding IE8 bug reports from authors writing in to me, I envisage to respond appropriately to those in the next month or so, and to continue to invite authors to contribute to this ever-growing list.

IE9 is coming

All active bug tickets on Microsoft Connect have now been marked as postponed, and Microsoft have appended the following message to all of them:

Thank you for submitting your feedback on Internet Explorer 8. The information in this bug has been reviewed carefully by the team and will help inform future releases of Internet Explorer. We are now closing down the Internet Explorer 8 Feedback Program in preparation for soliciting feedback for our next version and as such, per the Microsoft Connect guidelines, all remaining bugs for IE8 will be resolved as “Postponed” for now. When the feedback program for the next release is ready, we will look at transferring this bug, along with any applicable status update.

I would certainly take this as a sign that the release of IE9 is approaching. To close the bug reporting system relating to a current browser version for any significant period of time, without a new version (reporting system or browser) being released soon after, would be ludicrous. On the other hand, it does make sense to transfer all bug reports for IE8 over to the reporting system for IE9, and by Microsoft doing this, it confirms there’ll be no interim browser versions, anyway. Hopefully Microsoft will open up IE9’s reporting system soon, as I currently don’t have anywhere to create new tickets!

This status message from Microsoft also ties in nicely with the upcoming date of MIX 2010 where it’s been confirmed that Dean Hachamovitch will be discussing the development of IE9. Dare I suggest that Microsoft will give us a definitive release date for IE9, or even better, release it there and then? If it’s not the latter, I’d hazard a guess that we’ll see a beta release within the next five months.

Selecting text within an element in CSS

An interesting discussion (which established itself as a branch from discussing behavioral characteristics of overflow) is currently taking place on www-style regarding a text selector control. Much of the detail is still being fleshed out, but I thought I’d give a quick overview.

Initially discussed as a possible way to remove suppress whitespace textnodes between inline-blocks, the control itself would take the form of a pseudo element incorporating function notation taking a matching pattern as an argument – something along the lines of ::text(matching-pattern) – which would have the ability to match strings of text within an element.

In contrast to my own confused ramblings (which I subsequently retracted), the consensus now is that the pseudo element should be excluded from crossing element boundaries in order to match a constituent of the argument, which means the full range of CSS layout properties can be exposed to the pseudo element (dependant on DOM-based pattern matching). Otherwise, consider Tab’s example:

p::text("foo b"){ display:block; }
<p>foo <span>bar</span> baz</p>

The above would split the pseudo element in two, since part of it would cross into the <span> in order to match the pattern given as the argument, resulting in:

<p><text match="foo b">foo </text><i><text match="foo b">b</text>ar</i> baz</p>

Not only would this be quite-rightly unintuitive from an author’s perspective, but it would also be harder to implement (compared to excluding element boundary crossing) from a vendor point of view. Having said that, the former issue could be solved by providing a limited range of CSS properties, similar to that of ::first-line, although conversation is veering away from such a resolution.

The sub-topic of discussion at the moment is how to avoid one ::text() boundary from crossing another.

If you can take some time out of your day, it’s certainly an interesting read.

Establishing a new method of float containment

So, in the many years in which floating (itself a workaround due to a lack of a more sanctioned layout tool) has become an integral part of CSS layouts, we have still not been provided with a control, whose primary purpose is float containment.

Authors have become reliant on either replicating a clearing markup element using generated content (borne from author findings), or have found that overflow:hidden|scroll|auto; applied to the parent, expands the parent’s margin-box to encapsulate the height of the child(ren). In fact, any property/value pair that can establish a new block formatting context (BFC) has the ability to do this. These pairs include:

  • float:left|right
  • position:absolute|fixed
  • display:inline-block|table-cell|table-caption
  • overflow:hidden|scroll|auto

Although there are a couple of areas in the spec that detail behavioral characteristics of BFCs, the crucial containment behavior can be derived from the Float specification

[...] an element in the normal flow that establishes a new block formatting context (such as an element with ‘overflow’ other than ‘visible’) must not overlap any floats in the same block formatting context as the element itself. If necessary, implementations should clear the said element by placing it below any preceding floats, but may place it adjacent to such floats if there is sufficient space.

9.5 Floats

A host of potential candidates

Whilst the aforementioned properties are all able to clear child floats, there is a major difference with one property/value pair in particular in the way that it computes an element’s width.

Every property/value pair that has the ability to establish a BFC – apart from overflow:hidden|scroll|auto – irrecoverably alters a block box’s computed width by applying the ’shrink-to-fit’ algorithm. In theory, we could try to emulate the expand-to-fit computed width of an in-flow block box with something like:

display:inline-block; /* Establish a new BFC, but that applies shrink-to-fit to computed width */
   width:100%;
   box-sizing:border-box;
}

Whilst this would be a plausible solution in the presence of any horizontal padding values, horizontal margins would remain an issue, which leaves overflow as being the only real solution.

Exploiting a property for it’s side-effect

Since we’re hacking a property purely for the purposes of harnessing a side-effect of it’s BFC-establishing characteristic, we have to contend with it’s primary purpose; controlling the clipping of an element’s content when it overflows that element’s content box.

In the common case where an element (which has a floated sibling) overflows it’s parent and the parent is established as the containing block, one of the overflow mechanisms will be invoked; this is a problem if you require the overflowing content of the containing block to remain visible. The only solution in this case is to ‘revert’ to one of the more traditional workarounds involving placing a clearing pseudo element after the parent’s document tree content. However, this author-invented solution acquires the pseudo element and means it can’t be used for more appropriate presentational purposes.

What’s needed

The crux of the matter is this – we’re being forced to use hacks in order to contain floats. Whilst float is an arguably adequate layout model for controlling content position amongst siblings (images, text, etc), it’s inadequate as a fundamental layout mechanism.

We’ve already identified that one particular characteristic of a BFC is that it contains floats in the manner that we require, each of the properties also have their own primary behavioral characteristics. So what I think’s needed is a new control which has the primary purpose of float containment in the same manner as a BFC currently does:

'float-contain'
Value:       auto | contain
Initial:     auto
Applies to:  non-replaced block-level elements
Inherited:   no

Granted, there are modules in the pipeline that will supersede float as a layout tool, but these are all still Working Drafts and likely to remain as drafts for a while longer (as far as I know). However, establishing a control that can be used as an interim solution whilst we still have to use floats, would be advantageous.

You can follow the discussion on www-style here (NOTE: the thread spans multiple months)

Bring back float-displace

Although I was already aware of this property’s existence, I was unaware that it had been removed from later iterations of css3-box – that was, until the related issue was brought up recently on www-style.

To me, float-displace is another good example of a property (another being box-sizing) introduced in CSS3 that aims to ‘patch’ a logical failing present in previous CSS revisisons. The current behavior can be described as, the indented edge (caused by a margin value) of the in-flow element isn’t preserved between the margin-edge of the float and the content-edge of the in-flow element; this creates the following pit-falls:-

  1. It’s completely counter-intuitive for authors who aren’t already aware of this limitation
  2. The only real workaround to this limitation is to apply a margin value (which equals the indentation of the in-flow element) to the floated element, thus emulating this indentation.

From an author’s perspective, it’s perfectly acceptable to assume that the indented egde of the in-flow element will be preserved upon encountering a float.

I have no idea what the reasoning behind removing this property from the current revision was, but am keen to find out.