(bug 25830) fix JS preview causing the page to "jump"
authorMatmaRex <matma.rex@gmail.com>
Thu, 9 Aug 2012 13:51:28 +0000 (15:51 +0200)
committerMatmaRex <matma.rex@gmail.com>
Fri, 31 Aug 2012 23:07:31 +0000 (01:07 +0200)
Originally a patch by DieBuche <diebuche@gmail.com>, fixed to apply on
master (only whitespace changes were needed), with multiple new tweaks and
fixes.

The patch introduces fadeTo(..., 0.4) instead of fadeIn/fadeOut, causing
the preview not to be removed, but only faded out slightly. The reason
for this change is twofold:
* We do not want to completely remove the elements, which is what the old
  version did. This causes the edit field to jump up and then back down
  when the preview is reinserted.
* We do not want to display a huge blank white space where the preview
  used to be before it disappeared.

Instead of scrolling to the top, we scroll straight to the preview. This
works when the preview is set to appear below edit field and possibly with
non-default skins. (And also is much neater.) Thanks to Jdlrobson for
noticing this issue.

We also separately handle first preview and all the following ones to
further reduce jumping. Thanks to MarkTraceur and Kaldari for noticing the
problem and to Kaldari for a patch.

Change-Id: I743ed45e039445242a99a23cad719a75731c5562

skins/common/preview.js

index 9e76ca0..2922558 100644 (file)
@@ -3,10 +3,27 @@
  */
 (function( $ ) {
        window.doLivePreview = function( e ) {
+               var previewShowing = false;
+
                e.preventDefault();
 
                $( mw ).trigger( 'LivePreviewPrepare' );
 
+               var $wikiPreview = $( '#wikiPreview' );
+
+               $( '#mw-content-text' ).css( 'position', 'relative' );
+
+               if ( $wikiPreview.is( ':visible' ) ) {
+                       previewShowing = true;
+               }
+
+               // show #wikiPreview if it's hidden (if it is hidden, it's also empty, so nothing changes in the rendering)
+               // to be able to scroll to it
+               $wikiPreview.show();
+
+               // Jump to where the preview will appear
+               $wikiPreview[0].scrollIntoView();
+
                var postData = $('#editform').formToArray();
                postData.push( { 'name' : 'wpPreview', 'value' : '1' } );
 
                                                        '#catlinks'];
                var copySelector = copyElements.join(',');
 
-               $.each( copyElements, function(k,v) { $(v).fadeOut('fast'); } );
+               $.each( copyElements, function( k, v ) {
+                       $( v ).fadeTo( 'fast', 0.4 );
+               } );
 
                // Display a loading graphic
                var loadSpinner = $('<div class="mw-ajax-loader"/>');
-               $('#wikiPreview').before( loadSpinner );
+               // Move away from header (default is -16px)
+               loadSpinner.css( 'top', '0' );
+
+               // If the preview is already showing, overlay the spinner on top of it.
+               if ( previewShowing ) {
+                       loadSpinner.css( {
+                               'position': 'absolute',
+                               'z-index': '3',
+                               'left': '50%',
+                               'margin-left': '-16px'
+                       } );
+               }
+               $wikiPreview.before( loadSpinner );
 
                var page = $('<div/>');
                var target = $('#editform').attr('action');
                                        $(copyElements[i]).prop( 'class', newClasses );
                                }
 
-                               $.each( copyElements, function(k,v) {
+                               $.each( copyElements, function( k, v ) {
                                        // Don't belligerently show elements that are supposed to be hidden
-                                       $(v).fadeIn( 'fast', function() { $(this).css('display', ''); } );
+                                       $( v ).fadeTo( 'fast', 1, function() {
+                                               $( this ).css( 'display', '' );
+                                       } );
                                } );
 
                                loadSpinner.remove();