Signup Scheduler and Status modules

Over the past couple of weeks I've put a ton of time into a couple of modules that extend the functionality provided by the fantastic Signup module. Both of these modules come as a result of requirements defined by a project I've got going at work. We're creating a course catalog and the Signup module was our pick for how users "register" for courses. The base module is pretty solid, but we needed some additional functionality to meet the requirements of the registration system.

Signup Scheduler provides users with the ability to administer a node's signups (either by being the node creator or by being a global signup administrator) to set open and close dates for signups on the node. Signups are then opened and closed based on the defined schedule via cron.

While the scheduler module is pretty slick, I'm really excited about the Signup Status module - mostly because it solves several problems for our registration system. The goal of the module is to add the concept of "status" to a user's signup to a node, with status meaning any number of things. User's could be marked as "complete," allowing the node creator (in this case, course instructor) to mark a user as having completed a course. Other states could be "incomplete," "no-show," etc. By default, the module provides two states, "Approved" (the default state) and "Wait Listed," and any number of other states can be added by site administrators that users can then assign to signed-up users.

This functionality essentially provides two major requirements for us - arbitrary status assignment and wait listing. I've still got a bit more work to do on the wait listing functionality to make it really work without confusing the node creator, but essentially the idea is that the "wait listed" state, and any other states an administrator creates, could be marked as modifying the signup total. This will allow node creators to specify, for example, that a course has 10 wait list seats available.

The Signup Scheduler module provides some other notable functionality, as well. Node creators can now print a roster of attendees and signup other users for the node. It also provides what I hope will be a solid API for other modules to tie into, including a couple of hooks that allow other modules to act upon the status change for a user. I'm hoping to spend some time helping getting the base Signup module itself to a state where it has some nice integration points in it like this, too. For example, right now it's not possible to tie into the event of a user's signup being cancelled, or the event of signing-up a user (at least as far as I can tell).

There will be some more fun stuff along these lines over the coming days and weeks, so stay tuned!

Organic Groups - Select Audience by Group Type

Last week I posted up a new Drupal module that attempts to improve the usability of the Organic Groups module when it's used with multiple group types and large numbers of groups. The module modifies the node edit form's audience selector, provided by the Organic Groups module, such that the groups are selectable by content type. This is useful on sites with a very large number of groups and many different group types. For example, a site like the one this was written for, with Districts, Schools and Interest Groups (all of which are content types defined as organic groups) will have have a node edit form with an individual selector for each group type.

Check it out, if you're an Organic Groups user, and let me know what you think.

New theme

I was getting tired of my old theme's design and didn't feel like updating it. It's not so much a matter of not wanting to do it as not having the time or ability to design a theme from the ground up. I really like writing the code behind a theme - I've done that many times in the last couple of years - but I just don't have the graphic design skills to come up with something top-notch, like the Deco theme, which I'm using now.

The Deco theme was designed by Klaas Van Waesberghe for the Google Summer of Code 2007. I think it's absolutely fantastic, and I hope it continues to see progress.

Now that I'm back in school, I've been stewing over some ideas for an SOC project for 2008... but more on that later. In the meantime, enjoy the new look!

Journalistic integrity in enthusiast gaming coverage

In the wake of Jeff Gerstmann's controversial firing from Gamespot, the larger issue of journalistic integrity in the enthusiast gaming press has come to the forefront. I don't have much to say on the issue, aside from echoing N'Gai Croal's we haven't the faintest non-fatal suggestion for how to close up Pandora's box now that it is wide open. If you're not familiar with the story, it started after Gerstmann was suspiciously fired after a negative review of Eidos's Kane & Lynch, which had been heavily advertised on Gamespot in the days leading up to the review. A full rundown can be found at 1Up.

I'm really just writing this post as a way to gather a collection of what I think are some of the most important or interesting links surrounding the issue. Check them out if your interested; but, Croal's article is definitely recommended reading, regardless of your interest in this specific situation.

Why I hate cell phones (a.k.a. Why Android is so important)

I was reading through my news feeds this evening and come across 1Up's glowing review of Orcs & Elves II. Not being much of a cell phone gamer, I passed on the original since I had heard it was coming to the Nintendo DS... and I still haven't played it there, either. So, I figured, "What the heck? Why not give it a shot?" So, I Googled "orcs & elves blackberry", which gave me a link to EA's page to buy the original game (Orcs & Elves) as the top result. Perfect, right?

Not quite. Look at this garbage. There are a number of things I could complain about as a user, so where do I even start? My first reaction was, "Holy crap. How the hell am I supposed to find my phone in that list?" After finally finding anything called a "Blackberry" on that mess they call a web page, I realized that I was just looking at the list for AT&T phones. Well, I'm on T-Mobile, so, a few minutes later, I found my way to the T-Mobile purchase page. No Blackberry was listed at all, let alone the model I have. "So... I can't buy the game? ...I think?" It was so confusing and frustrating, I didn't even even bother looking any more.

