Drupal: Installing a WYSIWYG editor that lets users insert images

WYSIWYG stands for “what you see is what you get.” Here’s a WYSIWYG editor:

WYSIWYG content creation interface

Figure 1. WYSIWYG content creation interface

Users see the buttons, and they know what to do. Click the B button, get bold text. They’ve seen buttons like this in word processors, spreadsheets, and so on.

Here’s a non-WYSIWYG editor:

Normal content creation interface

Figure 2. Normal content creation interface

The editor in Figure 2 is just a standard HTML <textarea>. Average nontech people have no idea what to do.

Drupal 6 does not have a WYSIWYG editor out-of-the-box. This article explains how you can install one.

The tutorial not only tells you what to do, but explains why you do it. The tutorial goes into some depth about input formats, filters, and other Drupal mysteries.

Drupal is complex. The people who created Drupal have built thousands of business Web sites between them. For small companies, large companies, non-profits, manufacturing companies, service companies, universities, governments, ... you name it, they’ve done it. They made Drupal a flexible system. Its architecture lets you create sites to serve many different business goals.

The better you can configure Drupal to fit the needs of a company, the more value you have to that company. That means understanding businesses – goals, value propositions, different jobs, different skill levels, etc. And understanding Drupal. And being able to fit the two together. Hopefully, this tutorial will show you an example of that.

If you’re in a hurry and just want “click-this-and-then-click-that,” you may want skim past the “why” bits. Come back when you want to build deeper skills.

Why bother with WYSIWYG?

The goal is to make it easier for people without technical training to create content for a Drupal site. Why bother? So that:

Site content can be maintained by the most expert people in the company.

This is not about technical expertise, but about content expertise. Marketing people write marketing content, HR people write HR content, public relations people write press releases, and so on. Like this:

Matching site and organization architectures

Figure 3. Matching site and organization architectures

A site organized this way can serve the business well.

  • Marketers can set up the messages they want. They can quickly experiment with wording, formatting, layout, and images. Marketing is done better.
  • The service people can experiment with different ways of organizing self-service information, setting up service appointments, ordering spare parts, etc. Service is done better.
  • The HR people can experiment with different ways of publishing job openings, enticing the best applicants, managing applications, listing benefits options, etc. HR is done better.

The whole site fits business goals. It’s more agile as well. Changes can be made quickly by the people who best know what changes to make.

There’s coordination, of course. There is a standard look-and-feel for the site, for example. The Weber does that.


Sometimes it’s best for specialists to create specialized sites. For example, a microsite (a small, short-lived site) for a social media campaign might be maintained by social media experts working in consultation with the company’s marketers, rather than by the marketers themselves.

In this article, I’ll stick to a company’s main Web site. It usually serves many business goals.


When people in the functional areas (marketing, accounting, etc.) maintain their own content, many issues come up. The most important are:

  • Making it easy for those people to create content.
  • Setting security policies, so that Evil Doers can’t enter Evil Content.

Drupal’s flexible architecture means it can handle all sorts of situations. Including exceptions. For example, most marketers want to do WYSIWYG, but one wants to write raw HTML. No problem. You can set that up.

Keep these business issues in mind as we go. You’ll see how Drupal can make it all work.

The goal

We want to let users create content easily, and be able to insert images.

It’s all HTML

Here’s someone writing content with a WYSIWYG editor:

Creating content with a WYSIWYG editor

Figure 4. Creating content with a WYSIWYG editor

But Drupal stores raw code in its database, usually just HTML. So what good are WYSIWYG editors to Drupal? This is the secret:

A WYSIWYG editor takes what the user does and converts it into HTML.

The content in Figure 4 could have been created this way:

Creating content without a WYSIWYG editor

Figure 5. Creating content without a WYSIWYG editor

With or without the WYSIWYG editor, Drupal gets HTML. A WYSIWYG editor makes it easier to write HTML.

Including images

We want to let people include images in their content, without knowing much about the tech.

We want to give users an easy “mental model” for inserting images. That is, regardless of where images are actually stored and how they are handled, we give them an easy way to think about how they insert images.

There are two basic approaches.

First, users see images as separate from the pages they create. They upload images to a directory. Then they navigate to the directory, and insert images.

Images are separate from pages

