Ben Murden

Development

Giant Bomb Video Commander

by on Mar.08, 2013, under Development

I recently wrote a Chrome Extension, partially because I wanted to learn how one can be used to inject functionality into an existing website, and partially because I really wanted some functionality that wasn’t already on Giant Bomb. From this was born the Giant Bomb Video Commander! It’s a simple extension that injects some Javascript when there’s a video present, and adds keyboard controls for HTML5 video objects.

I’ve posted a GitHub repository of the source as well.

Leave a Comment :, , , more...

Business Objects: Room Occupancy

by on Mar.06, 2012, under Development

Sometimes Business Objects can make the simplest thing super difficult—if you’re used to using SQL. In this particular case, I just needed an outer join in which I can count the number of rows that have something on the left of the join, and those that don’t.

Scenario

We have data about rooms in a hotel, and we have data about bookings. Bookings are associated to a room by the room ID, and they have a begin and end date, so we know who is in what room at any given time. We have a data cube in which all rooms are shown with booking details if there’s a booking, and a blank space if there isn’t. We want to show a count of occupied and unoccupied rooms off to the side with a single dimension and single measure, so we can do some nice charting.

Setup

We need a variable that shows whether a room is occupied or vacant. This can be achieved simply enough with a dimension that has the following code.

=If IsNull([Booking ID]) Then "Vacant" Else "Occupied"

If you put this next to your list of rooms and bookings, it should show when a room is occupied or vacant. That’s not very interesting by itself, so let’s  start counting how many there are.

You can create multiple measures counting all rooms, occupied rooms, then available rooms by subtracting one from the other, but this leaves you with multiple measures and isn’t suitable for certain charts.

To have a block with the two possible dimensions counted, I started with the following.

=Count([All Rooms].[Room ID])

Create a block that has the room occupancy variable dimension and the count. Make sure it is also set to Show rows with empty dimension values, and what do you get? A count of one for both? Yeah, I had that problem too.

Solution

It isn’t enough just to count, you have to count without row aggregation. That means we need to count every row in which “Occupied” or “Vacant” occurs, even if they are the same (which is kind of the point).

The mistake I made was in the counting variable, so let’s fix that.

=Count([All Rooms].[Room ID]; All)

That little “All” as the second argument makes all the difference! Ugh…

You should now see a count of all room states as expected, and can now make fancy charts all you like.

Caution

One thing to watch out for is if you are actually getting some duplicate rows for another reason, you’ll be counting those, too.

2 Comments : more...

CakePHP ACL and Groups

by on Sep.23, 2011, under Development

There are many great tutorials out there to help you get started with the arcane ACL features of CakePHP, but none of them seemed to cover a specific problem that occurs with reassignment of a parent_id on a save operation.

The parent_id would revert to being null on some save operations on the User model, so if, for example, the user changed their password, they’d end up with no group and an infinite redirect; the redirect loop occurring because everyone should be in a group. Upon investigation with a debugger on task, I discovered the problem resides with the parentNode function, and that all other examples out there are written with the expectation that a group_id will be present in every save operation.

Since parentNode is always called on a save operation performed on a model acting as an ARO, some modification of the typical example is necessary to ensure that you’ll always have the group_id available for finding the parent node ID.

function parentNode() {
  if (!$this->id && empty($this->data)) {
    return null;
  }
  $data = $this->data;
  if (empty($this->data)) {
    $data = $this->read();
  }
  if (empty($data['User']['group_id'])) {
    $groupId = $this->field('group_id', array(
      'id' => $this->id,
    ));
    if (empty($groupId)) {
      return null;
    } else {
      $node = array('model' => 'Group', 'foreign_key' => $groupId);
    }
  } else {
    $node = array('model' => 'Group', 'foreign_key' => $data['User']['group_id']);
  }
  return $node;
}

Like in the Change Password example, on pages where user data is changed, but the group_id is not needed, the parent_id can now be found for the User ARO. On the other hand, you won’t overwrite the group_id if the data indicated it should be changed.

Hope people find this useful, and if you have any suggestions for improvements, let me know!

Leave a Comment :, , more...

Chrome CSS3 Transform Crash

by on Sep.12, 2011, under Development, Web

This crash only seems to occur on some graphics cards, and as far as I know, only on Windows, so I believe it has something to do with Chrome’s implementation of graphics acceleration.

Here’s a test page:

http://benmurden.com/css3test/css3test.html

