7 * @param {jQuery.Event} e
9 function doLivePreview( e ) {
10 var $wikiPreview, copySelectors, removeSelectors, $copyElements, $spinner,
11 targetUrl, postData, $previewDataHolder;
15 // Deprecated: Use mw.hook instead
16 $( mw ).trigger( 'LivePreviewPrepare' );
18 $wikiPreview = $( '#wikiPreview' );
20 // Show #wikiPreview if it's hidden to be able to scroll to it
21 // (if it is hidden, it's also empty, so nothing changes in the rendering)
24 // Jump to where the preview will appear
25 $wikiPreview[0].scrollIntoView();
27 // List of selectors matching elements that we will
28 // update from from the ajax-loaded preview page.
40 $copyElements = $( copySelectors.join( ',' ) );
42 // Not shown during normal preview, to be removed if present
47 $( removeSelectors.join( ',' ) ).remove();
49 $spinner = $.createSpinner( {
53 $wikiPreview.before( $spinner );
56 marginTop: $spinner.height()
58 // Make sure preview area is at least as tall as 2x the height of the spinner.
59 // 1x because if its smaller, it will spin behind the edit toolbar.
60 // (this happens on the first preview when editPreview is still empty)
61 // 2x because the spinner has 1x margin top breathing room.
62 $wikiPreview.css( 'minHeight', $spinner.height() * 2 );
64 // Can't use fadeTo because it calls show(), and we might want to keep some elements hidden
65 // (e.g. empty #catlinks)
66 $copyElements.animate( {
70 $previewDataHolder = $( '<div>' );
71 targetUrl = $( '#editform' ).attr( 'action' );
73 // Gather all the data from the form
74 postData = $( '#editform' ).formToArray();
80 // Load new preview data.
81 // TODO: This should use the action=parse API instead of loading the entire page
82 // Though that requires figuring out how to convert that raw data into proper HTML.
83 $previewDataHolder.load( targetUrl + ' ' + copySelectors.join( ',' ), postData, function () {
85 // Copy the contents of the specified elements from the loaded page to the real page.
86 // Also copy their class attributes.
87 for ( i = 0; i < copySelectors.length; i++ ) {
88 $from = $previewDataHolder.find( copySelectors[i] );
92 .append( $from.contents() )
93 .attr( 'class', $from.attr( 'class' ) );
96 // Deprecated: Use mw.hook instead
97 $( mw ).trigger( 'LivePreviewDone', [copySelectors] );
99 mw.hook( 'wikipage.content' ).fire( $wikiPreview );
102 $copyElements.animate( {
109 // Do not enable on user .js/.css pages, as there's no sane way of "previewing"
110 // the scripts or styles without reloading the page.
111 if ( $( '#mw-userjsyoucanpreview' ).length || $( '#mw-usercssyoucanpreview' ).length ) {
115 // The following elements can change in a preview but are not output
116 // by the server when they're empty until the preview reponse.
117 // TODO: Make the server output these always (in a hidden state), so we don't
118 // have to fish and (hopefully) put them in the right place (since skins
119 // can change where they are output).
121 if ( !document.getElementById( 'p-lang' ) && document.getElementById( 'p-tb' ) ) {
123 $( '<div>' ).prop( 'id', 'p-lang' )
127 if ( !$( '.mw-summary-preview' ).length ) {
128 $( '.editCheckboxes' ).before(
129 $( '<div>' ).prop( 'className', 'mw-summary-preview' )
133 if ( !document.getElementById( 'wikiDiff' ) && document.getElementById( 'wikiPreview' ) ) {
134 $( '#wikiPreview' ).after(
135 $( '<div>' ).prop( 'id', 'wikiDiff')
139 // Make sure diff styles are loaded
140 mw.loader.load( 'mediawiki.action.history.diff' );
142 $( document.body ).on( 'click', '#wpPreview, #wpDiff', doLivePreview );
145 }( mediaWiki, jQuery ) );