Figure 6. Images are separate from pages

If they create a new page and want to use the same images, they don’t upload again. They just insert the existing images.

In the second model, users think that images are tied to a single page.

Images specific to a page

Figure 7. Images specific to a page

If they create a new page and want the same images, they upload the images again. So there are two copies of the brown and purple images on the server’s disk drive.

The first approach uses disk space and network bandwidth more efficiently. It also means that if a user changes one of the images, all pages that use the image will change automatically. That can save time. Or cause havoc.

The second approach is less technically efficient. Multiple copies of the same images are stored, one for each time the image appears.

I’m going to use the second approach, for two reasons. First, some nontech users have a hard time with directories. They can type, do bolding, headings, etc. But directories are more abstract, and they have trouble using them.

The second reason is that people have to be organized to use directories well. They have to decide which files go where, know where to look for existing images, and so on.

In real companies, things get disorganized. The image directories become more and more chaotic over time. Especially when people are switching jobs, and forget to document what images go where.

This leads to the havoc mentioned above. Suppose someone looks at a page, and decides that a photo should be larger. She makes a new larger image, and uploads it, replacing the existing image. She checks the page, and all is good.

What she doesn’t know is that the original image was also used on three other pages. The layout of those three pages could be broken.

So, each page will have its own images. That will cause duplication. But the inefficiencies from duplication will probably cost less in the long run than the problems caused by sharing images across pages.

Each page will have this on it:

Uploading an image

Figure 8. Uploading an image

Click the Browse button, find an image to upload, and then see:

Image uploaded

Figure 9. Image uploaded

That’s me in the snow. The red thing is a halter. Fashionable, no?

Click the Insert button to get:

Image inserted

Figure 10. Image inserted

The user can drag the image around in the editor, and even resize it:

Resized image

Figure 11. Resized image

We end up with an editor that’s easy to use. It lets users add and resize images. W00f!

So, that’s the goal. How do we get there?

We’ll look at the solution in two chunks:

  • Installing the editor
  • Allowing image insertion

Installing the editor

Let’s start with Drupal 6, a vanilla install.


Well, almost vanilla. I added the Administration menu module to make things easier. That’s the first module I install on every site.


We’ll use the WYSIWYG module. It’s a “glue” module. It doesn’t offer WYSIWYG tools itself. Instead, it acts as a go-between, letting WYSIWYG tools work in Drupal.

WYSIWYG module is glue

Figure 12. WYSIWYG module is glue

“Editor library” means the code for an editor. There are many WYSIWYG editors available: TinyMCE, CKEditor, NicEdit, and so on. Each editor has a set of HTML, CSS, and JavaScript files that make it work. There are usually other files as well, like images and documentation.

The WYSIWYG module lets you choose which editor you add to your site. You can choose more than one, if you like.

Several editors installed

Figure 13. Several editors installed

The WYSIWYG module is flexible. Maybe it’s more superglue than glue.

So, we install the WYSIWYG module. Here’s what we see on the module page:

Modules page

Figure 14. Modules page

But the module doesn’t install any editors by itself. So this is the current situation:

No editors

Figure 15. No editors

Go to Administer > Site configuration > WYSIWYG. (When I show a sequence like this, I mean “Click on Administer, then Site configuration, then WYSIWYG.”) You’ll see this:

No editor libraries

Figure 16. No editor libraries

We have to download and install one or more editors.

Let’s install CKEditor. Here are the instructions from the WYSIWYG module, at Administer > Site configuration > WYSIWYG:

CKEditor installation instructions

Figure 17. CKEditor installation instructions

Click the download link, and see:

CKEditor download

Figure 18. CKEditor download

Download the zip (or the tar.gz, doesn’t matter) to your computer, and extract it. You get all the CKEditor files in a directory:

CKEditor directory

Figure 19. CKEditor directory

Now upload the files to your server. It’s important to put the editor library in the right place, so the WYSIWYG module can find it. Here are the instructions again:

CKEditor installation instructions

Figure 17 (again). CKEditor installation instructions

Start your file transfer client (I use WinSCP), and create the direcory sites/all/libraries. Notice that the directory is called libraries, not library.

Upload the ckeditor directory to the new directory.

Directory uploaded

Figure 20. Directory uploaded

