Index: src/wp-admin/css/common.css
===================================================================
--- src/wp-admin/css/common.css	(revision 29492)
+++ src/wp-admin/css/common.css	(working copy)
@@ -2255,6 +2255,7 @@
 	right: 0;
 	left: 0;
 	min-height: 100%;
+	min-height: -webkit-calc( 100% - 346px );
 	min-height: calc( 100% - 346px );
 }
 
Index: src/wp-admin/css/edit.css
===================================================================
--- src/wp-admin/css/edit.css	(revision 29492)
+++ src/wp-admin/css/edit.css	(working copy)
@@ -405,6 +405,20 @@
 }
 /* end editor-expand.js override */
 
+#poststuff #post-body #postbox-container-1.pinned {
+	position: fixed;
+	margin: 0;
+	top: 56px;
+	bottom: 0;
+	right: 20px;
+	-webkit-transition: top 200ms;
+	transition: top 200ms;
+}
+
+#postbox-container-1 #side-sortables {
+	padding-bottom: 1px;
+}
+
 #timestampdiv select {
 	height: 21px;
 	line-height: 14px;
Index: src/wp-admin/js/editor-expand.js
===================================================================
--- src/wp-admin/js/editor-expand.js	(revision 29492)
+++ src/wp-admin/js/editor-expand.js	(working copy)
@@ -16,6 +16,10 @@
 		$textEditorClone = $( '<div id="content-textarea-clone"></div>' ),
 		$bottom = $( '#post-status-info' ),
 		$statusBar,
+		$sideSortables = $( '#side-sortables' ),
+		$postboxContainer = $( '#postbox-container-1' ),
+		$postBody = $('#post-body'),
+		$wpfooter = $( '#wpfooter' ),
 		fullscreen = window.wp.editor && window.wp.editor.fullscreen,
 		mceEditor,
 		mceBind = function(){},
@@ -22,7 +26,16 @@
 		mceUnbind = function(){},
 		fixedTop = false,
 		fixedBottom = false,
-		scrollTimer;
+		fixedSide = false,
+		scrolledSide = false,
+		scrollTimer,
+		justFixedSide = false,
+		justFixedSideTimer,
+		lastScrollPosition = 0,
+		pageYOffsetAtTop = 130,
+		pinnedToolsTop = 56, // also used in CSS for the "#poststuff #post-body #postbox-container-1.pinned" selector
+		textEditorClonePaddingTop = 37,
+		autoresizeMinHeight = 300; // $window.height() - 310;
 
 	$textEditorClone.insertAfter( $textEditor );
 
@@ -31,7 +44,7 @@
 		'font-size': $textEditor.css( 'font-size' ),
 		'line-height': $textEditor.css( 'line-height' ),
 		'padding': $textEditor.css( 'padding' ),
-		'padding-top': 37,
+		'padding-top': textEditorClonePaddingTop,
 		'white-space': 'pre-wrap',
 		'word-wrap': 'break-word'
 	} );
@@ -88,8 +101,8 @@
 
 		hiddenHeight = $textEditorClone.height();
 
