- •Contents at a Glance
- •Contents
- •Foreword
- •About the Authors
- •About the Technical Reviewers
- •Acknowledgments
- •Introduction
- •How Drupal Works
- •What Is Drupal?
- •Technology Stack
- •Core
- •Administrative Interface
- •Modules
- •Hooks
- •Themes
- •Nodes
- •Fields
- •Blocks
- •File Layout
- •Serving a Request
- •The Web Server’s Role
- •The Bootstrap Process
- •Processing a Request
- •Theming the Data
- •Summary
- •Writing a Module
- •Creating the Files
- •Implementing a Hook
- •Adding Module-Specific Settings
- •Defining Your Own Administration Section
- •Presenting a Settings Form to the User
- •Validating User-Submitted Settings
- •Storing Settings
- •Using Drupal’s variables Table
- •Retrieving Stored Values with variable_get()
- •Further Steps
- •Summary
- •Hooks, Actions, and Triggers
- •Understanding Events and Triggers
- •Understanding Actions
- •The Trigger User Interface
- •Your First Action
- •Assigning the Action
- •Changing Which Triggers an Action Supports
- •Actions That Support Any Trigger
- •Advanced Actions
- •Using the Context in Actions
- •How the Trigger Module Prepares the Context
- •Changing Existing Actions with action_info_alter()
- •Establishing the Context
- •How Actions Are Stored
- •The actions Table
- •Action IDs
- •Calling an Action Directly with actions_do()
- •Defining Your Own Triggers with hook_trigger_info()
- •Adding Triggers to Existing Hooks
- •Summary
- •The Menu System
- •Callback Mapping
- •Mapping URLs to Functions
- •Creating a Menu Item
- •Page Callback Arguments
- •Page Callbacks in Other Files
- •Adding a Link to the Navigation Block
- •Menu Nesting
- •Access Control
- •Title Localization and Customization
- •Defining a Title Callback
- •Wildcards in Menu Items
- •Basic Wildcards
- •Wildcards and Page Callback Parameters
- •Using the Value of a Wildcard
- •Wildcards and Parameter Replacement
- •Passing Additional Arguments to the Load Function
- •Special, Predefined Load Arguments: %map and %index
- •Building Paths from Wildcards Using to_arg() Functions
- •Special Cases for Wildcards and to_arg() Functions
- •Altering Menu Items from Other Modules
- •Altering Menu Links from Other Modules
- •Kinds of Menu Items
- •Common Tasks
- •Assigning Callbacks Without Adding a Link to the Menu
- •Displaying Menu Items As Tabs
- •Hiding Existing Menu Items
- •Using menu.module
- •Common Mistakes
- •Summary
- •Working with Databases
- •Defining Database Parameters
- •Understanding the Database Abstraction Layer
- •Connecting to the Database
- •Performing Simple Queries
- •Retrieving Query Results
- •Getting a Single Value
- •Getting Multiple Rows
- •Using the Query Builder and Query Objects
- •Getting a Limited Range of Results
- •Getting Results for Paged Display
- •Other Common Queries
- •Inserts and Updates with drupal_write_record()
- •The Schema API
- •Using Module .install Files
- •Creating Tables
- •Using the Schema Module
- •Field Type Mapping from Schema to Database
- •Textual
- •Varchar
- •Char
- •Text
- •Numerical
- •Integer
- •Serial
- •Float
- •Numeric
- •Date and Time: Datetime
- •Binary: Blob
- •Declaring a Specific Column Type with mysql_type
- •Maintaining Tables
- •Deleting Tables on Uninstall
- •Changing Existing Schemas with hook_schema_alter()
- •Modifying Other Modules’ Queries with hook_query_alter()
- •Connecting to Multiple Databases Within Drupal
- •Using a Temporary Table
- •Writing Your Own Database Driver
- •Summary
- •Working with Users
- •The $user Object
- •Testing If a User Is Logged In
- •Introduction to user hooks
- •Understanding hook_user_view($account, $view_mode)
- •The User Registration Process
- •Using profile.module to Collect User Information
- •The Login Process
- •Adding Data to the $user Object at Load Time
- •Providing User Information Categories
- •External Login
- •Summary
- •Working with Nodes
- •So What Exactly Is a Node?
- •Not Everything Is a Node
- •Creating a Node Module
- •Creating the .install File
- •Creating the .info File
- •Creating the .module File
- •Providing Information About Our Node Type
- •Modifying the Menu Callback
- •Defining Node-Type–Specific Permissions with hook_permission()
- •Limiting Access to a Node Type with hook__node_access()
- •Customizing the Node Form for Our Node Type
- •Validating Fields with hook_validate()
- •Saving Our Data with hook_insert()
- •Keeping Data Current with hook_update()
- •Cleaning Up with hook_delete()
- •Modifying Nodes of Our Type with hook_load()
- •Using hook_view()
- •Manipulating Nodes That Are Not Our Type with hook_node_xxxxx()
- •How Nodes Are Stored
- •Creating a Node Type with Custom Content Types
- •Restricting Access to Nodes
- •Defining Node Grants
- •What Is a Realm?
- •What Is a Grant ID?
- •The Node Access Process
- •Summary
- •Working with Fields
- •Creating Content Types
- •Adding Fields to a Content Type
- •Creating a Custom Field
- •Adding Fields Programmatically
- •Summary
- •The Theme System
- •Themes
- •Installing an Off-the-Shelf Theme
- •Building a Theme
- •The .info File
- •Adding Regions to Your Theme
- •Adding CSS Files to Your Theme
- •Adding JavaScript Files
- •Adding Settings to Your Theme
- •Understanding Template Files
- •The Big Picture
- •The html.php.tpl File
- •The page.tpl.php File
- •The region.tpl.php File
- •The node.tpl.php File
- •The field.tpl.php File
- •The block.tpl.php File
- •Overriding Template Files
- •Other Template Files
- •Introducing the theme() Function
- •An Overview of How theme() Works
- •Overriding Themable Items
- •Overriding with Template Files
- •Adding and Manipulating Template Variables
- •Using the Theme Developer Module
- •Summary
- •Working with Blocks
- •What Is a Block?
- •Block Configuration Options
- •Block Placement
- •Defining a Block
- •Using the Block Hooks
- •Building a Block
- •Enabling a Block When a Module Is Installed
- •Block Visibility Examples
- •Displaying a Block to Logged-In Users Only
- •Displaying a Block to Anonymous Users Only
- •Summary
- •The Form API
- •Understanding Form Processing
- •Initializing the Process
- •Setting a Token
- •Setting an ID
- •Collecting All Possible Form Element Definitions
- •Looking for a Validation Function
- •Looking for a Submit Function
- •Allowing Modules to Alter the Form Before It’s Built
- •Building the Form
- •Allowing Functions to Alter the Form After It’s Built
- •Checking If the Form Has Been Submitted
- •Finding a Theme Function for the Form
- •Allowing Modules to Modify the Form Before It’s Rendered
- •Rendering the Form
- •Validating the Form
- •Token Validation
- •Built-In Validation
- •Element-Specific Validation
- •Validation Callbacks
- •Submitting the Form
- •Redirecting the User
- •Creating Basic Forms
- •Form Properties
- •Form IDs
- •Fieldsets
- •Theming Forms
- •Using #prefix, #suffix, and #markup
- •Using a Theme Function
- •Telling Drupal Which Theme Function to Use
- •Specifying Validation and Submission Functions with hook_forms()
- •Call Order of Theme, Validation, and Submission Functions
- •Writing a Validation Function
- •Form Rebuilding
- •Writing a Submit Function
- •Changing Forms with hook_form_alter()
- •Altering Any Form
- •Altering a Specific Form
- •Submitting Forms Programmatically with drupal_form_submit()
- •Dynamic Forms
- •Form API Properties
- •Properties for the Root of the Form
- •#action
- •#built
- •#method
- •Properties Added to All Elements
- •#description
- •#attributes
- •#required
- •#tree
- •Properties Allowed in All Elements
- •#type
- •#access
- •#after_build
- •#array_parents
- •#attached
- •#default_value
- •#disabled
- •#element_validate
- •#parents
- •#post_render
- •#prefix
- •#pre_render
- •#process
- •#states
- •#suffix
- •#theme
- •#theme_wrappers
- •#title
- •#tree
- •#weight
- •Form Elements
- •Text Field
- •Password
- •Password with Confirmation
- •Textarea
- •Select
- •Radio Buttons
- •Check Boxes
- •Value
- •Hidden
- •Date
- •Weight
- •File Upload
- •Fieldset
- •Submit
- •Button
- •Image Button
- •Markup
- •Item
- •#ajax Property
- •Summary
- •Filters
- •Filters and Text formats
- •Installing a Filter
- •Knowing When to Use Filters
- •Creating a Custom Filter
- •Implementing hook_filter_info()
- •The Process Function
- •Helper Function
- •Summary
- •Searching and Indexing Content
- •Building a Custom Search Page
- •The Default Search Form
- •The Advanced Search Form
- •Adding to the Search Form
- •Introducing the Search Hooks
- •Formatting Search Results with hook_search_page()
- •Making Path Aliases Searchable
- •Using the Search HTML Indexer
- •When to Use the Indexer
- •How the Indexer Works
- •Adding Metadata to Nodes: hook_node_update_index()
- •Indexing Content That Isn’t a Node: hook_update_index()
- •Summary
- •Working with Files
- •How Drupal Serves Files
- •Managed and Unmanaged Drupal APIs
- •Public Files
- •Private Files
- •PHP Settings
- •Media Handling
- •Upload Field
- •Video and Audio
- •File API
- •Database Schema
- •Common Tasks and Functions
- •Finding the Default Files URI
- •Copying and Moving Files
- •Checking Directories
- •Uploading Files
- •Getting the URL for a File
- •Finding Files in a Directory
- •Finding the Temp Directory
- •Neutralizing Dangerous Files
- •Checking Disk Space
- •Authentication Hooks for Downloading
- •Summary
- •Working with Taxonomy
- •The Structure of Taxonomy
- •Creating a Vocabulary
- •Creating Terms
- •Assigning a Vocabulary to a Content Type
- •Kinds of Taxonomy
- •Flat
- •Hierarchical
- •Multiple Hierarchical
- •Viewing Content by Term
- •Using AND and OR in URLs
- •Specifying Depth for Hierarchical Vocabularies
- •Automatic RSS Feeds
- •Storing Taxonomies
- •Module-Based Vocabularies
- •Creating a Module-Based Vocabulary
- •Keeping Informed of Vocabulary Changes with Taxonomy Hooks
- •Common Tasks
- •Displaying Taxonomy Terms Associated with a Node
- •Building Your Own Taxonomy Queries
- •Using taxonomy_select_nodes()
- •Taxonomy Functions
- •Retrieving Information About Vocabularies
- •taxonomy_vocabulary_load($vid)
- •taxonomy_get_vocabularies()
- •Adding, Modifying, and Deleting Vocabularies
- •taxonomy_vocabulary_save($vocabulary)
- •taxonomy_vocabulary_delete($vid)
- •Retrieving Information About Terms
- •taxonomy_load_term($tid)
- •taxonomy_get_term_by_name($name)
- •Adding, Modifying, and Deleting Terms
- •taxonomy_term_save($term)
- •taxonomy_term_delete($tid)
- •Retrieving Information About Term Hierarchy
- •taxonomy_get_parents($tid, $key)
- •taxonomy_get_parents_all($tid)
- •taxonomy_get_children($tid, $vid, $key)
- •taxonomy_get_tree($vid, $parent, $max_depth, $load_entities = FALSE)
- •Finding Nodes with Certain Terms
- •Additional Resources
- •Summary
- •Caching
- •Knowing When to Cache
- •How Caching Works
- •How Caching Is Used Within Drupal Core
- •Menu System
- •Caching Filtered Text
- •Administration Variables and Module Settings
- •Disabling Caching
- •Page Caching
- •Static Page Caching
- •Blocks
- •Using the Cache API
- •Caching Data with cache_set()
- •Retrieving Cached Data with cache_get() and cache_get_multiple()
- •Checking to See If Cache Is Empty with cache_is_empty()
- •Clearing Cache with cache_clear_all()
- •Summary
- •Sessions
- •What Are Sessions?
- •Usage
- •Session-Related Settings
- •In .htaccess
- •In settings.php
- •In bootstrap.inc
- •Requiring Cookies
- •Storage
- •Session Life Cycle
- •Session Conversations
- •First Visit
- •Second Visit
- •User with an Account
- •Common Tasks
- •Changing the Length of Time Before a Cookie Expires
- •Changing the Name of the Session
- •Storing Data in the Session
- •Summary
- •Using jQuery
- •What Is jQuery?
- •How jQuery Works
- •Using a CSS ID Selector
- •Using a CSS Class Selector
- •jQuery Within Drupal
- •Your First jQuery Code
- •Targeting an Element by ID
- •Method Chaining
- •Adding or Removing a Class
- •Wrapping Existing Elements
- •Changing Values of CSS Elements
- •Where to Put JavaScript
- •Adding JavaScript via a Theme .info File
- •A Module That Uses jQuery
- •Overridable JavaScript
- •Building a jQuery Voting Widget
- •Building the Module
- •Using Drupal.behaviors
- •Ways to Extend This Module
- •Compatibility
- •Next Steps
- •Summary
- •Localization and Translation
- •Enabling the Locale Module
- •User Interface Translation
- •Strings
- •Translating Strings with t()
- •Replacing Built-In Strings with Custom Strings
- •String Overrides in settings.php
- •Replacing Strings with the Locale Module
- •Exporting Your Translation
- •Starting a New Translation
- •Generating .pot Files with Translation Template Extractor
- •Creating a .pot File for Your Module
- •Using the Command Line
- •Using the Web-Based Extractor
- •Creating .pot Files for an Entire Site
- •Installing a Language Translation
- •Setting Up a Translation at Install Time
- •Installing a Translation on an Existing Site
- •Right-to-Left Language Support
- •Language Negotiation
- •Default
- •User-Preferred Language
- •The Global $language Object
- •Path Prefix Only
- •Path Prefix with Language Fallback
- •URL Only
- •Content Translation
- •Introducing the Content Translation Module
- •Multilingual Support
- •Multilingual Support with Translation
- •Localizationand Translation-Related Files
- •Additional Resources
- •Summary
- •What Is XML-RPC?
- •Prerequisites for XML-RPC
- •XML-RPC Clients
- •XML-RPC Client Example: Getting the Time
- •XML-RPC Client Example: Getting the Name of a State
- •Handling XML-RPC Client Errors
- •Network Errors
- •HTTP Errors
- •Call Syntax Errors
- •A Simple XML-RPC Server
- •Mapping Your Method with hook_xmlrpc()
- •Automatic Parameter Type Validation with hook_xmlrpc()
- •Built-In XML-RPC Methods
- •system.listMethods
- •system.methodSignature
- •system.methodHelp
- •system.getCapabilities
- •system.multiCall
- •Summary
- •Writing Secure Code
- •Handling User Input
- •Thinking About Data Types
- •Plain Text
- •HTML Text
- •Rich Text
- •Using check_plain() and t() to Sanitize Output
- •Using filter_xss() to Prevent Cross-Site Scripting Attacks
- •Using filter_xss_admin()
- •Handling URLs Securely
- •Making Queries Secure with db_query()
- •Keeping Private Data Private with hook_query_alter()
- •Dynamic Queries
- •Permissions and Page Callbacks
- •Cross-Site Request Forgeries (CSRF)
- •File Security
- •File Permissions
- •Protected Files
- •File Uploads
- •Filenames and Paths
- •Encoding Mail Headers
- •Files for Production Environments
- •SSL Support
- •Stand-Alone PHP
- •AJAX Security, a.k.a. Request Replay Attack
- •Form API Security
- •Protecting the Superuser Account
- •Summary
- •Development Best Practices
- •Coding Standards
- •Line Indention and Whitespace
- •Operators
- •Casting
- •Control Structures
- •Function Calls
- •Function Declarations
- •Function Names
- •Class Constructor Calls
- •Arrays
- •Quotes
- •String Concatenators
- •Comments
- •Documentation Examples
- •Documenting Constants
- •Documenting Functions
- •Documenting Hook Implementations
- •Including Code
- •PHP Code Tags
- •Semicolons
- •Example URLs
- •Naming Conventions
- •Checking Your Coding Style with Coder Module
- •Finding Your Way Around Code with grep
- •Summary
- •Optimizing Drupal
- •Caching Is the Key to Drupal Performance
- •Optimizing PHP
- •Setting PHP Opcode Cache File to /dev/zero
- •PHP Process Pool Settings
- •Tuning Apache
- •mod_expires
- •Moving Directives from .htaccess to httpd.conf
- •MPM Prefork vs. Apache MPM Worker
- •Balancing the Apache Pool Size
- •Decreasing Apache Timeout
- •Disabling Unused Apache Modules
- •Using Nginx Instead of Apache
- •Using Pressflow
- •Varnish
- •Normalizing incoming requests for better Varnish hits
- •Varnish: finding extraneous cookies
- •Boost
- •Boost vs. Varnish
- •Linux System Tuning for High Traffic Servers
- •Using Fast File Systems
- •Dedicated Servers vs. Virtual Servers
- •Avoiding Calling External Web Services
- •Decreasing Server Timeouts
- •Database Optimization
- •Enabling MySQL’s Query Cache
- •MySQL InnoDB Performance on Windows
- •Drupal Performance
- •Eliminating 404 Errors
- •Disabling Modules You’re Not Using
- •Drupal-Specific Optimizations
- •Page Caching
- •Bandwidth Optimization
- •Pruning the Sessions Table
- •Managing the Traffic of Authenticated Users
- •Logging to the Database
- •Logging to Syslog
- •Running cron
- •Architectures
- •Single Server
- •Separate Database Server
- •Separate Database Server and a Web Server Cluster
- •Load Balancing
- •File Uploads and Synchronization
- •Multiple Database Servers
- •Database Replication
- •Database Partitioning
- •Finding the Bottleneck
- •Web Server Running Out of CPU
- •Web Server Running Out of RAM
- •Identifying Expensive Database Queries
- •Identifying Expensive Pages
- •Identifying Expensive Code
- •Optimizing Tables
- •Caching Queries Manually
- •Changing the Table Type from MyISAM to InnoDB
- •Summary
- •Installation Profiles
- •Creating a New Installation Profile
- •The enhanced.info File
- •The enhanced.profile File
- •The enhanced.install File
- •Using hook_install_tasks and hook_install_tasks_alter
- •Summary
- •Testing
- •Setting Up the Test Environment
- •How Tests Are Defined
- •Test Functions
- •Test Assertions
- •Summary
- •Database Table Reference
- •Resources
- •Code
- •The Drupal Source Code Repository on GIT
- •Examples
- •Drupal API Reference
- •Security Advisories
- •Updating Modules
- •Updating Themes
- •Handbooks
- •Forums
- •Mailing Lists
- •Development
- •Themes
- •Translations
- •User Groups and Interest Groups
- •Internet Relay Chat
- •North America
- •Europe
- •Asia
- •Latin America / Caribbean
- •Oceania
- •Africa
- •Videocasts
- •Weblogs
- •Conferences
- •Contribute
- •Index
- •Numbers
C H A P T E R 9
■ ■ ■
The Theme System
Changing the HTML or other markup that Drupal produces requires knowledge of the layers that make up the theme system. In this chapter, I’ll teach you how the theme system works and reveal some of the best practices hiding within the Drupal 7 core. Here’s the first one: you don’t need to (nor should you) edit the HTML within module files to change the look and feel of your site. By doing that, you’ve just created your own proprietary content management system and have thus lost one of the biggest advantages of using a community-supported open source software system to begin with. Override, don’t change!
Themes
In Drupal-speak, themes are a collection of files that make up the look and feel of your site. You can download preconstructed themes from http://drupal.org/project/themes, or you can roll your own, which is what you’ll learn to do in this chapter. Themes are made up of most of the things you’d expect to see as a web designer: style sheets, images, JavaScript files, and so on. The difference you’ll find between a Drupal theme and a plain HTML site is targeted template files. Template files typically contain large sections of HTML and smaller special snippets that are replaced by dynamic content as Drupal constructs the page. You can create targeted template files for just about every container of content in Drupal—such as the overall page, regions, blocks, nodes, comments, and even fields. We’ll walk through the process of creating several component-level template files in a bit, but let’s start by installing an off-the-shelf theme from Drupal.org and examine the components that make up that theme.
Installing an Off-the-Shelf Theme
There are hundreds of themes available for Drupal. If you are looking for a quick and easy way to get a site up and running, you might consider browsing through the themes at www.drupal.org/project/ themes. Be sure to select “7.x” in the “Filter by compatibility” drop-down list to show only themes that have been ported to Drupal 7.
185
CHAPTER 9 ■ THE THEME SYSTEM
■ Note You must pick a theme that has a Drupal 7 version. Drupal 6 and prior themes will not work on a Drupal 7 site due to the changes in the structure of themes in Drupal 7.
As you browse through the themes, you’ll often run across themes that are described as “starter themes.” Starter themes are focused on providing a solid foundation on which to construct a new theme. Starter themes typically have a wealth of inline documentation and helpful features and functionality. The benefit of a starter theme is that it provides a solid structure on which to lay graphical elements and colors, without having to start with a blank “piece of paper.” Themes that are not classified as starter themes already have graphical effects (e.g., images, colors, fonts, etc.) applied and may fit your needs with very little modification.
For demonstration purposes, we’ll install the Pixture Reloaded theme. There’s nothing significant about this theme other than it has been converted to work with Drupal 7. Visit the theme’s page on Drupal.org (http://drupal.org/project/pixture_reloaded), and copy the URL associated with the download link for the Drupal 7 version of the theme. Return to your site, click the Appearance link at the top of the page, and on the Appearance page click the “Install new theme” link. On the form for uploading a new theme, paste the Pixture Reloaded download URL into the text box labeled “Install from a URL,” and then click the Install button. Drupal will download and save the theme in your sites/all/themes directory. You may then enable the theme as the default theme by revisiting the Appearance page and clicking the “Set default” link.
Installing themes from Drupal.org is simple and quick. You can download any number of themes and give them a test drive on your site by following the foregoing directions, but it is likely that you’ll want at some point to create your own custom theme. In the following sections, I’ll show you how to start with a clean slate and create a brand-new Drupal theme from scratch.
Building a Theme
There are several ways to create a theme, depending on your starting materials. Suppose your designer has already given you the HTML and CSS for the site. It’s relatively easy to take the designer’s HTML and CSS and convert it into a Drupal theme.
The general steps for creating a new Drupal theme include the following:
1.Create or modify an HTML file for the site.
2.Create or modify a CSS file for the site.
3.Create an .info file to describe your new theme to Drupal.
4.Standardize the file names according to what Drupal expects.
5.Insert available variables into your template.
6.Create additional files for individual node types, blocks, and so on.
We’ll start constructing our new theme by first deciding on a name—“Grayscale”—and then create a directory in the sites/all/themes directory using that same name (sites/all/themes/grayscale). Next we’ll need to create an .info file for our new theme in the sites/all/themes/grayscale directory. I’ll create the grayscale.info file initially with the basic information necessary to incorporate the theme into Drupal’s theme registry:
186
CHAPTER 9 ■ THE THEME SYSTEM
name = Grayscale core = 7.x
engine = phptemplate
Once you’ve saved the grayscale.info file, you can now enable the theme by clicking the Appearance link at the top of the page and scrolling down until you see the Grayscale theme. Click the “Enable and set default” link to apply the theme as the site’s default theme. Click the Home button to visit the home page of your site, and volia! You have a new Drupal theme (see Figure 9-1), and all you had to do was create three lines of code in the .info file.
Figure 9-1. The site rendered in the Grayscale theme
187
CHAPTER 9 ■ THE THEME SYSTEM
While it would never win an award for creative design, the process that you just walked through shows how simple it is to create a Drupal theme from scratch. Let’s expand on our site a little bit by applying some CSS to rearrange and style things a bit. The first step is to create a new directory in your Grayscale theme directory called css. While it’s not required that you put all of your CSS files into a subdirectory, it does make it nice so that others don’t have to dig through your theme directory to locate all the CSS files. In the css directory, create a new file named style.css. The name is purely arbitrary, but several Drupal themes use style.css as the naming convention for the primary .css file associated with that theme.
Next we need to instruct our theme to apply style.css to the theme. To do that, we’ll update the grayscale.info file by adding the following line:
stylesheets[all][] = css/style.css
This specifies that style.css should be applied to all mediums used to display the site (screen, projector, and print). You can also apply style sheets that are specific to a particular medium—for example, print, by using the following:
stylesheets[print][] = css/print.css
Or to use a style sheet for both screen and projector combine the two as shown below:
stylesheets[screen, projector][] = theScreenProjectorStyle.css
For our purposes, we’ll stick with all mediums.
Next we’ll examine the structure that Drupal used to render the page so that we can identify CSS IDs and classes to apply styles to. If you use Firefox, I suggest that you download and install Firebug (http://getfirebug.com). If you use Internet Explorer, I suggest you download and install the IE Developers Toolbar (www.microsoft.com/downloads/en/details.aspx?FamilyID=95e06cbe-4940-4218- b75d-b8856fced535), or if you’re using Safari, try the built-in web inspector. All three tools provide the ability to inspect the structure of the site and easily identify which CSS IDs and classes to apply styling to. Figure 9-2 shows the types of information that Firebug for Firefox displays when inspecting a page.
188
CHAPTER 9 ■ THE THEME SYSTEM
Figure 9-2. Output generated by Firefox’s Firebug tool
Take a moment to download one of the tools if you don’t already have it, and once installed, use the Inspection option to examine the structure of the HTML and the DIVs that were generated by Drupal.
189
Download from Wow! eBook <www.wowebook.com>
CHAPTER 9 ■ THE THEME SYSTEM
The next step is to define the styling for the CSS IDs and classes. Before taking that step, let’s look at the page source of our site to see the HTML generated by Drupal for the home page of our new site, focused on the structure of the DIV tags. I’ll omit the HTML between the DIV tags for brevity’s sake. If you want to see the details of the page, simply right-click in the browser window and select view source as it appears on the screen. I’ll show just the DIV structure between the <body> and </body> tags.
<body class="html front logged-in one-sidebar sidebar-first page-node toolbar toolbardrawer" >
<div id="skip-link"> … </div>
<div class=”region region-page-top”>..</div> <div id=”page-wrapper”>
<div id=”header”>
<div class=”section clearfix”> <a id=”logo” … ></a>
<div id=”name-and-slogan”></div> </div>
</div>
<div id=”navigation”> <div class=”section”>
<ul id=”main-menu”>….</ul> <ul id=”seconary-menu”>…</ul>
</div>
</div>
<div id=”main-wraper”> <div id=”main”>
<div id=”content”>…</div>
<div id=”sidebar-first” class=”column sidebar”>…</div> </div>
</div>
<div id=”footer>…</div> </div>
</body>
There is significantly more between the DIV tags, but what is important for our exercise is to understand the general DIV structure so we can add style definitions to the css/style.css file. The following (see listing 9-1) are CSS definitions that I used to create the visual design shown in Figure 9-3.
Listing 9-1. Contents of style.css
body {
background-color: #c6c6c6;
}
#page {
background-color: #c6c6c6;
}
190
CHAPTER 9 ■ THE THEME SYSTEM
#skip-link { width: 960px;
margin-right: auto; margin-left: auto; background-color: #c6c6c6;
}
#header { width: 960px;
background-color: #ffffff; margin-right: auto; margin-left: auto; margin-top: 10px;
height: 40px; padding-top: 10px;
border-top: 3px solid #000; border-bottom: 3px solid #000;
}
#logo {
float: left; margin-left: 20px;
}
a#logo { text-decoration: none;
}
#name-and-slogan { float: left; margin-left: 100px;
}
#site-name a { text-decoration: none;
}
#navigation { width: 960px;
margin-right: auto; margin-left: auto; background-color: #c6c6c6; height: 45px;
}
#navigation h2 { display: none;
}
191
CHAPTER 9 ■ THE THEME SYSTEM
ul#main-menu { background-color: #EEE; height: 25px;
}
ul#main-menu { text-decoration: none; padding-top: 5px;
}
ul#main-menu li a { text-decoration: none; padding-right: 10px;
}
ul#secondary-menu { background-color: #333; height: 25px;
}
ul#secondary-menu li a { text-decoration: none; color: #fff; padding-right: 10px; height: 25px;
border-right: 1px solid #fff;
}
ul#secondary-menu a:hover { color: #ff0000;
}
#main-wrapper { clear: both;
background-color: #ffffff; width: 960px; margin-right: auto; margin-left: auto;
}
#main {
width: 960px; margin: 5px auto;
}
#content { width: 775px; float: right;
padding-left: 15px;
}
192
CHAPTER 9 ■ THE THEME SYSTEM
#sidebar-first { float: left; width: 130px; margin:0; padding: 20px;
background-color: #EEE;
}
#footer { width: 920px; padding: 20px;
margin-right: auto; margin-left: auto; clear: both; min-height: 100px; background-color: #333; color: #fff;
}
#footer a { color: #fff;
}
After saving style.css, revisit the home page of your site. It should look something like Figure 9-3.
Figure 9-3. The site after applying the style sheet additions
193