It might take a while. The CKEditor file set is fairly large.

Now go back to Administer > Site configuration > WYSIWYG. This time, you’ll see:

No editor assigned

Figure 21. No editor assigned

If you still get a message about the WYSIWYG module not knowing about any libraries, make sure you have uploaded the CKEditor directory to the right place. It should be under all/sites/libraries.

To make sense of the next few steps, you need to understand about input formats and input filters. Let’s take a look.

Configuring input formats and filters

The input format system can seem complicated at first. But you won’t be able to manage your site completely unless you understand input formats.

Let’s start by talking about the business problem we need to solve. On a typical Web site, some people create content, and other people view it. Like this:

The content cycle

Figure 22. The content cycle

The content creator types content into a browser (1 in Figure 22). Drupal writes the content to a database (2). Later, a user asks to see that content. Drupal loads the content from the database (3), and sends it to the user (4).

What type of data is the content? Usually just HTML:

Basic HTML

Figure 23. Basic HTML

The user sees:

Basic HTML output

Figure 24. Basic HTML output

By the way, I’m about to start using the term “node.” For this tutorial, a node is a Web page. The two aren’t strictly equivalent. But, for now, when I say “node,” think “Web page.”

Two problems

The Drupal administrator has two problems:

Problem 1: How to make it easy for unskilled people to create content, and at the same time not restrict skilled people unnecessarily. This is on the left side of the content cycle. You do this by giving different people different types of editing interfaces.

Problem 2: How to protect users (on the right side of the content cycle) from Evil Content Creators. You do this by restricting what nodes can show to users. Content created by untrusted people is checked before being shown to a user. Evil Code is stripped out.

Remember, in a real company, you need flexibility here. Most marketers would want a WYSIWYG editor. However, there will always be one or two marketers who are taking night classes in HTML. They’ll want to do things that the WYSIWYG editor might not support, like creating custom CSS classes. You’ll need to give the marketers the option to enter raw code, if they want.

Would the marketers create Evil Content? Probably not. They’d get fired.

So for the marketers:

  • Content creation interface: WYSIWYG editor, with a raw HTML option.
  • Security output filter: permissive.

Now suppose that random people on the Web can enter comments on product pages. You don’t know the skill level of these people, so you give them a simplified WYSIWYG editor, with just a few options, like bolding and italics.

You do know that human Evil Doers are out there. Some know HTML, CSS, and JavaScript, better than you do. For them:

  • Content creation interface: simplified WYSIWYG editor only. No raw HTML option.
  • Security output filter: Restrictive

The company will have two or three trusted supergeeks. They’re the ones people call when something is broken, and they can’t figure out what to do. They need a complete WYSIWYG editor, and a raw HTML option. They get to make any content they want, including arcane jQuery to handle a browser bug in the off-brand smart phone the CEO bought on her last trip to Korea.

  • Content creation interface: complete WYSIWYG editor, plus raw code.
  • Security output filter: None.


Drool-worthy Drupal

This complexity – input formats, filters, flux capacitors – gives Drupal a Bad Name with beginners. Frankly, if you just want a site to show off your bone collection, maybe you should use something easier, like WordPress.

But real companies are complex. Not just big corps, either. Small companies, too.

You have to deal not only with what the Web site does for users, but how content is created and managed. You have people all over the company who have good reasons to manage their own content. Marketers, sales reps, accountants with financial statements, HR people who want to post job openings, public relations people with press releases, customer service people and their product maintenance updates, ... The list goes on. And on. And on.

With Drupal, you can accommodate all these business goals. You don’t have to say, “Er, the software won’t let us do that.” You can have great value for the company, because you can make the Drupal site an integral part of the way the company does business. (Then ask for a big raise.)

So, even though these things are complex, learn them. You’ll be part of a business solution, not a technical problem.


Input formats stored with content

When we talked about the content cycle earlier, you saw that Drupal stores content in its database, and retrieves it when a user asks:

Storing content

Figure 25. Storing content

There’s a little more to it. Drupal stores other data along with the content:

Storing content and other stuff

Figure 26. Storing content and other stuff

One of the things that’s stored is the input format used with the content. So whenever there’s content in a node, there’s an input format for it.

