From 3ca8808c3bc5c40817bd70ef34bc9883b3481d5e Mon Sep 17 00:00:00 2001
From: Daryl Koopersmith <koop@git.wordpress.org>
Date: Mon, 29 Oct 2012 18:05:03 +0000
Subject: [PATCH] Add dynamic attachment view sizing. Removes the attachment
 view zooming in the process. see #21390.

git-svn-id: https://develop.svn.wordpress.org/trunk@22324 602fd350-edb4-49c9-b593-d223f7449a82
---
 wp-includes/css/media-views.css | 117 +++++++++++---------------------
 wp-includes/js/media-views.js   |  99 ++++++++++++---------------
 wp-includes/media.php           |  32 ++++++++-
 3 files changed, 113 insertions(+), 135 deletions(-)

diff --git a/wp-includes/css/media-views.css b/wp-includes/css/media-views.css
index cf2ac5d75a..98d96a07c8 100644
--- a/wp-includes/css/media-views.css
+++ b/wp-includes/css/media-views.css
@@ -174,6 +174,7 @@
 	bottom: 0;
 	height: auto;
 	width: auto;
+	margin: 0;
 	overflow: auto;
 }
 
@@ -197,44 +198,6 @@
 	font-family: sans-serif;
 }
 
-/**
- * Attachments
- */
-/*.attachments {
-	position: relative;
-	width: 100%;
-	height: 100%;
-}
-
-.attachments-header {
-	position: absolute;
-	top: 0;
-	left: 0;
-	right: 0;
-	height: 50px;
-	padding: 0 10px;
-	background: #fff;
-}
-
-.attachments-header h3 {
-	float: left;
-	margin: 0;
-	padding: 0;
-	line-height: 50px;
-	font-size: 18px;
-	font-weight: 200;
-}
-
-.attachments ul {
-	position: absolute;
-	top: 50px;
-	left: 0;
-	right: 0;
-	bottom: 0;
-	overflow: auto;
-	margin: 0 0 20px;
-}*/
-
 /**
  * Attachment
  */
@@ -289,49 +252,21 @@
 	margin: 0 auto;
 }
 
+.attachment .thumbnail {
+	-webkit-transform: translate( 50%, 50% );
+	-moz-transform:    translate( 50%, 50% );
+	-ms-transform:     translate( 50%, 50% );
+	-o-transform:      translate( 50%, 50% );
+	transform:         translate( 50%, 50% );
+}
+
 /* Vertically center the icons. */
 .attachment .icon {
 	top: 50%;
 	left: 50%;
-	-webkit-transform: translate( -50%, -50% );
-	-moz-transform:    translate( -50%, -50% );
-	-ms-transform:     translate( -50%, -50% );
-	-o-transform:      translate( -50%, -50% );
-	transform:         translate( -50%, -50% );
 }
 
