# HG changeset patch # User Atul Varma # Date 1259340216 18000 # Node ID 126e9241488c8d62007db96286fabda9a8732e78 Origination. diff -r 000000000000 -r 126e9241488c mozilla-the-big-picture.css --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mozilla-the-big-picture.css Fri Nov 27 11:43:36 2009 -0500 @@ -0,0 +1,7 @@ +#thumbnails canvas { + padding: 12px; +} + +.pic-container { + padding: 12px; +} diff -r 000000000000 -r 126e9241488c mozilla-the-big-picture.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mozilla-the-big-picture.html Fri Nov 27 11:43:36 2009 -0500 @@ -0,0 +1,14 @@ + + + + + Mozilla: The Big Picture + + +
+
+ + + + diff -r 000000000000 -r 126e9241488c mozilla-the-big-picture.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mozilla-the-big-picture.js Fri Nov 27 11:43:36 2009 -0500 @@ -0,0 +1,237 @@ +var __entries = [ + { + 'title': 'pocketfox', + 'caption': 'no u', + 'date': '', + 'post': 'http://blog.mozilla.com/blog/2009/11/06/firefox-goes-mobile-winner-announced-plus-a-new-design-challenge/', + 'large': 'http://creative.mozilla.org/images/designs/0/346/346_lg.jpg' + }, + { + 'title': 'colosseo', + 'caption': '', + 'date': '', + 'post': 'http://www.flickr.com/photos/nois3lab/4088072729/in/set-72157622640597827/', + 'large': 'http://farm3.static.flickr.com/2567/4088072729_0286a1611c_o.jpg', + 'small': 'http://farm3.static.flickr.com/2567/4088072729_57e0e4c513.jpg' + }, + { + 'title': 'happy b-day firefox', + 'caption': '', + 'date': '', + 'post': 'http://www.flickr.com/photos/rogeliocalamaya/4090865406/', + 'large': 'http://farm3.static.flickr.com/2778/4090865406_2cc961098e_o.jpg', + 'small': 'http://farm3.static.flickr.com/2778/4090865406_76ed2868d9.jpg' + }, + { + 'title': 'sketch day', + 'caption': '', + 'date': '', + 'post': 'http://blog.stephenhorlander.com/2009/11/20/sketch-day/', + 'large': 'http://www.stephenhorlander.com/images/blog-posts/sketches/menu-sketch-large.jpg', + 'small': 'http://www.stephenhorlander.com/images/blog-posts/sketches/menu-sketch-small.jpg' + } +]; + +function ObserverManager(subject) { + this.subject = subject; + this.observers = {}; + + var self = this; + this.subject.addObserver = function() { + self.add.apply(self, arguments); + }; +} + +ObserverManager.prototype = { + add: function add(topic, observer) { + if (!(topic in this.observers)) + this.observers[topic] = []; + this.observers[topic].push(observer); + }, + + notify: function notify(topic) { + if (!(topic in this.observers)) + this.observers[topic] = []; + for (var i = 0; i < this.observers[topic].length; i++) + this.observers[topic][i].observe(this.subject, topic); + } +}; + +function Thumbnail(selectableImage, canvas, size) { + canvas.width = size; + canvas.height = size; + + this.selectableImage = selectableImage; + this.canvas = canvas; + this.size = size; + this.selectableImage.addObserver("selection-changed", this); +} + +Thumbnail.prototype = { + observe: function observe(subject, topic) { + var selection = this.selectableImage.getNormalizedSelection(); + var ctx = this.canvas.getContext("2d"); + ctx.drawImage( + this.selectableImage.img, + selection.anchor.x, + selection.anchor.y, + selection.width, + selection.height, + 0, + 0, + this.size, + this.size + ); + } +}; + +function SelectableImage(url, canvas) { + var img = new Image(); + var ctx = canvas.getContext("2d"); + + img._parent = this; + img.onload = this.onImgLoad; + img.src = url; + + canvas._parent = this; + + $(canvas).mousedown(this.onDragStart); + $(canvas).mouseup(this.onDragStop); + + this.isDirty = false; + this.ctx = ctx; + this.canvas = canvas; + this.img = img; + this.selection = {anchor: {x: 0, y: 0}, + width: 0, + height: 0}; + this._observers = new ObserverManager(this); +} + +SelectableImage.prototype = { + onImgLoad: function onImgLoad(evt) { + var self = evt.target._parent; + + self.canvas.width = self.img.width; + self.canvas.height = self.img.height; + self._markDirty(); + }, + + onDragStart: function onDragStart(evt) { + var self = evt.target._parent; + var point = self._getCanvasPoint(evt); + + self.selection = {anchor: point, + width: 0, + height: 0}; + $(self.canvas).bind("mousemove", self.onDragging); + }, + + onDragging: function onDragging(evt) { + var self = evt.target._parent; + var point = self._getCanvasPoint(evt); + + var width = point.x - self.selection.anchor.x; + var height = point.y - self.selection.anchor.y; + + if (evt.shiftKey) { + // Constrain dimensions to square. + var maxDiff = Math.max(Math.abs(width), + Math.abs(height)); + if (width > 0) + width = maxDiff; + else + width = -maxDiff; + + if (height > 0) + height = maxDiff; + else + height = -maxDiff; + } + + self.selection.width = width; + self.selection.height = height; + self._markDirty(); + }, + + onDragStop: function onDragStop(evt) { + var self = evt.target._parent; + + $(self.canvas).unbind("mousemove", self.onDragging); + self._markDirty(); + self._observers.notify("selection-changed"); + }, + + getNormalizedSelection: function getNormalizedSelection() { + var x = this.selection.anchor.x; + var y = this.selection.anchor.y; + var width = this.selection.width; + var height = this.selection.height; + + if (width < 0) { + x = x + width; + width = -width; + } + if (height < 0) { + y = y + height; + height = -height; + } + + return {anchor: {x: x, y: y}, + width: width, + height: height}; + }, + + _getCanvasPoint: function _getCanvasPoint(evt) { + var ofs = $(this.canvas).offset(); + return {x: evt.pageX - ofs.left, + y: evt.pageY - ofs.top}; + }, + + _markDirty: function _markDirty() { + var self = this; + + if (!this._isDirty) { + this._isDirty = true; + window.setTimeout(function() { self._render(); }, 0); + } + }, + + _render: function _render() { + this._isDirty = false; + this.ctx.drawImage(this.img, 0, 0); + + var norm = this.getNormalizedSelection(); + + this.ctx.fillStyle = "rgba(0,0,0,0.75)"; + this.ctx.strokeStyle = "rgb(255,255,255)"; + this.ctx.lineWidth = 1.0; + this.ctx.lineJoin = "bevel"; + this.ctx.fillRect(norm.anchor.x, norm.anchor.y, + norm.width, norm.height); + this.ctx.strokeRect(norm.anchor.x, norm.anchor.y, + norm.width, norm.height); + } +}; + +function processEntries(entries) { + var THUMBNAIL_SIZE = 100; + + for (var i = 0; i < entries.length; i++) { + var entry = entries[i]; + entry.small = entry.small || entry.large; + + var container = $('
'); + var canvas = document.createElement("canvas"); + container.append(canvas); + $("#pics").append(container); + var selImg = new SelectableImage(entry.small, canvas); + + var thumbnailCanvas = document.createElement("canvas"); + $("#thumbnails").append(thumbnailCanvas); + var thumbnail = new Thumbnail(selImg, thumbnailCanvas, + THUMBNAIL_SIZE); + } +} + +$(window).ready(function() { processEntries(__entries); });