You should see a zooming, fading effect there. If you don’t see zooming, but you do see fading, then your browser doesn’t support CSS3 transform, transitions or both.

Safari doesn’t seem to have this problem.

If you experience a crash, it might be helpful for development folks to know which graphics card you’re using.

Leave a Comment :, , more...

Support IE6 With the Back of Your Hand

by on Apr.13, 2011, under Development, Web

I’ve been doing a bunch of development work with CakePHP lately and have gotten to the point where I’m in a position to submit a few bug fixes and improvements back to the project. One small improvement has already been accepted, so that’s a great start! Working with Oracle, PHP, CentOS, and CakePHP has been an… interesting experience, so I’m hoping to get some information together about that process and make it a little easier for others in the future.

In other areas, I’ve been trying out Sass, Compass, and blueprint, with exciting results. If you wish for CSS to be more pragmatic and structured, these tools are for you. I’m particularly interested in the potential of very experimental CSS3 implementations, like transform and transition. Makes the web feel modern all over again.

When asked to support IE6, I would do it, but I’d do it like this. I actually rather like the idea behind the Universal IE6 CSS project, in that it still aims to provide a usable and clearly presented version of your site, substituting only CSS, but lets those users know they’re getting a much reduced experience. If they’re on the Internet, why haven’t they hopped on the future train yet? Come on people, get with the program. The fact that projects like this have to exist is pretty crazy, but now that we’re in this mess, I’m glad it does.

Leave a Comment :, , , , , , more...

CakePHP, Rolling Session IDs, and Concurrent Ajax Calls

by on May.04, 2010, under Development

Picture a set of buttons in a list that allow users to quickly cancel listed bookings. These buttons make an Ajax call to a controller action with the relevant ID passed as a parameter. I already have a jQuery method turning these buttons – generated with Cake’s HtmlHelper->Link() – into Ajax calls using the anchor’s href as the URL.

By itself, each button works perfectly. The problem shows itself when a user tries to cancel multiple bookings concurrently. The controller action will process the first request, but choke on all the rest and return a blank response.

This is a very specific problem I had encountered with CakePHP, but I think with Ajax becoming the norm for web application interaction, it’s worth mentioning this fix. The problem lies in the way session IDs are regenerated between requests in Cake’s highest security setting. An easy fix would be to set Cake’s core security level to medium, but we care too much about security, right? So we’ll make a reusable fix that allows us to overcome this issue without affecting security across the board.

In the controller:

function beforeFilter() {
    // Fix for concurrent Ajax requests
    // If it's an Ajax request and the session id has been passed, retain it
    if ($this->RequestHandler->isAjax() && !empty($this->params['url']['s'])) {
      $this->Session->id($this->params['url']['s']);
      $this->Session->start();
    }
    parent::beforeFilter();
  }

This is a modification of a solution given by Adam Royle, changing the process to be more reusable with an optional querystring variable that indicates we want to keep the session ID during an Ajax call. This means if you don’t expect concurrent requests, you can forego the querystring and your action will perform as normal without it, regenerated session IDs included.

The link can then be generated like this:

echo $html->link(__('Cancel', true), array('controller' => 'bookings', 'action' => 'cancelBooking', '?' => array('s' => $session->id()), $booking['id']), array('id' => 'cancelLink'.$booking['id']));

Thanks be to Adam Royle for discovering the root of the issue.

Improvements

This is still not a perfect solution.

  • It effectively exposes the temporary session ID to the user.
  • It will also still fall over if the session ID is regenerated by another Ajax call on the same page, meaning all Ajax buttons in a single view must have this logic.
  • If the user navigates away and performs other actions, then returns to this page using the browser’s back button – and therefore, the local cache – the session ID will be wrong again and cause a logout.

Other possible solutions:

  • Queueing Ajax requests in jQuery so the session ID can regenerate as needed.
  • Session handler in Cake is modified to not regenerate session IDs when request is from an XML/HTTP Request Object.

If there are any other ways of preventing newly generated session IDs from messing with concurrent Ajax requests, I’d love to hear them!

5 Comments :, , , , more...

Finely WordPressed

by on Nov.30, 2009, under Development

I thought I’d dive into the World of WordPress (WoW) and try to start blogging here instead of having things floating around in a place I don’t control. I thought it’d give me a chance to actually make something as well – probably a WordPress theme or plugin.

Leave a Comment : more...

Looking for something?

Use the form below to search the site:

Still not finding what you're looking for? Drop a comment on a post or contact us so we can take care of it!