From 86c75aca35ccd16fe3a93e256679d87a4bd4f548 Mon Sep 17 00:00:00 2001 From: Stewart Lord Date: Wed, 21 Sep 2011 04:33:01 +0000 Subject: [PATCH] Made elephpant image banner dynamic. Elephpant images are pulled from flickr via the php-master server hourly. The web site now provides a simple PHP script to serve a random sampling of these images in JSON format. The web browser now loads the elephpant images via JavaScript, requesting only the number of images that are required to fill the viewport. Images are inserted into the page using the data URI scheme. This ensures that only one http request is needed to load all of the required images. If the browser window resizes, the JavaScript will fetch additional images as required to fill out the viewport again. There is a slight delay built in (250ms) to avoid excessive requests while the window is being resized. Some browsers (e.g. older versions of MSIE) do not support the data URI scheme. For these browsers we may wish to provide a fallback mechanism of aggregating the images (e.g. MHTML, aka MIME HTML). If the images fail to load, the elephant banner is hidden automatically. --- images/elephpants.php | 69 +++++++++++++++++++++++++++++++++++++++++++ include/header.inc | 8 ++--- include/layout.inc | 18 ----------- js/common.js | 52 ++++++++++++++++++++++++++++++++ styles/theme.css | 17 +++++------ 5 files changed, 132 insertions(+), 32 deletions(-) create mode 100644 images/elephpants.php diff --git a/images/elephpants.php b/images/elephpants.php new file mode 100644 index 000000000..bfcb57a50 --- /dev/null +++ b/images/elephpants.php @@ -0,0 +1,69 @@ +, + url: , + data: + },{ + ... + }] + +*/ + +// determine how many images to serve. +if (isset($_REQUEST['count'])) { + $count = intval($_REQUEST['count']); +} else { + header('HTTP/1.1 400', true, 400); + print json_encode(array( + 'error' => "Specify how many elephpants to serve via 'count'." + )); + exit; +} + +// read out photo metadata +$path = __DIR__ . '/elephpants'; +$json = @file_get_contents($path . '/flickr.json'); +$photos = json_decode($json, true); + +// if no photo data, respond with an error. +if (!$photos || !is_array($photos)) { + header('HTTP/1.1 500', true, 500); + print json_encode(array( + 'error' => "No elephpant metadata available." + )); + exit; +} + +// prepare requested number of elephpants at random. +shuffle($photos); +$elephpants = array(); +foreach ($photos as $photo) { + + // stop when we have the requested number of photos. + if (count($elephpants) == $count) { + break; + } + + // skip photo if file doesn't exist. + if (!is_readable($path . '/' . $photo['filename'])) { + continue; + } + + // add photo to response array. + $elephpants[] = array( + 'title' => $photo['title'], + 'url' => "http://flickr.com/photos/" . $photo['owner'] . "/" . $photo['id'], + 'data' => base64_encode(file_get_contents($path . '/' . $photo['filename'])) + ); +} + +print json_encode($elephpants); diff --git a/include/header.inc b/include/header.inc index f03252b8c..f2e1d1fe2 100644 --- a/include/header.inc +++ b/include/header.inc @@ -216,12 +216,10 @@ if (isset($shortname) && $shortname) {
"; - foreach ($elephpants as $image) { - print ""; - } - print "
"; + print "
"; } ?> diff --git a/include/layout.inc b/include/layout.inc index a7a1edafa..6d8739646 100644 --- a/include/layout.inc +++ b/include/layout.inc @@ -840,24 +840,6 @@ function site_header_beta($title = '', $config = array()) $STATIC_ROOT = "/"; } - // Prepare elephpant photo-stream. - // FIXME: This needs to be dynamically generated (randomized?) - // and delivered in a single http request (e.g. using data:// - // uri scheme). - if (isset($config['elephpants'])) { - $elephpants = array( - 'http://farm5.static.flickr.com/4111/5037379813_c727c94d83_s.jpg', - 'http://farm6.static.flickr.com/5046/5246051917_77bd222e31_s.jpg', - 'http://farm5.static.flickr.com/4116/4856848556_b8f64c1699_s.jpg', - 'http://farm5.static.flickr.com/4114/4934705762_e67cc7a5a3_s.jpg', - 'http://farm5.static.flickr.com/4081/4934704224_8f6d16ef1c_s.jpg', - 'http://farm5.static.flickr.com/4097/4795284575_16f7692c31_s.jpg', - 'http://farm5.static.flickr.com/4139/4795926308_4fa1038908_s.jpg', - 'http://farm5.static.flickr.com/4135/4795285595_ec6c565c10_s.jpg' - ); - $elephpants = array_merge($elephpants, $elephpants, $elephpants, $elephpants, $elephpants, $elephpants); - } - require dirname(__FILE__) ."/header.inc"; } function site_footer_beta($config = array()) diff --git a/js/common.js b/js/common.js index fac32886e..fd59929cd 100644 --- a/js/common.js +++ b/js/common.js @@ -237,6 +237,58 @@ $(document).ready(function() { }); }); + // load the elephpant images if elephpants div is in the dom. + $(".elephpants .images").first().each(function (idx, node) { + + // function to fetch and insert images. + var fetchImages = function() { + + // determine how many elephpants are required to fill the + // viewport and subtract for any images we already have. + var count = Math.ceil($(document).width() / 75) + - $(".elephpants .images img").length; + + // early exit if we don't need any images. + if (count < 1) { + return; + } + + // do the fetch. + $.ajax({ + url: '/images/elephpants.php?count=' + count, + dataType: 'json', + success: function(data) { + var photo, image; + for (photo in data) { + photo = data[photo]; + link = $(''); + link.attr('href', photo.url); + link.attr('title', photo.title); + image = $(''); + image.attr('src', 'data:Image;base64,' + photo.data); + $(node).append(link.append(image)); + } + }, + error: function() { + $(".elephpants").hide(); + } + }); + + } + + // begin by fetching the images we need now. + fetchImages(); + + // fetch more if viewport gets larger. + var deferred = null; + $(window).resize(function() { + window.clearTimeout(deferred); + deferred = window.setTimeout(function(){ + fetchImages(); + }, 250); + }); + }); + }); /** diff --git a/styles/theme.css b/styles/theme.css index 602482a6f..cba1c182c 100644 --- a/styles/theme.css +++ b/styles/theme.css @@ -578,10 +578,9 @@ div.elephpants { div.elephpants div.images { height: 75px; - width: 3000px; - position: relative; - left: -1%; background-color: #333; + text-align: center; + white-space: nowrap; } div.elephpants img { @@ -590,15 +589,15 @@ div.elephpants img { opacity: 0.5 -moz-opacity: 0.5; -webkit-opacity: 0.5; - transition: all 0.5s ease-in-out; - -webkit-transition: all 0.5s ease-in-out; - -moz-transition: all 0.5s ease-in-out; + transition: all 0.25s ease-in-out; + -webkit-transition: all 0.25s ease-in-out; + -moz-transition: all 0.25s ease-in-out; } div.elephpants:hover img { - opacity: 0.75; - -moz-opacity: 0.75; - -webkit-opacity: 0.75; + opacity: 0.6; + -moz-opacity: 0.6; + -webkit-opacity: 0.6; transition: all 0.25s ease-in-out; -webkit-transition: all 0.25s ease-in-out; -moz-transition: all 0.25s ease-in-out;