Mercurial > mozilla-the-big-picture
view mbp.js @ 37:ddab6ae20001
The best image for display is now chosen dynamically based on display resolution, rather than depending on the large/small CSS class metadata.
author | Atul Varma <varmaa@toolness.com> |
---|---|
date | Fri, 11 Dec 2009 16:18:38 -0800 |
parents | 2c5d734e1d2c |
children | 124129f5c74a |
line wrap: on
line source
$(window).ready( function() { var containerWidth = $("#container").width(); var rectRegexp = /rect\((\d+)px,? (\d+)px,? (\d+)px,? (\d+)px\)/; // Each entry may have multiple resolutions of the same image; // choose the one that's best for our display device, and // make sure we have a clipping area for its thumbnail. $(".mbp-entry").each( function() { var images = $(this).find("img"); var lastClip = null; var best = null; images.each( function() { var clip = $(this).css("clip"); if (clip != "auto") lastClip = this; if (best) { // The "best" image is the lowest-resolution image // that's still bigger than the width of our container: // this way we never upscale, but we also don't waste // bandwidth getting a massive image that we won't // see. if (this.width < best.width && this.width >= containerWidth) { best = this; } } else best = this; }); // If our best image doesn't have a CSS clipping rect associated // with it, we'll use the scaled clipping rect of another // resolution. if ($(best).css("clip") == "auto" && lastClip) { var scaling = best.width / lastClip.width; var parts = $(lastClip).css("clip").match(rectRegexp); if (!parts) throw new Error("Invalid 'clip' CSS for " + lastClip.src); var newParts = []; for (var i = 1; i <= 4; i++) newParts.push(Math.floor(parts[i] * scaling) + "px"); $(best).css({clip: "rect(" + newParts.join(", ") + ")"}); } // Remove all the non-ideal images we don't need. images.each(function() { if (this != best) $(this).remove(); }); }); var images = $(".mbp-entry img"); var loadsLeft = images.length; // Create the thumbnails and attach event handlers to them. images.each( function() { function onLoaded() { $("#countdown").text(--loadsLeft); var siblings = [this.previousSibling, this.nextSibling]; for (var i = 0; i < siblings.length; i++) if (siblings[i] && siblings[i].isElementContentWhitespace) $(siblings[i]).remove(); var clip = $(this).css("clip"); var parts = clip.match(rectRegexp); if (!parts) throw new Error("Invalid 'clip' CSS for " + this.src); var crop = {top: parts[1], right: parts[2], bottom: parts[3], left: parts[4]}; crop.width = crop.right - crop.left; crop.height = crop.bottom - crop.top; var canvas = document.createElement("canvas"); var self = $(this.parentNode).clone(); // Allow max-width/max-height of CSS to propagate. self.find("img").removeAttr("width").removeAttr("height"); $(canvas).mouseenter( function() { $("#big-picture").empty(); $("#big-picture").append(self); }); $(canvas).addClass("thumbnail"); $(this).before(canvas); var ctx = canvas.getContext("2d"); ctx.drawImage(this, crop.left, crop.top, crop.width, crop.height, 0, 0, canvas.width, canvas.height); $(this).remove(); if (loadsLeft == 0) { $("#countdown").remove(); $("#container").fadeIn(); } } if (this.complete) onLoaded.call(this); else this.addEventListener("load", onLoaded, false); }); $("h1").mouseover( function() { $("#big-picture").empty(); }); $("#countdown").text(loadsLeft); });