From god-awful two dollar ring tones that were probably ripped off from a music nerd's MIDI collection forum, to the industry's insistence on abandoning technology before it's even off the manufacturing floor, there are a million things wrong with the current cell phone industry. For me, though, when it comes to gaming - the problems become personal. It's insulting to me as a consumer and a gamer that my desire to give someone money for something has to be such an absolute pain in the ass. My money must not be that valuable to them, so I'm sure they won't miss it as I leave to go spend it elsewhere.

This whole experience, and dozens of other experiences like it, is why I'm so happy Google and their partners in the Open Handset Alliance are attempting to change that landscape with Android. Who knows - it could end up being just another marginally successful attempt at standardization, like J2ME - but good on 'em for giving it a shot. I really hope it works out. Until the industry evolves, though, I'll be sticking with things that work for my mobile entertainment and continuing to give blatantly dirty looks to the tween at the movies who's phone rips my ears apart with the sounds of the Cheetah Girls.

Drupal Node Overview training materials

I'm wrapping up my first semester of classes in ASU's Educational Technology Master's program, and the final project for my EDT502 (Design and Development of Instruction) class was to design a program of instruction. It was strongly recommended to us to keep the program length to one hour, and to choose something we were familiar with. So, of course, I chose Drupal!

This one hour training program was designed to be a focused and quick introduction to Drupal's node system. The target audience is potential Drupal developers who have experience administering Drupal, and its major focus is on presenting nodes as objects that can be modified by modules. It has three main objectives:

  • present an overview of Drupal's node structure in easy to understand terms;
  • provide attendees with useful tools for inspecting the structure of a node; and
  • give attendees the knowledge required to identify where and when nodes are modified.

I envision this being just one unit in a much larger set of materials that provide a solid introduction to Drupal development. I'm pretty excited about what I was able to come up with, and have started sketching out plans for other units. I've decided to post this unit up here to see if I can get any feedback, and to see if anyone is interested in helping me make the full program of instruction a reality. Please see the attachments below for the full final project. I've included everything. Please feel free to let me know what you think!

Some development notes

This is probably just about the most obvious observation to anyone who has written a technical training program or book before... but, man it's a lot of work! But, it's also incredibly rewarding and satisfying. At the same time, I'm not sure I see myself doing it for anything but material I'm passionate about and I certainly have no desire to be a full time instructional designer. I'm a little worried this could cause... issues... with the rest of my time in the Ed Tech program, but I'm optimistic that it won't.

Apple's Pages '08 is an incredible application and I credit using it with giving my project a level of polish I never would have been able to achieve on my own. I have nothing but praise for the way that Apple has solved issues that have plagued Microsoft Word for years. The UI is incredibly simple and straightforward, and accomplishing fairly complex tasks is a snap. I'm very excited to continue using it in my work.

Google Docs is great for just about every word processing task I have in my daily work. Most of my text heavy documents are written in Google Docs and never leave Google Docs. The framework there provides an awesome solution for taking notes, planning projects and collaborating. However, it is not good for writing materials that you intend to be well designed and printable with reasonably predictable results. I spent quite a few hours porting material from the Google Docs in which I drafted the project to Pages, and the process was not smooth. Next time, I'll plan ahead and start something like this in Pages right off the bat - and I'll just use Subversion as my change management tool.

Update:
I've added the project retrospective, called the Program Development Report, which I just finished up today. See the attachments for the PDF.

If you're coming from the front page or an RSS reader, follow the "read more" link below for the attachments.

Useful bash scripts

Just some personally useful bash scripts:

Find and delete files using a pattern

Find all files containing a particular string and do something with them - in this case, delete all files like "._*" i.e. "._user.module". This is usually junk left over from dead SSH sessions

for FILE in $(find . | grep '\._'); 
  do 
  rm $FILE; 
done;

Extract and import dumped SQL

This one comes from my work on gamerswithjobs.com, where I frequently received database dumps in the form of table dumps and need to decompress the import the SQL into a local DB. Also useful for bulk archiving or decompressing a large number of files.

echo "Extracting archives...";
for FILE in `ls *.gz`; 
  do 
  echo "Extracting $FILE ..."; 
  gzip -d $FILE; 
done;
 
echo "Importing SQL...";
for FILE in `ls *.sql`; 
  do 
  echo "Importing $FILE ..."; 
  mysql -h dbhost -u dbuser -pdbpass dbname < $FILE; 
done;

Dump and compress database tables

Another useful one from gamerswithjobs.com work. This one dump each table from a database as an individual .sql file. This is particularly useful for extremely large databases where a straight dump of the entire DB would take longer than acceptable, either by potential crashes or by sys admin enforcement of a max execution time of commands.

echo "Dumping tables...";
for TBL in `mysql -e "show tables" -N -h dbhost -u dbuser -pdbpass dbname`;
  do 
  echo "Dumping $TBL";
  mysqldump -h dbhost -u dbuser -pdbpass dbname $TBL > $TBL.sql;
done;
 
echo "Compressing dumped tables...";
for FILE in `ls *.sql`; 
  do 
  echo "Compressing $FILE ..."; 
  gzip $FILE; 
done;

Password Strength Module

