Is there a definitive, universal way to do this? For example using some environment variable that comes with Drupal.behaviours
?
I have done some research and there seems to be no common answer.
As mentioned above, Drupal core has no use for the node ID on the client side so it doesn't pass it through. if you want access to it you'll need to add it manually:
function MYMODULE_node_view($node, $view_mode, $langcode) {
if ($view_mode == 'full') {
$setting = array('MYMODULE' => array('currentNid' => $node->nid));
$node->content['#attached']['js'][] = array(
'data' => $setting,
'type' => 'setting',
);
}
}
Then on the client side you'll have access to it through Drupal.settings
:
var currentNid = Drupal.settings.MYMODULE.currentNid;
class
attribute from the bootstrap theme. Ultimately we are aiming towards a theme independent solution.
Jul 8, 2013 at 12:40
$setting = array('MYMODULE' => array('currentNid' => $node->nid));
the =
is extraneous. That did the job - tacked your code onto this function that already existed in pop_links
and added your javascript in pop_links.js
.
Jul 8, 2013 at 13:27
As mentioned by MPD in his answer, working with the default css-classes Drupal generates for the element is a easy solution which works without custom PHP code.
Here is our implementation:
(function($) {
/**
* Find Drupal Node ID based on <body> element classes.
*
* @return Node ID or false
**/
function getCurrentNodeId() {
var $body = $('body.page-node');
if ( ! $body.length )
return false;
var bodyClasses = $body.attr('class').split(/\s+/);
for ( i in bodyClasses ) {
var c = bodyClasses[i];
if ( c.length > 10 && c.substring(0, 10) === "page-node-" )
return parseInt(c.substring(10), 10);
}
return false;
}
/**
* Example usage...
*
**/
Drupal.behaviors.yourModuleNameHere = {
var nodeId = getCurrentNodeId();
if ( nodeId ) {
// Node ID found.
// ...do something with it.
} else {
// Node ID not found. Guess we are not on a node page
// ...handle this case with care too.
}
}
}(jQuery);
var $body = $('body.path-node');
(tested with zurb_foundation for 8.x-6.x)
The default template_preprocess_html()
has this bit of code in in
if ($suggestions = theme_get_suggestions(arg(), 'page', '-')) {
foreach ($suggestions as $suggestion) {
if ($suggestion != 'page-front') {
// Add current suggestion to page classes to make it possible to theme
// the page depending on the current page type (e.g. node, admin, user,
// etc.) as well as more specific data like node-12 or node-edit.
$variables['classes_array'][] = drupal_html_class($suggestion);
}
}
}
This will stick on classes to the <body>
element line page-node-123
. If you don't want to use your own code in a custom module, you can get the classes via jQuery, find the one that matches page-node-
, and then parse out the nid.
What has worked for me is adding the following line to my page.tpl.php
template. This adds the node ID to window.Drupal.settings.nid
which you can use at will in JavaScript.
drupal_add_js(array('nid' => $node->nid), 'setting');
As suggested in the comments, here's the code for adding the node ID from template.php
:
function MYTHEME_preprocess_page(&$variables, $hook) {
if ($node = menu_get_object()) {
drupal_add_js(array('nid' => $node->nid),'setting');
}
}
template_preprocess_page
instead (if you need it on the page level). To not mix things up and keep the templates as clean and readable as possible. Templates should be used for markup.
drupal_add_js()
; the nid isn't ever used on the client-side by core so there's no need for it to be added as a setting usually