views:

6956

answers:

6

What is the best method for including a CSS or Javascript file for a specific node in Drupal 6.

I want to create a page on my site that has a little javascript application running, so the CSS and javascript is specific to that page and would not want to be included in other page loads at all.

+3  A: 

The best solution I've come up with so far is to enable the PHP input mode, and then call drupal_add_css and drupal_add_js as appropriate in a PHP block in the start of the body of your node.

Evan
I've used this very technique over and over in Drupal 5. For example, the "Club Calendar" on the front page of this site was implemented this way.http://www.chesmontastro.org/
Mike Heinz
This might be the easiest solution, but quickly becomes unmaintainable, as storing PHP code in the database is very hard to debug, and revision control is nearly impossible. Inferis' solution above is a much cleaner approach.
jhedstrom
A: 

You can have a custom template for that node (node-needsjs.tpl.php) which calls the javascript. That's a little cleaner than using PHP right in the node body, and makes changes to content easier in the future.

EDIT: I don't think I was very clear above. You want to name the template file node-(nodeid).tpl.php. So if it was Node 1, call the file node-1.tpl.php

mabwi
I really should have thought this answer out better - a further benefit of using a custom template file is the ability to force other nodes to use the template via the template_preprocess_page function in template.php.
mabwi
+1  A: 

This should do the trick - a quickie module that uses the hook_nodeapi to insert the JS/CSS when the node is viewed.

function mymodule_nodeapi(&$node, $op, $a3 = NULL, $a4 = NULL) {
  // the node ID of the node you want to modify
  $node_to_modify = 6;

  // do it!
  if($op == 'view' && $node->nid == $node_to_modify) {
    drupal_add_js(drupal_get_path('module', 'mymodule') . '/mymodule.js');
    drupal_add_css(drupal_get_path('module', 'mymodule') . '/mymodule.css');
  }
}

This avoids security issues with enabling the PHP input filter, and doesn't require a separate node template file which could become outdated if you updated the main node template and forgot about your custom one.

ceejayoz
+6  A: 

I'd advise against using hook_nodeapi for that. Adding CSS and Javascript is related to layout so hook_nodeapi is not the place for it: use themeing. This way, you can override those files when you're going to develop a new theme. Doing that with the nodeapi approach would be a bit harder (you'd have to search the js/css list for the files, remove them and replace them with your own).

Anyway: what you need to do is add a node preprocess function that adds those files for you. You can do this either in a module or in a custom theme. For a module this would be:

function mymodule_preprocess_node(&$variables) {
  $node = $variables['node'];
  if (!empty($node) && $node->nid == $the_specific_node_id) {
    drupal_add_js(drupal_get_path('module', 'mymodule') . "/file.js", "module");
    drupal_add_css(drupal_get_path('module', 'mymodule') . "/file.css", "module");
  }
}

or for a theme:

function mytheme_preprocess_node(&$variables) {
  $node = $variables['node'];
  if (!empty($node) && $node->nid == $the_specific_node_id) {
    drupal_add_js(path_to_theme() . "/file.js", "theme");
    drupal_add_css(path_to_theme(). "/file.css", "theme");
  }
}

Don't forget to clear the cache, first.

These functions are called before the node is themed. Specifing the js/css there allows for a cascaded approach: you can have the generic/basic stuff in the module and provide enhanced or specific functionality in the theme.

Inferis
+3  A: 

I use the preprocess functions but this has some issues. $variables['styles'] is usually set before the node preprocess function is called. In other words drupal_get_css is already called which makes you calling drupal_add_css useless. The same goes for drupal_add_js. I work around this by resetting the $variables['styles'] value.

function mytheme_preprocess_node(&$variables) {
  $node = $variables['node'];
  if (!empty($node) && $node->nid == $the_specific_node_id) {
    drupal_add_js(path_to_theme() . "/file.js", "theme");
    drupal_add_css(path_to_theme(). "/file.css", "theme");
    $variables['styles'] = drupal_get_css();
    $variables['script'] = drupal_get_js();
  }
}

This seems to work for most cases.

P.S. There's hardly any ever need to create a module to solve a theming problem.

Cheers.

canen
A: 

This seems like a good solution:

http://drupal.org/project/js_injector and http://drupal.org/project/css_injector

It works when you want to insert inline code into something other than technically a node so there's no node id and no PHP input option available. Like I used it to inject small jQuery tweaks into a couple of admin pages. It works by path rather than node id.

ninusik