Every node uses exactly one input format at any one time. Some users have permission to apply more than one input format to a node. But only one at a time. They select a format from a list. If there are eight input formats they could use, they can select just one at a time.

When the node is stored in the database, the current input format is stored along with it. Next time the node is edited, Drupal will use that input format. If the user changes to a different format for that node, the new format will be stored with the node when it is written to the database.

Where input formats apply

Remember that in a typical installation, you need to control:

  • The interface used by the content creator.
  • The filters applied to the output.

In out-of-the-box Drupal, input formats control only the output side. (Yes, input formats really control output.) When you add the WYSIWYG module, input formats become more powerful. They control both the input interface and the output filtering.


Purists might object to my putting these two together. I just find it helpful to think of it this way.


WYSIWYGed input formats fit into the content cycle like this:

Content cycle with input format

Figure 27. Content cycle with input format

You can improve the input side by adding WYSIWYG. Fair enough. But let’s look at the output side a little more.

Foiling Evil Doers

Suppose the content creator is Evil. (Of course, dogs are never evil, unlike some bipeds I could name, so you’ll have to use your imagination.) The content creator types this:

Evil code

Figure 28. Evil code

The user would see:


Figure 29. Alert

It might be rare for an employee to enter Evil Code. But if you let random people on the Internet enter content – add comments, for example – then you need to guard against this.

A filter is a short program that looks at content before it is shown to the user, and alters it. For example, in Figure 30, a filter could strip out everything between <script> and </script>.

Not all filters are for stripping out Evil Content. Filters can also make content easier to create, or a site easier to manage. For example, I might write a filter that looks for [product-support-telephone] and converts it to 1-800-666-6666. Then I tell content writers to type in [product-support-telephone] when they want to include the product support telephone number in their content. For example:

Entering the product support telephone number

Figure 30. Entering the product support telephone number

Site users would see:

Telephone number

Figure 31. Telephone number

Why do this? Suppose the company starts selling zombies in Canada. Canadian zombies have reduced aggression, and an optional second language module. There’s a different telephone number for support in Canada. I change my filter to replace [product-support-telephone] with “1-800-666-6666 (US), or 1-800-777-7777 (Canada).” This change happens automatically across the entire site, without editing a single page. W00f!

We need a name for this filter. Let’s call it “Placeholder filler.”


This is similar to what Drupal’s Token module does.


There are many other useful filters. The URL filter – part of default Drupal – converts URLs users type into clickable text. Right now, I’m writing with Textile syntax, thanks to the Textile module.

A filter by any other name

So, filters control output. When a user asks for a page, data is taken from the database and sent through the filters. Only data that makes it through the filters is displayed.

So you’d think that they’d be called “output filters,” right? Actually, Drupal calls them “input filters,” since they filter a user’s input. But the filtering isn’t actually done when users input data. Drupal stores in the database exactly what users enter, including Evil Code. Input filters are applied when content is read from the database and output to the user.

I’ll remind you of this by calling them “output (called input) filters.”

So what is an input format, really?

Think of a WYSIWYGed input format as a combination of:

  • A WYSIWYG editor and a configuration. The configuration specifies, for example, what buttons to show on the editor’s toolbar.
  • A collection of output (called input) filters. They alter data that flows through them.

Structure of a WYSIWYGed input format

Figure 32. Structure of a WYSIWYGed input format

Here are three input formats, matching requirements we talked about earlier. The first one is for people we don’t trust at all. They might be Evil Humans.

Input format: Untrusted

Editor: CKEditor

Configured buttons: Bold, italic, ordered list, unordered list. No raw HTML option.


Restrict HTML – only allow <p>, <br/>, <strong>, <em>, <ul>, <ol>, <li>

URL filter – convert URLs into clickable links.

Here’s the same thing as a graphic:

Input format: Untrusted

Figure 33. Input format: Untrusted

The next input format is for employees who create content, like the marketers.

Input format: Content creator

Editor: CKEditor

Configured buttons: Bold, italic, strike-through, ordered list, unordered list, left, center, and right align, indent, outdent, undo, redo, link, image, fore color, back color, cut, copy, paste, font, font size, remove format, check spelling. Raw HTML option.


Restrict HTML – filter out <script>. Users have to ask for permission for this one. We’d also want to strip out <applet>, <object>, and other tags that might allow Evility.

