Archive for the ‘Code’ Category

Useful PHP libraries, part 2 – Scaffold CSS

Tuesday, February 16th, 2010

Scaffold CSS was developed by Anthony Short and it is – basically – every CSS-coder’s dream come true:

Variables, nested selectors, abstractions from vendor-specific properties etc. etc. etc. Good stuff!

Installation and usage couldn’t be simpler! (Really. I don’t see how it could!)
You place the library folder in whatever folder holds you CSS-files. Then you copy-paste the .htaccess-file that redirects every request for your CSS-files to the library. Scaffold then reads through your CSS and interprets whatever tricks you’ve written and serves up nicely formatted (or minifed, if you prefer) W3C-compliant CSS.

”What’s this good for?”, you say?

Well. Consider this piece of regular CSS:

form#searchbox #arrival_date,
form#searchbox #departure_date,
form#searchbox #persons,
form#searchbox #location
{
font-size: 18px;
color: white;
margin-bottom: 20px;
}
form#searchbox #arrival_date label,
form#searchbox #departure_date label,
form#searchbox #persons label,
form#searchbox #location label
{
width: 100px;
display: inline-block;
}
form#searchbox #arrival_date input,
form#searchbox #departure_date input,
form#searchbox #persons input,
form#searchbox #location input
{
font-size: 18px;
width: 180px;
height: 40px;
padding-left: 10px;
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
-ms-box-sizing: border-box;
box-sizing: border-box;
behavior: url("boxsizing.htc");
}
form#searchbox #arrival_date .popupcalendar_icon,
form#searchbox  #departure_date .popupcalendar_icon,
form#searchbox  #persons .popupcalendar_icon,
form#searchbox  #location .popupcalendar_icon
{
background: url(./graphics/images/sprites.png) no-repeat 0 0;
height: 295px;
width: 314px;
display: block;
text-indent: -9999px;
overflow: hidden;
background-position: -271px -20px;
height: 39px;
width: 31px;
zoom: 1;
display: inline;
display: -moz-inline-box;
display: inline-block;
vertical-align: top;
margin: 3px 0px 0px 10px;
}

Even though it’s nicely ordered and very readable, this code is still quite hard to understand at first look. You can’t just read what’s going on. What’s related to what? You need to look back and forth a few times to see this.
This makes it bad code!
Good code is always easy to read and understand.

Now look at the same code in Scaffold syntax:

@constants {
   labelTextColor: white;
   gutter: 10px;
}
 
form#searchbox {
 
   #arrival_date, #departure_date, #persons, #location  {
      font-size: 18px;
      color: !labelTextColor;
      margin-bottom: #[2 * !gutter]px;
 
      label {
         width: #[10 * !gutter]px;
         +inline-block();
      }
 
      input {
         font-size: 18px;
         width: 180px;
         height: #[4 * !gutter]px;
         padding-left: #[1 * !gutter]px;
         +border-box();
      }
 
      .popupcalendar_icon {
         image-replace: url('./graphics/images/sprites.png');
         background-position: -271px -20px;
         height:39px;
         width: 31px;
         +inline-block();
         margin: 3px 0px 0px 10px;
      }
   }
}

The nesting immedietaly makes the code easy to read!
The selectors come in a logical order. The code is scannable, and in my opinion this is quite a revolution as far as CSS goes!

And it gets even better!

As you may have noticed, my second code example is full of non-CSS properties.
These are Scaffold-specific functions, constants and ”mixins”.

For example: A standard gutter width of 10px is defined as a constant, then used throughout the style declarations by reference.
No more search-and-replace for simple color changes!
This feature alone will save me countless hours.

Then there’s stuff like ”+inline-block();” or ”+border-box();”. These are ”mixins” that basically call a set of CSS properties that take care of crossbrowser compatibility. Scaffold serves up vendor-specific properties and even a selection of IE-behaviors, filters and expressions to get the desired effect working all around. Now we have a one line trick that’ll fix box model-quirks or get inline-blocks behave like expected. (Or rotation, shadows and other CSS3-goodies for that matter). This means more time for coffee, which is nice!

Finally we have functions like ”image-replace: url(‘./graphics/images/sprites.png’);”
This line takes care of everything regarding CSS image replacement. It even automatically sets the correct height and width fitting the specified image file.

The library has tons of useful features and some pretty advanced ones too. Everything is cached, so it’s just as fast as regular CSS.

So if you’re lucky enough to have your CSS-files served from an Apache server with PHP enabled, then by all means, do not miss out on Scaffold CSS!

Useful PHP libraries, part 1 – SLIR

Wednesday, February 3rd, 2010

In this series of blog posts I introduce my favourite PHP libraries.

Today’s library is:
SLIR

SLIR – or ”Smart Lencioni Image Resizer” – was developed by Joe Lencioni. It’s purpose is on-the-fly scaling and cropping of images.

SLIR works by scaling the image on request, rather than on import.
The benefit is that you can change your image sizes on the fly. If your page layout changes, you can just request images with a size that fits.

It’s basically a clever PHP script that “acts” as like image, combined with a .htaccess-file, that disguises the PHP-file as an actual image file.

This means you activate the resizer just by putting a url into your img-tags.
The url holds the resize parameters and the path to the original image file.

Example:

Original image:

<img src="http://www.jakobloekkemadsen.com/wp-content/uploads/2010/02/DSC_1225_maj-30-2009.jpg" alt="" />

Scaled to fit 100px width:

<img src="http://www.jakobloekkemadsen.com/slir/w100/wp-content/uploads/2010/02/DSC_1225_maj-30-2009.jpg" alt="" />

Scaled to fit 25px width and cropped to square:

