LivePreview: coding conventions and overall code prettiness
authorMatmaRex <matma.rex@gmail.com>
Sat, 1 Sep 2012 14:46:04 +0000 (16:46 +0200)
committerMatmaRex <matma.rex@gmail.com>
Wed, 5 Sep 2012 18:07:30 +0000 (20:07 +0200)
There are no functionality changes; some code has been moved around, some
variables were renamed, some whitespace fixed, some comments updated.

Slightly non-trivial changes:
* use .animate instead of .fadeTo (see comment in code for explanation)
* move loading diff styles out of the if (RL will take care of it)

Change-Id: I57e2fc0b090b6cbbcc15a445ac65bab860fbcae9

skins/common/preview.js

index e0a3c00..d70a2ec 100644 (file)
 /**
  * Live preview script for MediaWiki
  */
-(function( $ ) {
-       window.doLivePreview = function( e ) {
-               var previewShowing = false;
-
+( function( mw, $ ) {
+       var doLivePreview = function( e ) {
                e.preventDefault();
 
                $( mw ).trigger( 'LivePreviewPrepare' );
 
                var $wikiPreview = $( '#wikiPreview' );
 
-               $( '#mw-content-text' ).css( 'position', 'relative' );
-
+               // this needs to be checked before we unconditionally show the preview
+               var previewVisible = false;
                if ( $wikiPreview.is( ':visible' ) ) {
-                       previewShowing = true;
+                       previewVisible = 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
+               // show #wikiPreview if it's hidden to be able to scroll to it
+               // (if it is hidden, it's also empty, so nothing changes in the rendering)
                $wikiPreview.show();
-
-               // Jump to where the preview will appear
+               // jump to where the preview will appear
                $wikiPreview[0].scrollIntoView();
 
-               var postData = $('#editform').formToArray(); // formToArray: from jquery.form
-               postData.push( { 'name' : e.target.name, 'value' : '1' } );
-
-               // Hide active diff, used templates, old preview if shown
-               var copyElements = ['#wikiPreview', '#wikiDiff', '.templatesUsed', '.hiddencats',
-                                                       '#catlinks', '#p-lang', '.mw-summary-preview'];
-               var copySelector = copyElements.join(',');
+               // list of elements that will be loaded from the preview page
+               var copySelectors = [
+                       '#wikiPreview', '#wikiDiff', '#catlinks', '.hiddencats', '#p-lang', // the meat
+                       '.templatesUsed', '.mw-summary-preview' // editing-related
+               ];
+               var $copyElements = $( copySelectors.join( ',' ) );
 
-               $.each( copyElements, function( k, v ) {
-                       $( v ).fadeTo( 'fast', 0.4 );
-               } );
+               var $loadSpinner = $( '<div>' ).addClass( 'mw-ajax-loader' );
+               $loadSpinner.css( 'top', '0' ); // move away from header (default is -16px)
 
-               // Display a loading graphic
-               var loadSpinner = $('<div class="mw-ajax-loader"/>');
-               // Move away from header (default is -16px)
-               loadSpinner.css( 'top', '0' );
+               // If the preview is already visible, overlay the spinner on top of it.
+               if ( previewVisible ) {
+                       $( '#mw-content-text' ).css( 'position', 'relative' ); // FIXME this seems like a bad idea
 
-               // If the preview is already showing, overlay the spinner on top of it.
-               if ( previewShowing ) {
-                       loadSpinner.css( {
+                       $loadSpinner.css( {
                                'position': 'absolute',
                                'z-index': '3',
                                'left': '50%',
                                'margin-left': '-16px'
                        } );
                }
-               $wikiPreview.before( loadSpinner );
 
-               var page = $('<div/>');
-               var target = $('#editform').attr('action');
+               // fade out the elements and display the throbber
+               $( '#mw-content-text' ).prepend( $loadSpinner );
+               // we can't use fadeTo because it calls show(), and we might want to keep some elements hidden
+               // (e.g. empty #catlinks)
+               $copyElements.animate( { 'opacity': 0.4 }, 'fast' );
 
-               if ( !target ) {
-                       target = window.location.href;
-               }
+               var $previewDataHolder = $( '<div>' );
+               var target = $( '#editform' ).attr( 'action' ) || window.location.href;
 
-               page.load( target + ' ' + copySelector, postData,
-                       function() {
-
-                               for( var i=0; i<copyElements.length; ++i) {
-                                       // For all the specified elements, find the elements in the loaded page
-                                       //  and the real page, empty the element in the real page, and fill it
-                                       //  with the content of the loaded page
-                                       var copyContent = page.find( copyElements[i] ).contents();
-                                       $(copyElements[i]).empty().append( copyContent );
-                                       var newClasses = page.find( copyElements[i] ).prop('class');
-                                       $(copyElements[i]).prop( 'class', newClasses );
-                               }
-
-                               $.each( copyElements, function( k, v ) {
-                                       // Don't belligerently show elements that are supposed to be hidden
-                                       $( v ).fadeTo( 'fast', 1, function() {
-                                               $( this ).css( 'display', '' );
-                                       } );
-                               } );
-
-                               loadSpinner.remove();
-
-                               $( mw ).trigger( 'LivePreviewDone', [copyElements] );
-                       } );
+               // gather all the data from the form
+               var postData = $( '#editform' ).formToArray(); // formToArray: from jquery.form
+               postData.push( { 'name' : e.target.name, 'value' : '1' } );
+
+               // load new preview data
+               // FIXME this should use the action=parse API instead of loading the entire page
+               $previewDataHolder.load( target + ' ' + copySelectors.join( ',' ), postData, function() {
+                       // Copy the contents of the specified elements from the loaded page to the real page.
+                       // Also copy their class attributes.
+                       for ( var i = 0; i < copySelectors.length; i++ ) {
+                               var $from = $previewDataHolder.find( copySelectors[i] );
+                               var $to = $( copySelectors[i] );
+
+                               $to.empty().append( $from.contents() );
+                               $to.attr( 'class', $from.attr( 'class' ) );
+                       }
+
+                       $loadSpinner.remove();
+                       $copyElements.animate( { 'opacity': 1 }, 'fast' );
+
+                       $( mw ).trigger( 'LivePreviewDone', [copySelectors] );
+               } );
        };
 
-       $(document).ready( function() {
-               // construct space for interwiki links if missing
-               // (it is usually not shown when action=edit, but shown if action=submit)
+       $( document ).ready( function() {
+               // construct the elements we need if they are missing (usually when action=edit)
+               // we don't need to hide them, because they are empty when created
+
+               // interwiki links
                if ( !document.getElementById( 'p-lang' ) && document.getElementById( 'p-tb' ) ) {
-                       // we need not hide this, because it's empty anyway
                        $( '#p-tb' ).after( $( '<div>' ).attr( 'id', 'p-lang' ) );
                }
 
-               // construct space for summary preview if missing
+               // summary preview
                if ( $( '.mw-summary-preview' ).length === 0 ) {
                        $( '.editCheckboxes' ).before( $( '<div>' ).addClass( 'mw-summary-preview' ) );
                }
 
-               // construct space for diff if missing. also load diff styles.
+               // diff
                if ( !document.getElementById( 'wikiDiff' ) && document.getElementById( 'wikiPreview' ) ) {
                        $( '#wikiPreview' ).after( $( '<div>' ).attr( 'id', 'wikiDiff' ) );
-                       // diff styles are by default only loaded when needed
-                       // if there was no diff container, we can expect the styles not to be there either
-                       mw.loader.load( 'mediawiki.action.history.diff' );
                }
 
+               // diff styles are usually only loaded during, well, diff, and we might need them
+               // (mw.loader takes care of stuff if they happen to be loaded already)
+               mw.loader.load( 'mediawiki.action.history.diff' );
+
                $( '#wpPreview, #wpDiff' ).click( doLivePreview );
        } );
-}) ( jQuery );
+} )( mediaWiki, jQuery );