URL filter – convert URLs into clickable links.

Placeholder filler – replace company-specific placeholders, like [product-support-telephone].

Here’s the same thing as a graphic:

Input format: Content creator

Figure 34. Input format: Content creator

Now for the last input format, for the trouble-shooting geeks:

Input format: Geek

Editor: CKEditor

Configured buttons: Everything. Raw HTML option.


URL filter – convert URLs into clickable links.

Placeholder Filler – replace company-specific placeholders, like [product-support-telephone].

Here’s the same thing as a graphic:

Input format: Geek

Figure 35. Input format: Geek

Roles, too

Often, you create input filters for each user role. A role is a category of user that has a given set of permissions.

Let’s do that here. We’ll give anonymous users the Untrusted input format. We’ll make a role called “Content creator,” and give it the Content creators input format. Finally, we’ll make a role called “Geek,” and, of course, give it the Geek input format.


Notice that, once again, Drupal’s flexibility lets us apply the exact business policies we need. W00f for Drupal!


Configuring the WYSIWYG

OK, let’s review. You’ve installed the WYSIWYG module, and CKEditor. You know that input formats (1) give content creators a nice interface (input side), and (2) filter out Evil Code (output side). That was a long side trip into the world of input formats. But worthwhile.

On with the hands-on.

Drupal creates two input formats when you install it:

  • Filtered HTML
  • Full HTML

If you go to Administer > Site configuration > Input formats, you’ll see:

Starting input formats

Figure 36. Starting input formats

Filtered HTML is the default. When you create a new node, that is the input format Drupal will use.

Let’s implement the three input formats we came up with earlier: Untrusted, Content creator, and Geek. Let’s start by renaming the Filtered HTML format to Untrusted. I’ll click on Configure next to Filtered HTML (Figure 36).

Filtered HTML options

Figure 37. Filtered HTML options

I’ll change the name to Untrusted.

Because this is the default filter, it is available to all roles. That’s why the roles selection is disabled.

We haven’t hooked the WYSIWYG module up to any input formats yet, so we can’t set up the editor. But we can specify the output (called input) filters.


Figure 38. Untrusted

Recalls that one of the filters limits which HTML tags can be shown to the user. Drupal calls the HTML filter. Argh! “Filtered HTML” and “HTML filter” are different things, but their names are so similar! Sigh.

Let’s turned on two extra filters that come with base Drupal: HTML corrector and Line break converter. They’re not in our specification, but they’re useful. Don’t forget to click Save.

Now we need to configure the HTML filter, to tell Drupal what HTML tags are allowed for this input format. On Administer > Site configuration > Input formats, click the Configure link for Untrusted, and then the Configure tab. Here’s how we change the settings:

Configuring Untrusted

Figure 39. Configuring Untrusted

The tag list contains the tags in the spec, plus one more – <a>. The URL filter changes URLs into <a> tags, so we need to let them through.

Turn off HTML help. Anonymous users (who use the Untrusted input format) aren’t typing HTML anyway.

Don’t forget to Save.

Now to create the other input formats: Content creator and Geek. Remember that each needs a role as well. It’s a little easier to create the roles first, so that’s what we’ll do, at Administer > User management > Roles:


Figure 40. Roles

At Administer > Site configuration > Input formats, click Add input format, and create this:

Content creator

Figure 41. Content creator

Notice that we’ve let the Geek role use the Content creator input format. Why? So geeks can see the same display that content creators do, and figure out where content creators might be having problems.

We need to configure the filters for this input format. But there’s a problem, so we’ll come back to it.

Here’s the last input format:


Figure 42. Geek

Notice that the HTML filter has been turned off. Geeks can do anything. The Geek filters don’t need any configuration.

Now we have the following filters:

Extra input format

Figure 43. Extra input format

We have an extra one there: Full HTML. Delete it. Then we’ll have:

List of input formats

Figure 44. List of input formats

Filtering problems

Remember I said there are problems with the Content creator input format? They have to do with filtering.

We want to allow Content creators to use anything but the <script> tag. The standard HTML filter lets us specify what tags people are allowed to use, not what they cannot use.

