Categories
Drupal Planet jQuery Mobile Phonegap

Building a jQuery Mobile HTML5 App with PhoneGap for Drupal 7, Part 2

In this post, we’re going to add functionality to take a picture to our jQuery Mobile app using the PhoneGap Media Capture API. We’ll add a button with jQuery Mobile that brings up the mobile phone’s camera.

With jQuery Mobile, to make buttons, we can use the <a href> tag with a data-role=”button” attribute. If you’re submitting a form, use the <button> tag instead – jQuery Mobile will format both of those the same way.  We’ll go ahead and add a button that doesn’t do anything yet – replace the contents of the <div data-role=”content”> tag with this:

<div data-role="content">             
  Welcome to the jQuery Mobile Demo App for Drupal!             
  <p/>             
  <a id="takePhotoButton" data-role="button">Take Photo</a>         
</div>

Run it in the iPhone Simulator, and it looks pretty good for us not having to do too much!

We’ll take advantage of jQuery’s bind method and PhoneGap’s deviceready event for our button functionality.

One gotcha you will probably run into is that you’re used to binding to the click event with jQuery on desktop browsers. With jQuery Mobile, we need to bind to the tap event for our button instead.

We’re using the PhoneGap Media Capture API with the camera – only one line of Javascript needed to bring up the camera on the phone.

navigator.device.capture.captureImage(captureSuccess, captureError, {limit: 1});

You’ll need to provide functions to handle success and errors, along with PhoneGap’s CaptureImageOptions. In our case, we’re limiting the number of photos the user can take to one at a time.

Here’s the JavaScript we need to add to our index.html

<script> 
        function captureSuccess(mediaFiles) {
            navigator.notification.alert('Success taking picture:');
        }        
        function captureError(mediaFiles) {
            navigator.notification.alert('Error taking picture: ' + error.code);
        }
        $(document).bind("deviceready",function () {
            $("#takePhotoButton").bind("tap", function() {
                navigator.device.capture.captureImage(captureSuccess, captureError, {limit: 1});
            });
        });
</script>

You won’t be able to see this run in the iPhone Simulator, because the iPhone Simulator doesn’t have a camera – instead, you’ll need to run it on an actual iPhone (or iPod Touch or iPad with a camera).

In my next post, we’ll cover how to upload images to Drupal 7 using Services 3.

Categories
Drupal Planet jQuery Mobile Phonegap

Building a jQuery Mobile HTML5 App with PhoneGap for Drupal 7, Part 1

In this series of posts, I’m going to discuss how to build a jQuery Mobile HTML5 App that talks to Drupal 7 using AJAX, REST and JSON. I’m going to use the PhoneGap project to create an iPhone application out of the jQuery Mobile app that you can install onto your iPhone. Using PhoneGap, you can also create apps for Android, WebOS, Android, Blackberry, and Symbian.

This first post in the series will get you up and running with jQuery Mobile and PhoneGap on iOS with XCode 4. We’ll get to Drupal a little bit further down the road, so if you just want to do some apps that don’t connect to a server, this post should be useful.

I’m going to use Drupal 7 as the server for the app. Drupal 7 has a lot of functionality built in, but not web services, so you will need to install the Services 3 module.

To build the client application, first download and install the latest version of PhoneGap, following the directions for getting started here:

http://www.phonegap.com/start#ios-x4

For this post, I’m using XCode 4 as the IDE for iOS, so I linked to the specific directions for that platform. I’m also going to target iOS 4.x and above, using the PhoneGap Media Capture API to access the camera.

After running the PhoneGap installer, open XCode 4 and start a new project. You should see the PhoneGap template as one of your options:

Click Next on the Choose your template dialog

I’m going to use DrupalApp as my Product Name, and com.jefflinwood as my company identifier.

Click Next.

Now put your new project into a folder of your choice (for instance, under your home directory’s Documents), and let XCode 4 create a local git repository if it offers to.

Click Create

XCode 4 will do some processing, and then you should see your new DrupalApp project in Xcode.

