Drupal: Installing a WYSIWYG editor that lets users insert images
UPDATE: If you have trouble with the CSS created by your WYSIWYG editor, see Drupal: Limit WYSIWYG editors.
WYSIWYG stands for “what you see is what you get.” Here’s a WYSIWYG editor:

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:

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:

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.
<aside>
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.
</aside>
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:

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:

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.

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.

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:

Figure 8. Uploading an image
Click the Browse button, find an image to upload, and then see:

Figure 9. Image uploaded
That’s me in the snow. The red thing is a halter. Fashionable, no?
Click the Insert button to get:

Figure 10. Image inserted
The user can drag the image around in the editor, and even resize it:

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.
<aside>
Well, almost vanilla. I added the Administration menu module to make things easier. That’s the first module I install on every site.
</aside>
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.

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.

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:

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

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:

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:

Figure 17. CKEditor installation instructions
Click the download link, and see:

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:

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:

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.

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:

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:

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:

Figure 23. Basic HTML
The user sees:

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.
<aside>
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.
</aside>
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:

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

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.
<aside>
Purists might object to my putting these two together. I just find it helpful to think of it this way.
</aside>
WYSIWYGed input formats fit into the content cycle like this:

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:

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:

Figure 30. Entering the product support telephone number
Site users would see:

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.”
<aside>
This is similar to what Drupal’s Token module does.
</aside>
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.

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.
Filters:
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:

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.
Filters:
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:

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.
Filters:
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:

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.
<aside>
Notice that, once again, Drupal’s flexibility lets us apply the exact business policies we need. W00f for Drupal!
</aside>
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:

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).

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:

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:

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:

Figure 43. Extra input format
We have an extra one there: Full HTML. Delete it. Then we’ll have:

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:

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:

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:

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:

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:

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.

Figure 50. No disabling WYSIWYG
Activate the following editor features:

Figure 51. Active buttons for the Untrusted input format
This matches our earlier specification.
Here is the CSS section:

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:

Figure 48 (again). Editors selected
Now for the Content creator input format. People using this format are allowed to enter raw HTML. So:

Figure 53. Content creators can enter raw HTML
Here are the buttons for this input format:

Figure 54. Content creator buttons
UPDATE: Turning all these things on might work poorly with your theme. If you have trouble with the CSS created by your WYSIWYG editor, see Drupal: Limit WYSIWYG editors.
<aside>
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.
</aside>
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.

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:

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.
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.
<aside>
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 > Modulesto 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.
</aside>
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.
<aside>
If you’re a database person, you’ll recognize that content types are like entities. Each Web page is an instance.
</aside>
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.
<aside>
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.
</aside>
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:

Figure 60. Image insertion widget
Go to Administer > Content management > Content types, and see that CCK has added a new option, “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:

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:

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:

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.
<aside>
If you are using CCK’s Content Permissions module, don’t forget to set permissions appropriately.
</aside>
We’re almost done.
Enable the Image Resize Filter module if you haven’t already. Here’s Administer > Site building > Modules:

Figure 64. Enable Image Resize Filter module
Go back to Administer > Site configuration > Input formats:

Figure 44 (again). List of input formats
Click on the configure link for Content creator, and enable the Image resize 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.
<aside>
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.
</aside>
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:

Figure 67. Uploaded a bird image
Then insert it into the page, and resize it:

Figure 68. Resizing the bird
W00f! W00f! W00f! It’s all perfect! Yes!
Let’s save that and look at the 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):

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:

Figure 61 (again). Manage fields
Then click on Display fields:

Figure 71. Display fields
Check the Exclude boxes:

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.

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.
What an excellently written tutorial.
I was browsing, looking for comparisons on the wysiwyg editors out there, and came across this page.
This is so freakingly well done. Lots of great info, excellent verbal style, good pictures, everything.
I've got my own notes on how to do all this stuff, but the way you have written it up was pretty damn good.
I've bookmarked it.
Thank you!
-johnc
What John Said.
Great write up, thank you. It explained so much that I suffered through without learning. Now it all makes so much more sense. I have no idea what the dog thing is about, but if it helps you keep writing content like this, roll on.
Wow this excellent
Thank-you so much. They way you write is so accessible for the reader - I like the way you recap.
woof :-)
Choose images from server
Great tutorial.
Thanks. One thing I could not find is a module that allow a user to see which images have already been uploaded to server when adding an image through a CCK field, instead of uploading it again. Sorry my bad English. I hope I got to explain my doubt? Thanks in advance.
Andre
Andre, That would be a good
Andre,
That would be a good module.
You could use a file manager. One that works with CKEditor is CKFinder. This page…
http://drupal.org/node/728210
...is about using CKEditor and CKFinder with Drupal. I haven’t tried it myself.
Kieran
Really great
VERY helpful, especially like the way you use the image of the user interface we are shooting for to orient the reader as you go. (One prob I ran into -- don't get the nice handles on the image for resizing, have to resize via image properties...)
Aye, that's a problem with
Aye, that's a problem with Chrome and Safari. Both are based on WebKit, an open source browser engine.