Another problem has to do with CSS styles. We want to allow Content creators to use the WYSIWYG editor to do things like set the color of text. Remember that WYSIWYG editors write HTML. The way they normally represent colors is to write HTML with inline CSS styles, such as:

<p>I <span style="color:red;">love</span> dogs.</p>

We can tell the standard HTML filter to let <span> through, but not to let any attributes like style through. They’ll get stripped out.

Argh! What are we to do?

There are several options. One is to change the specification. Remove the <script> filtering requirement from the spec. Then we could turn off the standard HTML filter altogether. So we ask the specers (the people who wrote the spec) whether the restriction was necessary. If they’re in a good mood, they’ll say, “OK, you can take that out.”

But they’re grumpy today. They refuse to change the spec. What now?

A more powerful HTML filter

As usual, there’s a module for that. In fact, there are several we could use. They offer more flexibility in building HTML filters.

The WYSIWYG Filter is handy. It gives you a lot of control over what HTML tags and attributes you allow through.

Download, install and enable the WYSIWYG Filter module. Go to Administer > Site configuration › Input formats. Click Configure next to the Content editor input format:

List of input formats

Figure 45. List of input formats

Turn the HTML Filter off. Turn the WYSIWYG Filter on.

Now let’s configure the filter. Click on the Configure tab, and scroll down to the WYSIWYG Filter section. Remember that we want to disallow <script>, <applet>, and other tags that could allow attacks. It turns out the WYSIWYG Filter won’t allow those tags anyway. W00f!

WYSIWYG Filter is a “whitelist” filter. That is, you explicitly tell it what tags and attributes you want to allow. What do we want to allow? All the code that CKEditor generates, when users use the features we want to allow. How do you what CKEditor does? You can RTFM, experiment, or just let a lot of stuff through. I tend to use the last approach.

Here are the settings we’ll use for this tutorial:

WYSIWYG Filter settings

Figure 46. WYSIWYG Filter settings

Don’t forget to check all of the boxes under Style properties.

I won’t go over the settings in detail. You can check the docs, on the module’s Drupal page.

These settings are more permissive than we need. But they won’t allow destructive stuff through, so it does what we want.

So, we have three roles, and three input formats. We’ve set up the output (called input) filters, to implement the security settings, the Placeholder filler (recall that makes it easier to change things like phone numbers site wide), and some other convenience things.

Now let’s tie the WYSIWYG module to each input format. W00f!

Attaching WYSIWYG configurations to input formats

Here’s what you’ll see at Administer > Site configuration > WYSIWYG:

No editor assigned

Figure 47. No editor assigned

None of the input formats has a WYSIWYG editor associated with it. Let’s change each of the dropdowns to CKEditor, and click Save:

Editors selected

Figure 48. Editors selected

Let’s configure each input format separately, so we can activate different editor features for each format.

Click Edit for the Untrusted input format, and see:

Starting to configure the untrusted input format

Figure 49. Starting to configure the untrusted input format

There are a bazillion options. I’ll cover the most useful.

In the Basic setup section, make sure Show enable/disable rich text toggle link is off. People using this input format will only have the WYSIWYG editor available. They won’t be able to enter straight HTML.

No disabling WYSIWYG

Figure 50. No disabling WYSIWYG

Activate the following editor features:

Active buttons for the Untrusted input format

Figure 51. Active buttons for the Untrusted input format

This matches our earlier specification.

Here is the CSS section:

What CSS should the editor use?

Figure 52. What CSS should the editor use?

You need to decide what CSS the editor should use when the user is editing a page. Try using the theme CSS first. If it works, the styles the content editor sees when using the WYSIWYG editor will be the same ones the site user sees when looking at the page.

Unfortunately, I rarely find that the theme CSS works well. The theme CSS was designed for reading the site, not writing content in an editor. I almost always end up using the editor’s default CSS.

Now click the Save button, and you are returned to:

Editors selected

Figure 48 (again). Editors selected

Now for the Content creator input format. People using this format are allowed to enter raw HTML. So:

Content creators can enter raw HTML

Figure 53. Content creators can enter raw HTML

Here are the buttons for this input format:

Content creator buttons

Figure 54. Content creator buttons


You can take this opportunity to encourage good practice. For example, we haven’t enabled the text underlining button. Why? Because site users expect underlined text to be a link. Since underlining plain (non-link) text is bad practice, we omit the button.


