I have a client who wants a slightly complex multi-table layout for some of the content on their site. I have come up with a solution which I thought I would share, along with some alternatives that I considered...

They want their pages to be arranged something like this, where A,B,C,D,E and F are all user editable content areas:

+-----------------------+
| Std Header            |
+-----------------------+
| +---+  +---+  +---+   |
| | A |  | B |  | C |   |
| +---+  +---+  +---+   |
|                       |
| +---+  +---+  +---+   |
| | D |  | E |  | F |   |
| +---+  +---+  +---+   |
|                       |
+-----------------------+

You can obviously achieve this by including HTML "< table >" tags within a single page node. However, the problem with that is that the content editors don't like editing HTML. There is also a high risk that they would mess up the layout by accidentally deleteing some of the tags! In the past I have set up the TinyMCE "WYSIWYG" editor, but they do nasty things like cut & paste from word documents, which then includes lots of nasty MS Word formatting tags which are a pain to clean up. This approach also has the disadvantage that the page structure is then mixed with the content, which is bad practice. If they want to change the structure in future then every page will need to be re-edited. Yawn!

The second approach that I considered was something like the dashboard module. It works almost exactly the way that I would want, but unfortunately seems restricted to a fixed "header, footer and two columns" layout.

A third approach was to use the wonderful new "views" and "insert_view" modules. The idea would be to create a view onto a single page's content, then create a page which made multiple calls to "insert_view" to place the various content sections within the required table/div structure. Each box in the desired layout would thus come from a single (user editable) plain text "content" page, and all the formatting and "insert views" calls would be on a "structure" page that only I would edit. Unfortunately there currently seems to be a critical bug in the v4.7 insert_view module.

A fourth approach might be to write a custom module based on the "dashboard" module, and do some themeing to get the desired layout. That might be the most flexible way, but it seems like a lot of work, and I'm a bit lazy....

... so I came up with my alternative: use some php code to achieve pretty much the same thing as the "insert_view" approach would have done, ie "multiple content pages within a structure page".

Here's the php code. You can include it directly within the "structure" page, or in some php file that gets loaded by Drupal. I stuck it at the end of the dashboard.module file, but like I said, I'm a bit lazy! ;-)

function page_within_page($nid) {
  global $user;

  // fetch the body content for the requested page
  $sql = "SELECT r.body, r.format FROM {node} n, {node_revisions} r WHERE r.vid = n.vid AND n.nid = '%d'";
  $row = db_fetch_object(db_query($sql,$nid));
  $html = check_markup($row->body, $row->format, false);

  // show a handy "click to edit" link for certain users only
  if (($user->uid == 1) || ($user->uid == 2)) {
    $html .= '<p><a href="/node/' . $nid . '/edit">click to edit</a></p>';
  }

  return $html;
}

Then create a page containing the "structure", where node 10 contains the content you want in box "A", node 11 has the content for "B" etc:

<table width="100%">
<tr>
<td><?php page_within_page(10); ?></td>
<td><?php page_within_page(11); ?></td>
<td><?php page_within_page(12); ?></td>
</tr><tr>
<td><?php page_within_page(13); ?></td>
<td><?php page_within_page(14); ?></td>
<td><?php page_within_page(15); ?></td>
</tr>
</table>

Make sure that the "structure" node has the "php" input format set. Save and view. Hey presto - all your content in the desired layout. Add some css tags & start theming. :-)

One problem that I have found is that if I want to include uploaded images using the "upload" and "inline" modules, the images need to be attached to the "structure" page.

If I attach a file to the structure page and insert a "[inline:1]" tag, the image appears in the desired location. However if any of the sub-pages have an attachment and use the "[inline:1]" tag, the image attached to the "strcture" page is shown, rather than the one attached to the content.

I suspect that this is due to the way the check_markup() function processes the inline filter... it seems to use the context of the calling "structure" page, rather than the called "content" page. I've had a look at the check_markup() and inline.module code but don't know enough to figure it out. Any suggestions?

Well, I hope this is useful to somebody... and if you have any alternative solutions or suggestions, please let me know.

Cheers.

Comments

stevenlyons’s picture

Tables are not very flexible. I would use divs with CSS classes and floats instead. That way you can more easily change the look and feel of your site by just modifying one CSS file. Each div would look like this:


<div class="small_page">
  {render content here}
</div>

Check this website for tutorials on how to use divs to make grid-type layouts:
http://css.maxdesign.com.au/floatutorial/tutorial0407.htm