-		if ( hiddenHeight < 300 ) {
-			hiddenHeight = 300;
+		if ( hiddenHeight < autoresizeMinHeight ) {
+			hiddenHeight = autoresizeMinHeight;
 		}
 
 		if ( hiddenHeight === textEditorHeight ) {
@@ -112,7 +125,7 @@
 		mceEditor = editor;
 
 		// Set the minimum height to the initial viewport height.
-		editor.settings.autoresize_min_height = 300;
+		editor.settings.autoresize_min_height = autoresizeMinHeight;
 
 		// Get the necessary UI elements.
 		$visualTop = $contentWrap.find( '.mce-toolbar-grp' );
@@ -218,9 +231,12 @@
 			adminBarHeight = windowWidth > 600 ? $adminBar.height() : 0,
 			resize = type !== 'scroll',
 			visual = ( mceEditor && ! mceEditor.isHidden() ),
-			buffer = 200,
+			buffer = autoresizeMinHeight + adminBarHeight,
+			postBodyTop = $postBody.offset().top,
+			borderWidth = 1,
+			contentWrapWidth = $contentWrap.width(),
 			$top, $editor,
-			toolsHeight, topPos, topHeight, editorPos, editorHeight, editorWidth, statusBarHeight;
+			toolsHeight, topPos, topHeight, editorPos, editorHeight, editorWidth, statusBarHeight, sideScrollTrigger;
 
 		if ( visual ) {
 			$top = $visualTop;
@@ -238,18 +254,20 @@
 		editorWidth = $editor.outerWidth();
 		statusBarHeight = visual ? $statusBar.outerHeight() : 0;
 
+
 		// Maybe pin the top.
 		if ( ( ! fixedTop || resize ) &&
-				// Handle scrolling down.
-				( windowPos >= ( topPos - toolsHeight - adminBarHeight ) &&
-				// Handle scrolling up.
-				windowPos <= ( topPos - toolsHeight - adminBarHeight + editorHeight - buffer ) ) ) {
+			// Handle scrolling down.
+			( windowPos >= ( topPos - toolsHeight - adminBarHeight ) &&
+			// Handle scrolling up.
+			windowPos <= ( topPos - toolsHeight - adminBarHeight + editorHeight - buffer ) ) ) {
+
 			fixedTop = true;
 
 			$top.css( {
 				position: 'fixed',
 				top: adminBarHeight + toolsHeight,
-				width: $editor.parent().width() - ( $top.outerWidth() - $top.width() ),
+				width: contentWrapWidth - ( borderWidth * 2 ) - ( visual ? 0 : ( $top.outerWidth() - $top.width() ) ),
 				borderTop: '1px solid #e5e5e5'
 			} );
 
@@ -256,7 +274,7 @@
 			$tools.css( {
 				position: 'fixed',
 				top: adminBarHeight,
-				width: editorWidth + 2
+				width: contentWrapWidth
 			} );
 		// Maybe unpin the top.
 		} else if ( fixedTop || resize ) {
@@ -268,13 +286,13 @@
 					position: 'absolute',
 					top: 0,
 					borderTop: 'none',
-					width: $editor.parent().width() - ( $top.outerWidth() - $top.width() )
+					width: contentWrapWidth - ( borderWidth * 2 ) - ( visual ? 0 : ( $top.outerWidth() - $top.width() ) )
 				} );
 
 				$tools.css( {
 					position: 'absolute',
 					top: 0,
-					width: $contentWrap.width()
+					width: contentWrapWidth
 				} );
 			// Handle scrolling down.
 			} else if ( windowPos >= ( topPos - toolsHeight - adminBarHeight + editorHeight - buffer ) ) {
@@ -282,13 +300,14 @@
 
 				$top.css( {
 					position: 'absolute',
-					top: editorHeight - buffer
+					top: editorHeight - buffer,
+					width: contentWrapWidth - ( borderWidth * 2 ) - ( visual ? 0 : ( $top.outerWidth() - $top.width() ) )
 				} );
 
 				$tools.css( {
 					position: 'absolute',
-					top: editorHeight - buffer + 1, // border
-					width: $contentWrap.width()
+					top: editorHeight - buffer + borderWidth, // border
+					width: contentWrapWidth
 				} );
 			}
 		}
@@ -295,18 +314,19 @@
 
 		// Maybe adjust the bottom bar.
 		if ( ( ! fixedBottom || resize ) &&
-				// + 1 for the border around the .wp-editor-container.
-				( windowPos + windowHeight ) <= ( editorPos + editorHeight + bottomHeight + statusBarHeight + 1 ) ) {
+			// +[n] for the border around the .wp-editor-container.
+			( windowPos + windowHeight ) <= ( editorPos + editorHeight + bottomHeight + statusBarHeight + borderWidth ) ) {
+
 			fixedBottom = true;
 
 			$bottom.css( {
 				position: 'fixed',
 				bottom: 0,
-				width: editorWidth + 2,
+				width: editorWidth + ( borderWidth * 2 ),
 				borderTop: '1px solid #dedede'
 			} );
 		} else if ( ( fixedBottom || resize ) &&
-				( windowPos + windowHeight ) > ( editorPos + editorHeight + bottomHeight + statusBarHeight - 1 ) ) {
+				( windowPos + windowHeight ) > ( editorPos + editorHeight + bottomHeight + statusBarHeight - borderWidth ) ) {
 			fixedBottom = false;
 
 			$bottom.css( {
@@ -317,6 +337,61 @@
 			} );
 		}
 