The Geek input format is the easiest to set up. Let Geeks disable the editor so they can enter HTML. Leave all the controls unchecked. When you don’t check anything, all the buttons appear.

Setting up the Geek input format

Figure 55. Setting up the Geek input format

Let’s try it. Here’s the editor for the Untrusted input format:


Figure 56. Untrusted

That’s what we want. Just a few buttons. No “Disable editor” link. W00f!

Here the Content creator input format:

Content creator

Figure 57. Content creator

More buttons, more formatting options. And a “Disable editor” link, to switch to HTML.

Now here’s the Geek format:


Figure 58. Geek

Time for a w00f.


But we’re not done yet. Now we need to add image support.

Adding image support

You’ll need to download some modules. Quite a few:

  • CCK – lets you add new fields to content types. It has a bunch o’ modules. Enable at least the Content module.
  • FileField – lets you add CCK fields that store files. It has more than one module. Enable at least FileField.
  • ImageField – lets users upload images into those file fields. Enable it.
  • Insert – lets users insert image file references into the WYSIWYG editor. Enable it.
  • Image Resize Filter – lets users resize the images they have inserted. Enable it.


If you do much Drupal work, you should get to know Drush. Among other things, it makes installing modules a lot easier.

Take FileField. I could have gone to FileField’s page on drupal.org, downloaded the module, extracted the files, uploaded them to my server, and then visited Administer > Site building > Modules to enable the module. Instead, this is what I did:


Figure 59. Drush

I typed the text that’s underlined in red. My server’s Unix command shell showed the test. It took me maybe 20 seconds to install FileField.

Drush takes time to get used to, especially if you are new to the command line. But if you do much Drupal work, the time you spend learning Drush will be returned many times over.


All set? W00f!

CCK is one of the most important Drupal modules. It lets you add fields to content types.

Time for a detour. To see how CCK can help you do business.

Suppose your company rents out vacation cabins. It would be nice if each cabin had a Web page, listing its size, how many beds there are, what the kitchen facilities are like, some photos, etc.

With Drupal, you can create a “content type” called Cabin. A content type is a node that specializes in one particular type of Web page, like a page about a cabin. The Cabin content type starts out with the same fields as a regular page. Title, body, and some others. You add more fields, like:

  • Location
  • Price per week
  • Number of beds
  • List of appliances
  • Type of boat dock
  • Distance to camp store
  • Photos

You now have a Web page that describes a specific type of business object. There’ll be one of these pages for each cabin.


If you’re a database person, you’ll recognize that content types are like entities. Each Web page is an instance.


You can create content types for Boats, Staff, Customers, etc. You can link instances to each other. For example, you can list boats that can be rented with each cabin, by linking boat nodes to cabin nodes.

You might say to yourself, “Self, I could just type this stuff into a regular Web page.” True, but with CCK and the Views module, you can generate reports, showing, for example, current vacancies. Or a list of the boat types, or vacancies next summer, or whatever. All the reports about cabins will be updated automatically when the data about any cabin is changed.

If you’re a geek, this is exciting stuff. What can I say. We like good tech.


If you’re a business-casual-wearing corporate IT type, you should pay attention to Drupal and content types. Simple data modeling, with a completely integrated Web interface. Drupal handling the keys and other messy bits. You (and your clients) think at the business object level, not at the RDBMS level.

Doesn’t it make you just droooool.


We’re going to use CCK a little differently. We’re not going to create any new content types. Instead, we’re going to add an image field to the existing Page content type. We’ll let users store an unlimited number of images with each node.

This is what we’ll end up with:

Image insertion widget

Figure 60. Image insertion widget

Go to Administer > Content management > Content types, and see that CCK has added a new option, “manage fields:”

Manage fields

Figure 61. Manage fields

Click on that, and you’ll see a form that lets you add fields to the Page content type. Enter the following:

Adding an image field

Figure 62. Adding an image field

Let’s see how this stuff maps to what the user will see. Here’s a reminder of the user’s interface:

Image insertion widget

Figure 60 (again). Image insertion widget

Starting from the left of Figure 62, the first thing is the label. You can see that at the top of the widget in Figure 60. The next thing is the internal name of the field. The user doesn’t see that.