<img src="http://www.jakobloekkemadsen.com/slir/w25-c1:1/wp-content/uploads/2010/02/DSC_1225_maj-30-2009.jpg" alt="" />

”What about performance?”, I hear you ask. “Won’t the server choke on having to process all image requests?”

No, it won’t. (-:
SLIR caches the image the first time it’s requested, so all subsequent requests are served just as fast as any other image file on the server. The redirect is handled by an alias to the cachefile. Only if no matching cache file exists, or if it’s too old, or if the original has changed, then SLIR is invoked and a new image is generated and cached.

”Ok. But what about security, then?”

In theory this script enables a hacker to flood your server with files just by changing the url and requesting all imaginable combinations of width and height. This issue has been discussed in the comments on http://shiftingpixel.com/2008/03/03/smart-image-resizer/ and the current version of the script can be made to restrict access to any other combinations than the ones you specify.

Personally I haven’t found an easier, more futureproof and flexible solution for handling image scaling.
And it’s free!

Simply put: I love this script!

Stay tuned for part two of “Useful PHP libraries”. Coming soon …

How to inject dynamic content from PHP into an old and closed source cms.

Friday, December 4th, 2009

The problem

Recently I was asked by an e-commerce client if I could create a banner on his website that would let visitors know whether the phone hotline of the store is currently open or closed based on store opening hours.

In a PHP-based CMS the only task involved would have been writing a function outputting some HTML for use in the banner. So this should have been a no-brainer, had it not been for the fact that my client’s website is run in a proprietary, hosted (and heavily outdated) CMS with no server-side access what so ever!

My first thought was then to make a solution entirely in Javascript. This would be very possible in theory, but since Javascript is a client-side language, it can only know the time and date from the client’s local settings.

This fact rendered the client-side solution very impractical. What about time-zone differences? What if the clients clock is set wrong? How about daylight savings time? In reality, the client-side solution was not an option.

So what to do?

The solution

The only way to go about this problem was then to write a server-side script, run it on a different domain accessing one single source of time and date information (ie. this server’s own clock) and then inject the output into the client’s website using the front-end methods available to me.

That way, the information posted would appear correctly across all visitors regardless of their settings and time zone.

Using AJAX was not an option because of the Same Origin Policy preventing me to use something like jQuery’s load()-function. Also, the fact that the server running the client’s CMS itself was inaccessible to me ment that no proxy-script could be set up to circumvent the restriction.

What struck me, then, was that I had missed the most obvious solution, which was really lo-tech and simple. Embarrasingly simple, actually – as I had already spent so much time scratching my head and searching the web for a workaround to get this fancy AJAX-thing working …

First, here’s the PHP-script to generate the HTML string telling the visitor whether the hotline is open or closed:

<?php
 
header( "Content-type: application/x-javascript; charset=UTF-8" );
 
//Name of variable to output:
$nameOfVariable = "hotline_status";
 
//Strings to output:
$open = "<p class='$nameOfVariable'>The hotline is open!</p>";
$closed = "<p class='$nameOfVariable'>The hotline is closed!</p>";
 
//Opening hours (in 24-hour clock):
$weekday = array(
 'open' => 10,
 'close' => 17
);
 
$saturday = array(
 'open' => 10,
 'close' => 14
);
 
//Time zone adjustment. (If the server is in a different time zone than the hours configured above refer to):
$timeZoneAdjust = 1;
 
//Don't change these:
$now = time();
$daylightSavingsTime = date("I",$now);
$minutes = $now/60;
$minuteOfDay = $minutes % 1440;
$hourOfDay = abs(($minuteOfDay / 60)+$timeZoneAdjust) + $daylightSavingsTime;
$dayOfWeek = date("D",$now);
 
//Make the string:
echo "var $nameOfVariable = \"";
 
if ($dayOfWeek == "Sun") {
 //Sunday is hardcoded.
 echo $closed;
} elseif ($dayOfWeek == "Sat") {
 echo (($hourOfDay <= $saturday['open'] or $hourOfDay >= $saturday['close']) ? $closed : $open);
} else {
 echo (($hourOfDay <= $weekday['open'] or $hourOfDay >= $weekday['close']) ? $closed : $open);
}
 
echo "\";";
?>

Did you catch the trick?

The trick is to specify a php header like this:

header( "Content-type: application/x-javascript; charset=UTF-8" );

That way the script returns a javascript file.
This file contains a single variable holding the string that I want to inject into the DOM of my client’s website.

The result

On a normal weekday within hotline opening hours the output of the PHP file will look like this:

var hotline_status = "<p class='hotline_status'>The hotline is open!</p>";

I can then reference the PHP-file somewhere in the HTML of my client’s website (preferebly near the bottom for load speed reasons) like this:

<script type="text/javascript" src="http://path/to/php/file/"></script>;

Then I inject the content of the variable in the right place using jQuery:

$("div#hotline_status").append(hotline_status)

Voila!

Visitors now see if the hotline is open at the time of visiting the site.

(-:

Possibilities

And this is only a simple script.

You can use this method to apply all the bells and wistles of PHP (or your server-side language of choice) to your client’s ancient and closed source website – including database access, file reads, curls, etc.

Want to feed variables to your PHP script to condition an SQL-call?
No problem! Just append your variables to the filename of the referenced script (like scriptname.php?key=value) and use $_GET['key'] in the script to access them.

I guess you could even inject the script-tag itself on an event rather than on load, thus making user input possible, for instance on submitting a form. I haven’t tried this yet, though.

Of course, all of this wouldn’t be necessary at all in a perfect world where all clients have an open mind and understand the benefits of using non-proprietary, open-source CMS and e-commerce platforms.

But until that happens (which is never), little hacks like this are sometimes necessary to get the job done.

Hope you find it useful!