I've just released the first version of the Password Strength module for Drupal 5.x. The module started out as a back port of the nifty jQuery password strength checking built in to Drupal 6, but quickly grew to include other features we needed for a project at ASU. The module simply modifies existing password confirm fields (where two passwords are entered, like the user edit form), so no other setup is required beyond configuring the desired enforcement rules. The first release of the module features:

  • Client-side password strength checking using jQuery
  • Server-side password strength checking using PHP
  • Settings to control:
    • Toggle server-side enforcement of password on/off
    • Enforce low-, medium-, or high-strength passwords
  • Fully translatable

A functional difference

I spent two hours trying to solve a niggling Internet Explorer problem the other night. It involves a module I'm writing that needs to fudge the autocomplete path generated Drupal's autocomplete textfield form element. I wanted to base the path in one autocomplete textfield based on the result of another autocomplete textfield (if it had data in it). It took just a bit of experimentation to get this working perfectly in Firefox and I was really pleased with the results and happy that I didn't have to hack anything in core. jQuery's ability to quickly and easily add event listeners and modify attributes was a major lifesaver in this case.

The problem: apparently IE wigs out occasionally with attaching newly defined functions to events via jQuery. Take the following code, for example:

$('#edit-school').focus( function() { Drupal.ideal.setSchoolAutocomplete(); } );

The code above follows examples on the jQuery docs site, other code in Drupal (see autocomplete.js, for example), and is fairly standard code for jQuery stuff. The rest of the code does the following:

Drupal.ideal.setSchoolAutocomplete = function() {
  id = Drupal.ideal.getDistrictIdFromString($('#edit-district').val());
  if (id) {
    path = (id == 0) ? Drupal.settings.ideal.schoolAutocomplete : Drupal.settings.ideal.schoolAutocomplete + "/" + id;
    $('#edit-school-autocomplete').val(path);
    $('input.form-autocomplete').unbind();
    Drupal.autocompleteAutoAttach();
    Drupal.ideal.registrationAttach();
  }
}
 
Drupal.ideal.getDistrictIdFromString = function(string) {
  match_start = '(DistrictID: ';
  match_end = ')';
  if (string.indexOf(match_start) >= 0) {
    start = string.indexOf(match_start) + match_start.length;
    end = string.length - match_end.length;
    if (start && end) {
      return string.substring(start, end);
    }
  }
  return 0;
}

As you can see, I unbind all events from any autocomplete textfield. This is so I can get my data added into the path and re-run Drupal.autocompleteAutoAttach so that the autocomplete events pay attention to the new path. This worked perfectly fine in Firefox, but caused unresponsive script errors in IE 6 and 7. What was the fix? A simple matter of semantics. Bind directly to the function name, and everything is peachy-keen:

$('#my-textfield').focus( Drupal.ideal.setSchoolAutocomplete );

Maybe this is fixed in newer versions of jQuery (Drupal 5.2 runs on jQuery 1.0.4, I believe), but regardless it's far from something that should be breaking Internet Explorer.

The full, final code (minus settings junk) is:

Drupal.ideal.registrationAttach = function() {
  $('#edit-school').focus( Drupal.ideal.setSchoolAutocomplete );
}
 
Drupal.ideal.setSchoolAutocomplete = function() {
  id = Drupal.ideal.getDistrictIdFromString($('#edit-district').val());
  if (id) {
    path = (id == 0) ? Drupal.settings.ideal.schoolAutocomplete : Drupal.settings.ideal.schoolAutocomplete + "/" + id;
    $('#edit-school-autocomplete').val(path);
    $('input.form-autocomplete').unbind();
    Drupal.autocompleteAutoAttach();
    Drupal.ideal.registrationAttach();
  }
}
 
Drupal.ideal.getDistrictIdFromString = function(string) {
  match_start = '(DistrictID: ';
  match_end = ')';
  if (string.indexOf(match_start) >= 0) {
    start = string.indexOf(match_start) + match_start.length;
    end = string.length - match_end.length;
    if (start && end) {
      return string.substring(start, end);
    }
  }
  return 0;
}
 
if (Drupal.jsEnabled) {
  $(document).ready(Drupal.ideal.registrationAttach);
}

Back to school

Billy Madison

It took me a while, but I've finally finished the process of applying, registering and signing up for my Master's in Educational Technology at ASU. I start on August 20 with EDT501 and 502, which should give me a good intro to the program and, to be honest, help me figure out if it's really something I'm interested in continuing for a couple of years. I'm really looking forward to getting back into the classroom. I'm also a little nervous, as I haven't had mandatory homework for about four years now. I have strong hopes for the program, as they have a flexible curriculum and a focus on gaming that should be right up my alley.

Since I'm starting back into the academic swing of things, I figured I'd make another go at posting here for a while. I found when I was in school before I had lots of things to talk about - and hopefully this time will be no different. I also plan on starting work on some more personal projects, which will be showcased here. Finally, I've begun work on getting a portfolio put together for the site. Assembling the structure was a snap using the CCK, Views, Imagefield and Link modules for Drupal. Now I just need to get over my laziness and post up my work.

While it's been several months since I posted about it, I'm still really enjoying road biking. I certainly haven't done anything beyond casual riding yet, and I may never do so, but it's a fantastic and fun way to stay in shape.

Syndicate content