The third thing is the type of data that is stored in the field: a file. The user doesn’t see this directly. But by telling CCK that we want to store a file, that affects the fourth thing: how to let the user tell Drupal which file to store. We selected “Image” here (Figure 62). That creates the type of form element in Figure 60, with a Browse button, an Upload button, and other things.

Click the Save button (Figure 62), and Drupal/CCK asks for more details about the field. There are many settings. I’ll only show the ones I’m going to change:

Image field settings

Figure 63. Image field settings

The help text goes at the bottom of the widget.

Make sure Enable insert button is checked. This is what the Insert module provides. It lets the user add images into the body.

We want to let the user insert any number of images. Set the Number of values to Unlimited. Then save the settings.

Once you have created the image field, you can reuse it on any other content type. Story, Cabin, whatever.


If you are using CCK’s Content Permissions module, don’t forget to set permissions appropriately.


We’re almost done.

Enable the Image Resize Filter module if you haven’t already. Here’s Administer > Site building > Modules:

Enable Image Resize Filter module

Figure 64. Enable Image Resize Filter module

Go back to Administer > Site configuration > Input formats:

List of input formats

Figure 44 (again). List of input formats

Click on the configure link for Content creator, and enable the Image resize filter:

Enable filter

Figure 65. Enable filter

Do the same for the Geek format.

Go to Administer > User management > Permissions, and make sure Content creator and Geek can create and edit pages:


Figure 66. Permissions

Let’s try it. Create a Content creator user, if you don’t have one. Log is as that user.


I usually open more than one browser when working with Drupal. For example, I’ll be admin in Chrome, and Content creator in Firefox. So I don’t have to keep logging in and logging out of one browser to test things.


Create a new page. The user has access to two input formats, Untrusted and Content creator. Select the Content creator input format to see lots of editor buttons.

You should be able to upload an image:

Uploaded a bird image

Figure 67. Uploaded a bird image

Then insert it into the page, and resize it:

Resizing the bird

Figure 68. Resizing the bird

W00f! W00f! W00f! It’s all perfect! Yes!

Let’s save that and look at the page.

The bird page

Figure 69. The bird page

Nooooooooo! By all that’s holy, nooooooo!!

Tail hanging. Head down. Dog dejection.

Why is the bird photo showing up twice?

First, calm down. Take a deep, slow breath. It really does help. In….. out….. in….. out…..

OK, let’s see what’s going on.

Click Edit for the bird page. You’ll see two photos of Jill (that’s the bird):

Two photos in edit mode

Figure 70. Two photos in edit mode

Let’s think back to what CCK does. It lets you add fields to a content type. For example, you could make a content type called Cabin, and add Number of beds to it.

You do this because you want users to see the number of beds when they look at a cabin’s page. It wouldn’t make any sense to hide it away.

But our situation is different. We use the Images field as a storage place for images. We show them by inserting them into the page as needed. We don’t want to show the Images field itself. Only the page body, with the images inserted.

CCK can handle that. Go to Administer › Content management > Content types and click on manage fields for the Page content type:

Manage fields

Figure 61 (again). Manage fields

Then click on Display fields:

Display fields

Figure 71. Display fields

Check the Exclude boxes:

Exclude from display

Figure 72. Exclude from display

This tells CCK not to show the Images field when showing either the teaser or the full node. Don’t forget to Save.

Do the same for the Page’s other display contexts: RSS and Token.

OK, now go have a look at the bird page.

Finished bird page

Figure 73. Finished bird page

At last! All is w00fy in the land of WYSIWYG.

Try other stuff when you’re in edit mode. You can drag the image around in the text. You can right-click on the image, and make it float left or right. You can set the spacing betwixt the image and the surrounding text. What coolness!

The end

This tutorial covers one of the more complex things you normally do with Drupal. To understand what’s going on, you need to understand the Drupal Way. Input formats, output (called input) filters, and other stuff.

You should try for this level of understanding. You’ll be able to apply Drupal to more use cases. You’ll increase your value to clients and employers. And you’ll be able to swagger at the next Drupal meetup.

Let me know if you have any questions, or suggestions for improving the tutorial, at kieran@coredogs.com.


How to...