Hit the Play button in the upper left hand corner of XCode to run your project in the iPhone Simulator. PhoneGap will load, but it won’t have any content to display. The first time you run your project, PhoneGap will actually create a www folder you can drag into XCode to get started. Here’s what the iPhone Simulator will look like:

Now that we have our XCode project set up, and we’ve run our project, we need to add the www folder to our project. With the current version of PhoneGap, this needs to be done manually – the template isn’t set up to import the www folder into the XCode project. Luckily, this is pretty easy.

Open up the DrupalApp project folder in Finder. It should look like this:

Drag the www folder onto your XCode DrupalApp Project, right between DrupalApp and PhoneGap.framework. This is so XCode will bundle the contents of the www folder with your app when it packages the app to run on the iPhone Simulator or on an iPhone, iPod Touch, or iPad.

Xcode will prompt you to create folder references for any added folders – choose this option if the Create groups option is selected.

Click Finish.

Now run the project again, (stopping the currently running DrupalApp if it is still running) and PhoneGap should let you know it’s working:

The next step is to download and add jQuery Mobile (from http://jquerymobile.com/download/) to your XCode project. We will bundle the CSS, Javascript, and images into our app to minimize download times.

In the finder, create a new folder under the www folder named css, and copy the jquery.mobile-1.0b1.min.css file into the css folder. Create another folder under the www folder named javascripts, and copy the jquery.mobile-1.0b1.min.js file into the javascripts folder. You’ll also need to download jQuery 1.6.2 from http://code.jquery.com/jquery-1.6.2.min.js into your javascripts folder.

Now open the index.html in your www folder so we can add the CSS file and the two Javascript files.

In the index.html element, add

<link rel="stylesheet" href="css/jquery.mobile-1.0b1.min.css"/>

and

<script type="text/javascript" charset="utf-8" src="javascripts/jquery-1.6.2.min.js"></script>

<script type="text/javascript" charset="utf-8" src="javascripts/jquery.mobile-1.0b1.min.js"></script>

Now that we have jQuery Mobile added to our project, go ahead and run the project – you shouldn’t see any difference in the output from the iPhone Simulator. This is because jQuery Mobile expects your content to be in <div> tags that correspond to individual pages in your mobile application. This is a little different from what you might be used to, where each page in a web application is a separate HTML file. To minimize download time, and to enable transition effects between pages, it’s best to set up as many of your pages in one HTML file as possible. You can link to other HTML files, of course, but you may lose your transitions between the two – and mobile users strart to expect to see those transitions.

I mentioned that jQuery Mobile wants its content structured into <div> tags instead of individual HTML pages. With those <div> tags, you’ll need to tell jQuery Mobile how your content is structured with the new HTML5 data-* attributes. For instance, <div data-role=”page”>…</div> wraps a mobile page, while <div data-role=”header”>…</div> is the header and <div data-role=”content”>…</div> is the content of the page.

We’re going to replace the contents of the <body> tag of our index.html with some content structured for jQuery Mobile:

<body>  	  
  <div data-role="page" id="home">         
    <div data-role="header">             
      <h1>Home</h1>                       
    </div>         
    <div data-role="content">
      Welcome to the jQuery Mobile Demo App for Drupal!         
    </div>     
  </div> 
</body>

Run the app in the iPhone Simulator:

In the next post, I’m going to show you how to use PhoneGap’s cross-platform features to take photos with your smartphone’s camera.

Categories
Drupal Planet iPhone Development

Building a simple iPad Application with Drupal 7, Part 1

At DrupalCamp Colorado 2011, I created a birds-of-a-feather session on “Going Mobile with Drupal”. There were quite a few of us there, with all kinds of experience – we talked about using jQuery Mobile with Drupal and about connecting iPhone apps to Drupal using the Services module, REST, and either JSON or plist XML. Lots of interest in building RESTful web services with Drupal to support mobile apps.

Drupal 7 makes an ideal back-end for mobile apps, because it already has everything you need for content authoring and permissions built-in. There isn’t any reason to write a lot of server-side code to add a forum or groups or blogs to your mobile app. Another advantage is the large Drupal ecosystem of consultancies, developers, books, training, and conferences that you can turn to for help.

Tablet Puppy Ipad App

The night before the birds-of-a-feather, I built an iPad app to show the Drupal IOS SDK in use with an almost out-of-the-box Drupal 7 site. Here’s the github repo for my iPad demo app for Drupal – I’m not going to submit it to the App Store 🙂

Configuring Drupal to be the back end for Mobile

Right out of the box, Drupal 7 isn’t going to work as a back-end for mobile apps. You will need to install Services 3 to make it possible for Drupal to act as a REST server for its content. You’ll also need to set up an endpoint URL for your REST service, and tell Drupal which resources to expose at that endpoint. This is all much easier in Drupal 7/Services 3 than it was in Drupal 6/Services 2 – if you are using Drupal 6, see my article on Using Drupal 6 with the REST Server.

Drupal Services Modules for REST Server

The first step is to install the modules you’ll need for Services 3:

Services 7.x-3.0-rc3 – requires the ctools 7.x module

To make Services work with the Drupal iOS SDK for iPhone app development, you’ll also need:

Rest Server PLIST 7.x-1.0 – enable rest_server and rest_server_plist

If you’re also planning to retrieve views from your mobile app (and that’s most of the power here) you’ll need to install the Views module and the Services_views module. Services_views exposes Views as a resource to Services

Views 7.x-3.0-beta3 – enable Views and Views UI

Services_views 7.x-1.x-dev – enable Services_views

To keep this focused, I’m not including directions on how to install modules here – read the Drupal.org handbook on installing modules.

In the next post, I’ll cover how to configure Services so you can use Drupal as the server side of a mobile solution!

Categories
Drupal Planet iPhone Development Ruby

Content Authoring for an iPhone App with Drupal using MongoDB

I just finished an interesting project – the EveryMarathon marathon calendar iPhone app. I’m working on my Active City Guides – and as part of that project, I ended up finding every American marathon. Running marathons is one of my hobbies, as is travel, and I like to combine the two by planning trips around marathons. There are several web sites with marathon calendars, but no iPhone (or Android) apps that I could find. So why not make one of my own? I could have put a mobile theme on my Drupal site, but that’s too easy 🙂

One of the screens from the app that lets you track your favorite marathons and your finished marathons

Content Storage and Import

Because I already had the content in Drupal 6, that simplified some of my decisions. In addition, the races themselves would be read-only on the app, meaning I wouldn’t have to worry about editing them and syncing them back to the server. I’d have to get the content from Drupal into the iPhone app and store it – there are several choices I could make:

Core Data

Use Core Data with a SQLite database and import Race objects (and their dependencies) into the database. Sync the database with Drupal on load or in the background, using JSON and a library like Lidenbrock.

Plists from Drupal 6 over HTTP with Services

Use Drupal iOS SDK with Services 2.2 and the Plist Server Module. Supports Views, Nodes, Comments, Users, and Taxonomies. Most Drupal-centric solution

JSON from Drupal 6 over HTTP with Caching

Use Drupal’s REST Server with JSON for Views and Nodes. Use an iPhone REST library such as  RestKit.

JSON from Drupal 6 bundled with App

Pull JSON out of Drupal 6 with REST Server Nodes, and bundle it in with the iPhone app. Read JSON off of the file system when needed. Has the huge advantage of not needing sync code right away, as updates to content can be shipped with app releases – my content isn’t particularly timely, as the marathon dates get updated once a year. Also quite fast to load JSON directly into arrays or dictionaries in the iPhone app and then display them in UITableViews.

I went with the bundled JSON approach for my first release of the app. One of the great things about knowing there are different approaches is that you can make sure your app is flexible enough to change approaches in a new version if you need to – I’ve got everything abstracted away to a singleton EveryMarathonData model object that gets races for iPhone view controllers.

Using MongoDB to aggregate content for the App

Part of the app’s functionality is to display races by state and by month:

I wanted to keep the mobile experience simple – no Advanced Search features, no complicated sorting. I could certainly use Objective-C on the iPhone to display sorted arrays for me – the Races by State could be calculated on startup with the number of races each state has, the Races by Month could be sorted out from all of the races, but these will always be the same for a set of content. I wanted to have a very fast startup time and also have a laggy, crashing iPhone app – so I went with simple. I used MongoDB, a NoSQL database that works very well with JSON, to create JSON documents that had exactly the information I needed to display, in the order they would be shown. This turned out to be simple. I have a two-step process:

1. Download JSON nodes from Drupal and store them in MongoDB
2. Create JSON to bundle with the iPhone app from MongoDB

I wrote my MongoDB integration code in Ruby, but any language would have worked. Here’s my ruby script that generates the JSON for the iPhone app screen above:

require 'rubygems'
require 'json'
require 'mongo'

states = Array.new

db = Mongo::Connection.new.db("marathondb")
coll = db.collection("nodeData")

state_abbr = {
  'AL' => 'Alabama',
  'AK' => 'Alaska',
 ...other states omitted...
  'WI' => 'Wisconsin',
  'WY' => 'Wyoming'
}

reduce ="function(key, values) { " +
                    "var sum = 0; " +
                    "values.forEach(function(f) { " +
                    "   sum += f.count; " +
                    "}); " +
                    "return {count: sum};" +
                "};"

map = "function() { emit(this.field_location[0].province, {count: 1}); }"
races_by_state = coll.map_reduce(map, reduce,{'query'=> {"field_race_types.value" => "Marathon"}})
races_by_state.find().to_a.each do |f|
	state = Hash.new
	state[:state] = "#{f['_id']}"
	state[:count] = "#{f['value']['count']}"
	state[:name] = state_abbr[state[:state]]
	states.push state
end

File.open("races_by_state.json","w") { |f|
		f.puts JSON.pretty_generate states
	}

Basically, we make a connection to the MongoDB for a database and a collection of documents, then create an array of state names and abbreviations. MongoDB doesn’t use SQL, but we can use Map/Reduce to simulate a simple Group By SQL query.

We then prepare our JSON the way we want to use it in the iPhone app – an array of Dictionary/Hash objects. Each Hash object has the state’s abbreviation, the number of races for the state, and the full name of the state

The easiest part of the whole script is outputting the JSON to the file system – the json Ruby gem does all of the hard work!

Wrap Up

After running my ruby scripts, the app data lives in a “magic” directory that XCode knows to bundle into the app. From Objective-C, I can load any of these JSON files into memory, and then parse them into NSDictionary and NSArray objects.

Categories
Drupal Planet

Displaying Recent Tweets in Drupal 6 with twitter_pull

I’m writing this blog post for the Austin Drupal Newbies February Meetup to go along with my presentation about Drupal and Twitter.

Drupal sites can display the most recent tweets for a Twitter @username with the twitter_pull module for Drupal 6 and 7. The twitter_pull module is one of many Twitter-related modules for Drupal – a quick search on drupal.org revealed 151 matches for Twitter modules.

Twitter_pull solves one problem, and one problem only – retrieving recent tweets and displaying them in Drupal.

The module was written for developers to use with PHP – it isn’t configurable from the Admin menu like most other modules, at least in the most recent Drupal 6 release. This means you will have to do a few extra steps to get the twitter_pull module running on a stock Drupal 6 installation.

I’m going to give directions on how to show your recent tweets in a block in the right hand sidebar of a stock, out of the box Drupal 6.20 installation on a UNIX host that you have shell access to – for instance, a VPS or a shared host like PHPWebhosting. You can also install the twitter_pull module using drush or anything else you’re already comfortable with.

Downloading and Installing the Twitter Pull Module

The first step is to login and change directories on your host to your Drupal directory.

cd drupal
Next, create your sites/all/modules directory if it doesn’t already exist. Change your working directory to the modules directory.
 cd sites/all
 mkdir modules
 cd modules
Once you are in the modules directory, use the wget command to download the Drupal 6 version of Twitter_pull into your modules.
wget http://ftp.drupal.org/files/projects/twitter_pull-6.x-1.2.tar.gz
Now, uncompress the twitter_pull module
tar fxzv twitter_pull-6.x-1.2.tar.gz
We can log out of the Unix shell now. With Drupal 7, it’s much easier to install modules through the administration interface.

Enabling the Twitter Pull and PHP Filter Modules

The next step is to go to our Drupal Administration modules page. Login as the administrator to your Drupal site, and go to Site Building->Modules. We need to enable two modules.

http://www.yourserver.com/admin/build/modules

The two modules we need to enable are “PHP Filter” and “Twitter Pull”. Twitter Pull is the module we just downloaded, so it makes sense that we need to enable it.

Why do we need to enable “PHP Filter”? The reason is that the Twitter Pull module requires a small amount of PHP code to make it work. We are going to put that PHP code into a Drupal block. A fresh, clean, new Drupal 6 installation doesn’t let you use PHP code in a block – you will need to enable the “PHP Filter” module that comes with Drupal 6 for this to work.

After checking the boxes next to “PHP Filter” and “Twitter Pull”, click the “Save Configuration” button at the bottom of the modules page.

Creating the Recent Tweets Block

Now, we need to configure a Drupal block to display our recent Tweets. Start at the Blocks Administration page:

http://www.yourserver.com/admin/build/block

Now, add a block from that page


http://www.yourserver.com/admin/build/block/add
Set the block description to Recent Tweets, and the block title to Recent Tweets as well. Next, inside the block body, we will have to use some PHP code. Don’t worry if you aren’t familiar with PHP, this is a great way to get your feet wet. We only have to change one thing to customize this for your site! Copy and paste the following into your block body.
<?php if (function_exists('twitter_pull_render')) { print twitter_pull_render('@jefflinwood', '', 10); } ?>
What we are doing in the above PHP code is first, checking to see if the Twitter Pull module is enabled. If it is, we are making a call to the twitter_pull_render PHP method from the Twitter Pull module with three arguments: the Twitter search, the title to use, and the number of Tweets to show. In our case, we are using @jefflinwood as the Twitter search term, no title, as the title is provided by the block, and we are going to show up to 10 recent Tweets.

Now, change @jefflinwood to your Twitter username – @racetothealtar, for instance.

To make Drupal execute the PHP code in your block, you need to set the Input Format on the block to be PHP Code. If you didn’t enable the PHP Filter module earlier, you will not see this option here.

The defaults for the rest of the block should be okay. Save the block. Your block is now configured and ready to display.

Displaying the Block

Under disabled, change the drop-down for Recent Tweets from <none> to Right Sidebar. Now click the Save Blocks button – you should see the Recent Tweets in your right sidebar! Go to your front page, and they should be there as well.

Categories
Drupal Planet

Drupal 7 Theming Tip: Any Link on an Image Field with Drupal 7

[Dec. 8,2012 – Thanks to Blair Wadman for  noticing that WordPress ate my – – and turned them into en-dashes, thus confusing anyone reading this!]

I’m moving Clutter Puppy – Daily Clutter Tips from static HTML to Drupal 7, but there are quite a few problems I’m running into with theming for Drupal 7, mostly because the documentation is pretty unorganized for Drupal 7 theming. I’m pretty familiar with theming nodes and fields for Drupal 6 with CCK – now that CCK has moved into core for Drupal 7, the API has changed.

In my case, I’m trying to do something simple – on my node, I have two fields that I’d like to use together – “field_url”, which is a text field, and “field_pictures”, which holds an unlimited number of Drupal 7 Image fields. I’d like each image to link to the URL in field_url – that’s not the node URL, it’s just an arbitrary URL that gets entered at content creation.

One thing that really frustrates me about Drupal is how easy this would be with other web application frameworks. Most of them, you’d simply add a foreach loop to your template, and write out the a href and img tags with tip.url and tip.imageUrl. Done!

With Drupal, things get more complicated and the documentation gets horrible as soon as you want to change the default rendering for a Drupal node. With Drupal 7 to do this simple task, you’ll need to modify node.tpl.php, and create a field- -field_pictures.tpl.php template.

In node.tpl.php, put:

<?php print render($content['field_pictures']); ?>

where you want the pictures – this by itself isn’t too bad, but because every field wants to render itself, you’ll need to replace the default field rendering template for field_pictures. Inside of field- -field_pictures.tpl.php, put:

<ul>

<?php foreach ($items as $delta => $item) : ?>

<li><a target="_blank" 

href="<?php print $element['#object']->field_url['und'][0]['value']; 

?>"><?php print render($item); ?></a></li>

<?php endforeach; ?>

</ul>

for a nice unordered list that you can plug into a jQuery plugin, for instance.

The key here was to use the un-Googleable $element[‘#object’] to represent the parent node, and then to retrieve the field_url’s value from the node.

If there’s a better way to do this, I’d love to hear it – the D7 theming guide seems to be missing a discussion of the new D7 fields and how to theme them.

Categories
Drupal Planet

Clash between JSON out of Drupal with Youtube Embedded Field and MongoDB Key Names

(Quick background) As part of a much larger project, I’m pulling content out of Drupal as JSON-formatted nodes into MongoDB. The plan is to use Drupal as the content creation platform, and MongoDB as the database store for the content delivery platform, with JSON as the data format.

Importing JSON content from Drupal into MongoDB is actually very easy – I’ve got Drupal 6 already configured to serve JSON through the REST Service (for more, read my post Using Drupal’s Views as a JSON Web Service with the REST Server)

I installed MongoDB on Mac OS X, installed the mongo ruby gem, and then wrote a quick ruby script to pull JSON off my server and dump it into mongo. This worked great – it throws errors when it hits nodes that aren’t published, but that’s fine. What didn’t work was pulling in anything that used the Embedded Media Framework CCK field for Youtube – one of the JSON tags that gets embedded uses the string “http://www.w3.org/2005/Atom” as a key, and the periods aren’t legal in a key name in MongoDB.

Luckily, this was just the one key name in my JSON output, so I added a quick gsub call to replace www.w3.org with www-w3-org, and all was well. I don’t plan to use the Youtube Atom feed anyway, but if I do, I’ll just have to remember to use my key, not the Drupal 6 CCK key.

Categories
Blueprint CSS Drupal Planet

Using Boks with the Blueprint CSS framework to create Drupal Themes, Part 1

We’re going to create a Drupal 6 theme with the Blueprint CSS grid framework using the Boks visual layout designer. Making a good looking theme in Drupal can be frustrating, especially if you aren’t a graphic or web designer, and you don’t have an HTML/CSS template to work from.

CSS Grid Basics

One shortcut I’ve found for creating great looking web pages is the Blueprint CSS grid framework, which is an open source toolkit that had its version 1.0 release on September 29, 2010. There are several other grid toolkits, such as 960.gs that are similar – each of these helps solve some of the most frustrating CSS layout issues. Blueprint also resets each browser’s CSS back to a common standard, and then builds from there.

The Drupal content management system works extremely well with grid-oriented layout solutions. Many Drupal sites have a similar layout – a header, a footer, a content area, and one or more sidebars on either the left or right sides with the same height as the content area. For those of you who have been doing web development without a CSS framework, just getting that basic layout to work properly (without fixing the height of the content area) can be difficult.

Coming from a software developer background, a basic, fixed grid layout makes a lot of sense, both programmatically and visually.  Generally speaking, a grid CSS framework will provide a content area of about 950 pixels wide, which is a common content area on most web sites (for users with 1024×768 monitors).

Laying out the page visually with Boks

If you start with a wireframe (see my post on DIY Wireframing), you can have a pretty good idea of which elements on your web site are going to go where. From a paper wireframe, we can layout our HTML template in Boks, a visual Blueprint CSS designer. Boks is an Adobe AIR application that runs on Macs, Windows, and Linux as a desktop application.

The Boks interface is confusing, but at its heart, it’s a simple tool.

Choose the width (the default, 950, is fine) and the number of columns in your grid (the default, 24, gives you flexibility)

Set the page title, uncompress the CSS (Drupal will do this itself), and turn off the grid on our page

Click OK and hide the Settings dialog box, revealing the main Boks window:

Using Boks the first time can be very confusing. It is not at all clear what you are supposed to do here from the user interface – what you should do is start to add your visual elements. For this example, we are going to create a header, a content area, and a footer with two equal width blocks.

Start from the top, with the header. Click and drag with your mouse across all 24 columns:

All you need to do now is add a CSS id, in our case “header”, in the id field for the div. You can add other CSS styles or change the markup to another HTML element here, but you don’t have to. We can also add some sample HTML content for our header – put in “<h1>Example Blueprint Theme</h1>”

This really doesn’t look like our web page – Boks abstracts the web page into a series of rows and columns. You define the number of columns you want in your web page – we stuck with the default of 24 columns. Each of these columns is 30 pixels wide with a 10 pixel gutter. Our layout elements can span as many of these columns as we want.

To add a content area, we can drag across all of the columns underneath the header, naming the div “contentArea”. We can also use the dummy text feature of Boks with the “+Lorem Ipsum” button.

Keep the dummy text defaults and add 1 paragraph of Lorem Ipsum text.

Last, we need to add a footer, the same way we added contentArea. Don’t add content to the footer, because we are going to add two equal width areas to the footer.

Within each layout element, we can also create additional layout elements that span all or any part of the parent container’s columns.  We’re going to add two footer elements, leftFooter and rightFooter. Instead of clicking and dragging below the footer element, we are going to click and drag within the footer element. We’re only going to select half of the columns for each div. Call this div “leftFooter”, and use “Left Footer Area” as the HTML content.

Do something similar with the rightFooter – choose the other 12 columns within the footer element:

Our web site’s basic layout is done! This is just the first phase, with just layout, and no emphasis on visual styles yet. We can use the Live Preview feature built into Boks to see how our content area looks  – Choose Live Preview from the Window Menu and see how your page flows:

The last steps are to save our project as a .bok file with File->Save. This lets us re-open the project later in Boks. It doesn’t give us the actual HTML we’ll use in our projects, though. For that, we need to Export from Boks. The Export button is in the upper left corner, and it will save our web page in the directory of our choice. Use Firefox, Chrome, Safari or the browser of your choice to open the page up – it will be named output.html.

Here’s the HTML Boks generated for us. With the next part of this series, we’ll explore the CSS classes added to the HTML, and talk about some of the advantages (and disadvantages) of Blueprint CSS.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<meta content="Boks - 0.5.7" name="generator"/>
<title>Example Blueprint Theme</title>
<!-- Framework CSS -->
<link rel="stylesheet" href="css/screen.css" type="text/css" media="screen, projection"/>
<link rel="stylesheet" href="css/print.css" type="text/css" media="print"/>
<!--[if lt IE 8]><link rel="stylesheet" href="css/ie.css" type="text/css" media="screen, projection"/><![endif]-->
</head>
<body>
<div>
<div id="header"><h1>Example Blueprint Theme</h1></div>
<div id="contentArea"><p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin volutpat congue sapien, sed ornare velit suscipit eget. Vivamus eu lacus augue. Cras metus erat, posuere at venenatis vel, pulvinar molestie odio. Sed ac nibh sed enim suscipit feugiat. Pellentesque placerat porta tincidunt. Phasellus et nisl neque, sed gravida lacus. Phasellus posuere hendrerit ultrices. Fusce lacinia felis at elit ullamcorper lobortis. Pellentesque ac malesuada turpis. Nulla facilisi. Nullam bibendum ante eget lacus malesuada placerat. Donec sed neque sem. Aliquam erat volutpat. Duis vitae neque enim. Vivamus diam quam, posuere laoreet luctus sit amet, posuere at augue. Nam id ipsum enim. Donec diam justo, interdum ut pulvinar nec, lobortis non odio. Nam velit elit, tincidunt ac consectetur quis, ultricies vel magna.</p></div>
<div id="footer">
<div id="leftFooter">Left Footer Area</div>
<div id="rightFooter">Right Footer Area</div>
</div>
</div>
</body>
</html>
Categories
Drupal Planet

Quick Tip: Theming Custom Node Types with Acquia Marina

As I go through the process of translating my wireframes into CSS layouts, I found a pretty interesting bug/feature with the Drupal 6 theming engine and subthemes. In my case, I was trying to create a node-race.tpl.php for Acquia Marina that contains my custom PHP.

I copied node.tpl.php from the Fusion Core theme into my Acquia Marina theme directory and renamed it node-race.tpl.php. What I should have done was copied it into the Acquia Marina theme directory and kept the name node.tpl.php, and then copied it to node-race.tpl.php for modifications!

The Drupal theming engine should look for node-.tpl.php, node-.tpl.php, and finally node.tpl.php when it renders a node (Hint: Rebuild your theme registry as a first step). With subthemes, Drupal won’t check for the custom node templates if there is no base node.tpl.php in the subtheme directory.

For more, see the Drupal Issue: Themes can’t use node-story.tpl.php without node.tpl.php – marked will not fix for some reason. I need to file this in my blog category “hope-I-can-save-someone-else-fifteen-minutes-of-googling”

Categories
Drupal Planet

Integrating DIY Game Mechanics with Drupal

Trying to grow a community, user-generated content site is hard. Engaging your users and making them “sticky” requires that you give them some reason to care about your site – once of the best ways to do this is to add some elements of game mechanics to your site. Successes like FourSquare, Gowalla, and StackOverflow show the value of providing badges, status, reputation, or other virtual goodies to your users. Drupal 6 and 7 community sites can take advantage of several modules that provide these game mechanics to your users.

Adding Fun to your Web Site

There have been a lot of good discussions in other blog posts about ways to add game mechanics to your web site, making your site fun and sticky, engaging your users, and using social media to engage them in game mechanics. Summarizing them, you should definitely add badges users can show off through social media outlets, let your readers rank themselves in leaderboards (site-wide or on a more granular basis) and give them some sense of completion or accomplishing a goal, and always have additional levels, tasks, or badges they can earn – don’t make them too easy to get.

Some great articles on game mechanics:

And for the contrarian view:

If you’re not using Drupal, or you’re not comfortable managing game mechanics for your web site, several startups have stepped into the space of providing game mechanics as a service – I haven’t used any of them, but here’s a small list:

Finally, website building tool DevHub added game mechanics – a case study of they jumped ahead of the competition in a crowded market with game mechanics, maybe using BigDoor?

Drupal Modules for Game Mechanics

There isn’t a one-size fits all solution for adding game mechanics to Drupal sites. There are a couple of modules that you can cobble together to create a solution, but there’s a market opportunity for one of the above players to launch a Drupal module that hooks into both their hosted service and the Drupal userpoints module and its contrib modules to provide a seamless experience – the easier the third party service makes it, the more customers they’ll get.

When you create your own game mechanics solution in Drupal, you’ll need to decide what direction to drive your users, either an overall point system, or a badge/achievement system (or both, of course). With points, the core module you’ll work with is User Points. User Points ties in with a number of other Drupal modules, core and non-core through the User Points contrib module collection. In addition to the modules in that collection, there are a number of other User Points integrations listed on the User Points contrib page.

For badges and achievements, there are two modules – User Badges and the newer Achievements. With User Badges, you’ll have to setup your own rules using the Rules module to grant badges to users, unless you just want to have them defined by their user role (and what’s the fun in that?). A better starting point for game mechanics is probably the Achievements module, but it’s very new, not in CVS, and needs a lot of integration work to get it to the level of User Points!