+		// The sidebar is on the left and the scrolling height is large enough, pin it.
+		if ( $postboxContainer.width() < 300 && windowWidth > 600 && // sidebar position is changed with @media from CSS
+			$document.height() > ( $sideSortables.height() + postBodyTop + 120 ) && // the sidebar is not the tallest element
+			windowHeight < editorHeight / 2 ) { // the editor is twice as tall as the viewport
+
+			if ( ! fixedSide && ( postBodyTop - pinnedToolsTop ) < windowPos ) {
+				fixedSide = justFixedSide = true;
+				$postboxContainer.addClass( 'pinned' );
+			} else if ( fixedSide ) {
+				if ( ( postBodyTop - pinnedToolsTop ) >= windowPos ) {
+					fixedSide = false;
+					$postboxContainer.removeClass( 'pinned' );
+				}
+			}
+
+			if ( windowPos > lastScrollPosition ) {
+				// Scrolling down
+				if ( fixedSide ) {
+					if ( justFixedSide && windowPos + windowHeight + 20 > $wpfooter.offset().top ) {
+						justFixedSide = false;
+					}
+
+					if ( justFixedSide ) {
+						clearTimeout( justFixedSideTimer );
+						justFixedSideTimer = setTimeout( function() {
+							justFixedSide = false;
+						}, 400 );
+					} else {
+						sideScrollTrigger = ( $sideSortables.height() - ( windowHeight - pinnedToolsTop ) );
+
+						if ( ! scrolledSide && sideScrollTrigger > 1 && windowPos > sideScrollTrigger && windowPos > $wrap.offset().top ) {
+							scrolledSide = true;
+							$postboxContainer.css( 'top', -( sideScrollTrigger - ( pinnedToolsTop - 20 ) ) );
+							// 20 is additional distance from the bottom of the sidebar to the bottom of the window
+						}
+					}
+				}
+			} else if ( windowPos < lastScrollPosition ) {
+				// Scrolling up
+				if ( scrolledSide && ( fixedBottom || ( windowPos + windowHeight + 40 ) < $wpfooter.offset().top ) ) {
+					scrolledSide = false;
+					$postboxContainer.css( 'top', '' );
+				}
+
+				justFixedSide = false;
+			}
+
+			lastScrollPosition = windowPos;
+		} else {
+			// Unpin
+			$postboxContainer.removeClass( 'pinned' );
+			$postboxContainer.css( 'top', '' );
+			scrolledSide = fixedSide = false;
+		}
+
 		if ( resize ) {
 			$contentWrap.css( {
 				paddingTop: $tools.outerHeight()
@@ -354,7 +429,7 @@
 	function on() {
 		// Scroll to the top when triggering this from JS.
 		// Ensures toolbars are pinned properly.
-		if ( window.pageYOffset && window.pageYOffset > 130 ) {
+		if ( window.pageYOffset && window.pageYOffset > pageYOffsetAtTop ) {
 			window.scrollTo( window.pageXOffset, 0 );
 		}
 
@@ -397,7 +472,7 @@
 
 		// Scroll to the top when triggering this from JS.
 		// Ensures toolbars are reset properly.
-		if ( window.pageYOffset && window.pageYOffset > 130 ) {
+		if ( window.pageYOffset && window.pageYOffset > pageYOffsetAtTop ) {
 			window.scrollTo( window.pageXOffset, 0 );
 		}
 
Index: src/wp-includes/js/media-grid.js
===================================================================
--- src/wp-includes/js/media-grid.js	(revision 29492)
+++ src/wp-includes/js/media-grid.js	(working copy)
@@ -1,4 +1,4 @@
-/* global _wpMediaViewsL10n, MediaElementPlayer, _wpMediaGridSettings, confirm */
+/* global _wpMediaViewsL10n, MediaElementPlayer, _wpMediaGridSettings */
 (function($, _, Backbone, wp) {
 	// Local reference to the WordPress media namespace.
 	var media = wp.media, l10n;
