Node Embed: A Viable Media Management Solution for Drupal
Drupal has long struggled in the area of media management and embedding. Despite Drupal’s wide selection of media modules, none of them have matched our requirements (probably too much to ask). Media module almost tries to do too much thus being a little overwhelming and challenging to modify. The Insert and Video Embed modules, among others, attempt to solve specific use cases, but are quite limited. While developing cpr.org (Colorado Public Radio), we were able to really spend some time making Node Embed work well. While it's not without issues, I’m excited to share how we’ve used the Node Embed module at Aten to help solve our media management needs.
Node Embed allows you to embed one node into another. In this post, I’ll outline what it takes to set up Node Embed to embed images into your content. The same concept could be used for audio, video, or whatever content you can dream up to embed.
Before going any further, I want to give a shout out to Aten's Scott Reynen who is the current maintainer of Node Embed and has added some of the functionality to Node Embed mentioned in this post.
Embed an image with a caption and credit
This tutorial is based on Drupal 7.x
1. Download & enable necessary modules
I'm assuming you know how to download and enable modules.
Required Modules
- Node Embed
- Views and its dependencies
Optional modules
- WYSIWYG (Node Embed supports CKeditor or FCKeditor) WYSIWYG is not required but makes it easy for content editors to embed nodes directly from the WYSIWYG toolbar.
2. Verify text formats
- Navigate to
/admin/config/content/formats
- Edit the text format profile you want to enable Node Embed for
- Enable “Insert Node” by checking the checkbox
- You may need to experiment with Filter processing order, but should work out of the box (typically first in the list)
Note: If using with filtered html, make sure you are allowing tags!
3. Setup content types
For this example I’ll assume you have at least Basic Page and Image content types.
Basic page content type
- Title Field
- Body Field
Image content type
- Title
- Photo caption
- Credits
- Image field
4. Embed a node
After completing the first three steps, you are ready to embed a node.
- Create a new Image node (with an image of course). Take note of the NID (Node ID) after saving the node. NIDs can easily be found in the URL when editing a node. Note: If using the Node Embed button with WYSIWYG, you can avoid manually finding Node IDs.
- Create a new Basic Page node. While creating or editing the Basic Page node, embed your Image node. The format is
[[nid:(node_id)]]
Replace “(node_nid)” with your actual node ID. ex.[[nid:1]]
- Save the node. You should now have an embedded image. By default, Node Embed will use the “Default” view mode for the content you are embedding.
Your embedded content may not look exactly like you want at this point, so continue on to learn how to customize it.
Customizing embedded content
There are at least three options for taking control of your embedded content.
1. Customize the Node Embed view mode
By default, Node Embed module provides a Node Embed view mode for every content type. It just needs to be enabled. Until the Node Embed view mode is enabled, it will use the default view mode. A module like Display Suite will give you additional control over the output of your view mode.
- Visit /admin/structure/types
- Click “Manage Display” for the Image content type
- Enable Node Embed view Mode (This setting is hidden in the vertical tabs at the bottom of the page)
- Adjust the Node Embed view Mode (set image style, etc.)
2. Create a node embed template in your theme
Creating a custom node template will give you complete control over your markup.
sites/all/themes/[custom_theme]/node--[content_type_machine_name]--node_embed.tpl.php
You can put whatever html you like in your node--[content_type_machine_name]--node_embed.tpl.php
file. Here is a very simple example that will show the image field if it exists:
<?php if(isset($content['field_image'])): ?>
<figure><?php print render($content['field_image']); ?></figure>
<?php endif; ?>
Note: Using the render function will still use some view mode settings like image styles and whether labels show or not.
3. Overwrite the default view mode
By default Node Embed uses a view mode called node-embed
.
If you have a different view mode you prefer to use simply adjust your Node Embed code. For example, the following Node Embed code would use the teaser view mode.
[[nid:2 view_mode=teaser]]
Passing in custom variables
Node embed allows you to pass variables that you can access in preprocess functions and templates.
Imagine needing to easily be able to left or right align images. Your node embed code changes slightly to:
[[nid:1 align=right]]
Note: align is a made up variable. It could be anything, and same for the value right.
Accessing the Node Embed Parameter in code
You can access the parameters using the following construct in a node preprocess function.
$variables['node_embed_parameters']['align']
Add a node preprocess function to template.php
<?php
/**
* Override or insert variables into the node template.
*/
function yourthemename_preprocess_node(&$variables) {
if ($variables['view_mode'] == 'node_embed' && $variables['type'] == 'image') {
// Check to see if the align Node Embed parameter exists
if(isset($variables['node_embed_parameters']['align'])) {
// For security, run align through the check_plain() function
// Add the alignment value to the classes array used in our node template
$variables['classes_array'][] = check_plain($variables['node_embed_parameters']['align']);
}
}
}
// Closing php included only for proper highlighting in blog post
?>
Add the following to node--image--node_embed.tpl.php
<?php
/**
* $classes variable will include the alignment value of right, left or whatever is passed in
*/
?>
<figure class="<?php print $classes; ?> image-wrapper">
<?php if(isset($content['field_image'])): ?>
<?php print render($content['field_image']); ?>
<?php endif; ?>
<?php if(isset($content['body'])): ?>
<figcaption><?php print render($content['body']); ?></figcaption>
<?php endif; ?>
<?php if(isset($content['field_credits'])): ?>
<div class="image-credits"><?php print render($content['field_credits']); ?></div>
<?php endif; ?>
</figure>
Finally, add some css style.css
(or whatever stylesheet being used)
//add the potential classes that someone may use in Node Embed
.right {
float: right;
padding-left: 20px;
}
.left {
float: left;
padding-right: 20px;
}
Note: The Aten team will hopefully release our custom module that allows you to dynamically setup Node Embed Parameters and allows your users to easily insert an image with alignment, etc. Hat tip to Rob Ballou for his excellent work there. Here is a sneak peek:
The module provides "Align" and "Do not format or resize" to the Node Embed WYSIWYG insert form, making it easy to add custom parameters in a user friendly way. These options are customizable per content type.
Caveats
- Migrating content containing node embed tags would cause the embedded content to break if the node IDs don’t match on the new environment.
- Node Embed inserts custom tags into your markup
[[nid:(node_id)]]
. This won’t translate well if ever migrating away from Drupal or Node Embed.
Troubleshooting
- If just
[[nid:(node_id)]]
is outputting to the screen, make sure the node you are embedding exists and is published. - Double check text formats to make sure Node Embed tags (image tag included) are getting processed and not filtered out
Call for Comments
What are your thoughts on this approach to media handling in Drupal? What else has or hasn't worked for you?