mediawiki.action.edit.preview: Run hook on detached node
[lhc/web/wiklou.git] / resources / mediawiki.action / mediawiki.action.edit.preview.js
index 2b97b87..664bf89 100644 (file)
@@ -7,7 +7,7 @@
         * @param {jQuery.Event} e
         */
        function doLivePreview( e ) {
-               var $wikiPreview, copySelectors, removeSelectors, $copyElements, $spinner,
+               var $wikiPreview, $editform, copySelectors, $copyElements, $spinner,
                        targetUrl, postData, $previewDataHolder;
 
                e.preventDefault();
@@ -16,6 +16,7 @@
                $( mw ).trigger( 'LivePreviewPrepare' );
 
                $wikiPreview = $( '#wikiPreview' );
+               $editform = $( '#editform' );
 
                // 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)
                $copyElements = $( copySelectors.join( ',' ) );
 
                // Not shown during normal preview, to be removed if present
-               removeSelectors = [
-                       '.mw-newarticletext'
-               ];
-
-               $( removeSelectors.join( ',' ) ).remove();
+               $( '.mw-newarticletext' ).remove();
 
                $spinner = $.createSpinner( {
                        size: 'large',
                });
                $wikiPreview.before( $spinner );
                $spinner.css( {
-                       position: 'absolute',
                        marginTop: $spinner.height()
                } );
-               // Make sure preview area is at least as tall as 2x the height of the spinner.
-               // 1x because if its smaller, it will spin behind the edit toolbar.
-               // (this happens on the first preview when editPreview is still empty)
-               // 2x because the spinner has 1x margin top breathing room.
-               $wikiPreview.css( 'minHeight', $spinner.height() * 2 );
 
                // 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' );
+               $copyElements.animate( { opacity: 0.4 }, 'fast' );
 
                $previewDataHolder = $( '<div>' );
-               targetUrl = $( '#editform' ).attr( 'action' );
+               targetUrl = $editform.attr( 'action' );
 
                // Gather all the data from the form
-               postData = $( '#editform' ).formToArray();
+               postData = $editform.formToArray();
                postData.push( {
                        name: e.target.name,
                        value: ''
                // TODO: This should use the action=parse API instead of loading the entire page,
                // although that requires figuring out how to convert that raw data into proper HTML.
                $previewDataHolder.load( targetUrl + ' ' + copySelectors.join( ',' ), postData, function () {
-                       var i, $from;
+                       var i, $from, $next, $parent;
+
                        // Copy the contents of the specified elements from the loaded page to the real page.
                        // Also copy their class attributes.
                        for ( i = 0; i < copySelectors.length; i++ ) {
                                $from = $previewDataHolder.find( copySelectors[i] );
 
-                               $( copySelectors[i] )
-                                       .empty()
-                                       .append( $from.contents() )
-                                       .attr( 'class', $from.attr( 'class' ) );
+                               if ( copySelectors[i] === '#wikiPreview' ) {
+                                       $next = $wikiPreview.next();
+                                       // If there is no next node, use parent instead.
+                                       // Only query parent if needed, false otherwise.
+                                       $parent = !$next.length && $wikiPreview.parent();
+
+                                       $wikiPreview
+                                               .detach()
+                                               .empty()
+                                               .append( $from.contents() )
+                                               .attr( 'class', $from.attr( 'class' ) );
+
+                                       mw.hook( 'wikipage.content' ).fire( $wikiPreview );
+
+                                       // Reattach
+                                       if ( $parent ) {
+                                               $parent.append( $wikiPreview );
+                                       } else {
+                                               $next.before( $wikiPreview );
+                                       }
+
+                               } else {
+                                       $( copySelectors[i] )
+                                               .empty()
+                                               .append( $from.contents() )
+                                               .attr( 'class', $from.attr( 'class' ) );
+                               }
                        }
 
                        // Deprecated: Use mw.hook instead
                        $( mw ).trigger( 'LivePreviewDone', [copySelectors] );
 
-                       mw.hook( 'wikipage.content' ).fire( $wikiPreview );
-
                        $spinner.remove();
                        $copyElements.animate( {
                                opacity: 1
 
                if ( !document.getElementById( 'wikiDiff' ) && document.getElementById( 'wikiPreview' ) ) {
                        $( '#wikiPreview' ).after(
-                               $( '<div>' ).attr( 'id', 'wikiDiff')
+                               $( '<div>' ).attr( 'id', 'wikiDiff' )
                        );
                }
 
+               // This should be moved down to '#editform', but is kept on the body for now
+               // because the LiquidThreads extension is re-using this module with only half
+               // the EditPage (doesn't include #editform presumably, bug 55463).
                $( document.body ).on( 'click', '#wpPreview, #wpDiff', doLivePreview );
        } );