-.attachment .filename {
-	margin-top: 140px;
-	padding: 0 10px;
-	text-align: center;
-	font-weight: bold;
-}
-
-.attachment-preview .thumbnail,
-.attachment-preview .thumbnail img {
-	-webkit-transition-property: width, height, top, left, right, bottom;
-	-moz-transition-property:    width, height, top, left, right, bottom;
-	-ms-transition-property:     width, height, top, left, right, bottom;
-	-o-transition-property:      width, height, top, left, right, bottom;
-	transition-property:         width, height, top, left, right, bottom;
-	-webkit-transition-duration: 80ms;
-	-moz-transition-duration:    80ms;
-	-ms-transition-duration:     80ms;
-	-o-transition-duration:      80ms;
-	transition-duration:         80ms;
-	-webkit-transition-delay:    200ms;
-	-moz-transition-delay:       200ms;
-	-ms-transition-delay:        200ms;
-	-o-transition-delay:         200ms;
-	transition-delay:            200ms;
-}
-
-.attachment-preview .thumbnail {
-	width: 199px;
-	height: 199px;
-}
-
-.attachment-preview .thumbnail:after {
+.attachment-preview:after {
 	content: '';
 	display: block;
 	position: absolute;
@@ -343,8 +278,35 @@
 	overflow: hidden;
 }
 
-.attachment.fit .thumbnail:after {
-	box-shadow: inset 0 0 0 1px rgba( 0, 0, 0, 0.15 );
+.attachment .thumbnail img {
+	top: 0;
+	left: 0;
+}
+
+.attachment .icon,
+.attachment .thumbnail img {
+	-webkit-transform: translate( -50%, -50% );
+	-moz-transform:    translate( -50%, -50% );
+	-ms-transform:     translate( -50%, -50% );
+	-o-transform:      translate( -50%, -50% );
+	transform:         translate( -50%, -50% );
+}
+
+.attachment .filename {
+	position: absolute;
+	left: 0;
+	right: 0;
+	bottom: 0;
+	padding: 5px 10px;
+	text-align: center;
+	font-weight: bold;
+	background: rgba( 255, 255, 255, 0.8 );
+	box-shadow: 0 0 2px rgba( 0, 0, 0, 0.2 );
+}
+
+.attachment-preview .thumbnail {
+	width: 199px;
+	height: 199px;
 }
 
 .attachment .thumbnail img {
@@ -622,6 +584,7 @@
 .attachment-details .describe {
 	float: left;
 	margin: 10px 0 0;
+	border-radius: 3px;
 }
 
 /**
diff --git a/wp-includes/js/media-views.js b/wp-includes/js/media-views.js
index cc4b938346..a818097a3f 100644
--- a/wp-includes/js/media-views.js
+++ b/wp-includes/js/media-views.js
@@ -127,6 +127,12 @@
 			if ( ! this.get('library') )
 				this.set( 'library', media.query() );
 
+			if ( ! this.get('edge') )
+				this.set( 'edge', 120 );
+
+			if ( ! this.get('gutter') )
+				this.set( 'gutter', 6 );
+
 			this.on( 'activate', this.activate, this );
 			this.on( 'deactivate', this.deactivate, this );
 			this.on( 'change:details', this.details, this );
@@ -248,7 +254,8 @@
 			id:         'gallery',
 			multiple:   false,
 			describe:   true,
-			title:      l10n.createGallery
+			title:      l10n.createGallery,
+			edge:       199
 		},
 
 		toolbar: function() {
@@ -1016,8 +1023,8 @@
 
 		events: {
 			'click .attachment-preview':      'toggleSelection',
-			'mouseenter .attachment-preview': 'shrink',
-			'mouseleave .attachment-preview': 'expand',
+			// 'mouseenter .attachment-preview': 'shrink',
+			// 'mouseleave .attachment-preview': 'expand',
 			'change .describe':               'describe'
 		},
 
@@ -1052,7 +1059,7 @@
 			options.describe = this.controller.state().get('describe');
 
 			if ( 'image' === options.type )
-				_.extend( options, this.crop() );
+				_.extend( options, this.imageSize() );
 
 			this.$el.html( this.template( options ) );
 
@@ -1123,7 +1130,7 @@
 
 			// Use the provided image size if possible.
 			if ( sizes && sizes[ size ] ) {
-				return sizes[ size ];
+				return _.clone( sizes[ size ] );
 			} else {
 				return {
 					url:         this.model.get('url'),
@@ -1134,57 +1141,6 @@
 			}
 		},
 
-		crop: function( sizeId ) {
-			var edge = 199,
-				size = this.imageSize( sizeId ),
-				wide, tall;
-
-			wide = wp.media.fit( _.extend( { maxWidth:  edge }, size ) );
-			tall = wp.media.fit( _.extend( { maxHeight: edge }, size ) );
-
-			_.extend( size, wide.width > tall.width ? wide : tall );
-
-			size.top  = ( edge - size.height ) / 2;
-			size.left = ( edge - size.width ) / 2;
-			return size;
-		},
-
-		fit: function( sizeId ) {
-			var margin = 10,
-				full = 199,
-				edge = full - ( margin * 2 ),
-				size = _.extend( wp.media.fit( _.extend({
-					maxWidth:  edge,
-					maxHeight: edge
-				}, this.imageSize( sizeId ) ) ) );
-
-			size.top  = Math.round( margin + ( edge - size.height ) / 2 );
-			size.left = Math.round( margin + ( edge - size.width ) / 2 );
-			return size;
-		},
-
-		shrink: function() {
-			var size = _.pick( this.fit(), 'top', 'left', 'width', 'height' );
-			this.$el.addClass('fit');
-			this.$('.thumbnail').css( size );
-			this.$('.thumbnail img').css( _.extend( size, {
-				top:  0,
-				left: 0
-			} ) );
-		},
-
-		expand: function() {
-			var size = _.pick( this.crop(), 'top', 'left', 'width', 'height' );
-			this.$el.removeClass('fit');
-			this.$('.thumbnail img').css( size );
-			this.$('.thumbnail').css({
-				top:    0,
-				left:   0,
-				width:  199,
-				height: 199
-			});
-		},
-
 		describe: function( event ) {
 			if ( 'image' === this.model.get('type') )
 				this.model.save( 'caption', event.target.value );
@@ -1225,6 +1181,7 @@
 	media.view.Attachments = Backbone.View.extend({
 		tagName:   'ul',
 		className: 'attachments',
+		template:  media.template('attachments-css'),
 
 		events: {
 			'scroll': 'scroll'
@@ -1232,6 +1189,7 @@
 
 		initialize: function() {
 			this.controller = this.options.controller;
+			this.el.id = _.uniqueId('__attachments-view-');
 
 			_.defaults( this.options, {
 				refreshSensitivity: 200,
@@ -1252,6 +1210,28 @@
 			this.scroll = _.chain( this.scroll ).bind( this ).throttle( this.options.refreshSensitivity ).value();
 
 			this.initSortable();
+
+			this.controller.state().on( 'change:edge change:gutter', this.css, this );
+			this.css();
+		},
+
+		destroy: function() {
+			this.collection.off( 'add remove reset', null, this );
+			this.controller.state().off( 'change:edge change:gutter', this.css, this );
+		},
+
+		css: function() {
+			var $css = $( '#' + this.el.id + '-css' ),
+				state = this.controller.state();
+
+			if ( $css.length )
+				$css.remove();
+
+			media.view.Attachments.$head().append( this.template({
+				id:     this.el.id,
+				edge:   state.get('edge'),
+				gutter: state.get('gutter')
+			}) );
 		},
 
 		initSortable: function() {
@@ -1353,6 +1333,13 @@
 				this.collection.more();
 			}
 		}
+	}, {
+		$head: (function() {
+			var $head;
+			return function() {
+				return $head = $head || $('head');
+			};
+		}())
 	});
 
 	/**
diff --git a/wp-includes/media.php b/wp-includes/media.php
index 4f50f3d8a7..19ef68b52f 100644
--- a/wp-includes/media.php
+++ b/wp-includes/media.php
@@ -1327,8 +1327,7 @@ function wp_print_media_templates( $attachment ) {
 				<div class="media-progress-bar"><div></div></div>
 			<% } else if ( 'image' === type ) { %>
 				<div class="thumbnail">
-					<img src="<%- url %>" width="<%- width %>" height="<%- height %>" draggable="false"
-					style="top:<%- top %>px; left:<%- left %>px;" />
+					<img src="<%- url %>" draggable="false" />
 				</div>
 			<% } else { %>
 				<img src="<%- icon %>" class="icon" draggable="false" />
@@ -1461,5 +1460,34 @@ function wp_print_media_templates( $attachment ) {
 			<div class="button edit"><?php _e('Edit'); ?></div>
 		</div>
 	</script>
+
+	<script type="text/html" id="tmpl-attachments-css">
+		<style type="text/css" id="<%- id %>-css">
+			#<%- id %> {
+				padding: <%- gutter %>px;
+			}
+
+			#<%- id %> .attachment {
+				margin: <%- gutter %>px;
+				width: <%- edge %>px;
+			}
+
+			#<%- id %> .attachment-preview,
+			#<%- id %> .attachment-preview .thumbnail {
+				width: <%- edge %>px;
+				height: <%- edge %>px;
+			}
+
+			#<%- id %> .portrait .thumbnail img {
+				width: <%- edge %>px;
+				height: auto;
+			}
+
+			#<%- id %> .landscape .thumbnail img {
+				width: auto;
+				height: <%- edge %>px;
+			}
+		</style>
+	</script>
 	<?php
 }