Merge "Fix HTML output arround HTMLForm's submit buttons when in vform"
[lhc/web/wiklou.git] / resources / mediawiki.action / mediawiki.action.edit.preview.js
1 /**
2 * Live edit preview.
3 */
4 ( function ( mw, $ ) {
5
6 /**
7 * @param {jQuery.Event} e
8 */
9 function doLivePreview( e ) {
10 var $wikiPreview, $editform, copySelectors, $copyElements, $spinner,
11 targetUrl, postData, $previewDataHolder;
12
13 e.preventDefault();
14
15 // Deprecated: Use mw.hook instead
16 $( mw ).trigger( 'LivePreviewPrepare' );
17
18 $wikiPreview = $( '#wikiPreview' );
19 $editform = $( '#editform' );
20
21 // Show #wikiPreview if it's hidden to be able to scroll to it
22 // (if it is hidden, it's also empty, so nothing changes in the rendering)
23 $wikiPreview.show();
24
25 // Jump to where the preview will appear
26 $wikiPreview[0].scrollIntoView();
27
28 // List of selectors matching elements that we will
29 // update from from the ajax-loaded preview page.
30 copySelectors = [
31 // Main
32 '#firstHeading',
33 '#wikiPreview',
34 '#wikiDiff',
35 '#catlinks',
36 '.hiddencats',
37 '#p-lang',
38 // Editing-related
39 '.templatesUsed',
40 '.limitreport',
41 '.mw-summary-preview'
42 ];
43 $copyElements = $( copySelectors.join( ',' ) );
44
45 // Not shown during normal preview, to be removed if present
46 $( '.mw-newarticletext' ).remove();
47
48 $spinner = $.createSpinner( {
49 size: 'large',
50 type: 'block'
51 } );
52 $wikiPreview.before( $spinner );
53 $spinner.css( {
54 marginTop: $spinner.height()
55 } );
56
57 // Can't use fadeTo because it calls show(), and we might want to keep some elements hidden
58 // (e.g. empty #catlinks)
59 $copyElements.animate( { opacity: 0.4 }, 'fast' );
60
61 $previewDataHolder = $( '<div>' );
62 targetUrl = $editform.attr( 'action' );
63
64 // Gather all the data from the form
65 postData = $editform.formToArray();
66 postData.push( {
67 name: e.target.name,
68 value: ''
69 } );
70
71 // Load new preview data.
72 // TODO: This should use the action=parse API instead of loading the entire page,
73 // although that requires figuring out how to convert that raw data into proper HTML.
74 $previewDataHolder.load( targetUrl + ' ' + copySelectors.join( ',' ), postData, function () {
75 var i, $from, $next, $parent;
76
77 // Copy the contents of the specified elements from the loaded page to the real page.
78 // Also copy their class attributes.
79 for ( i = 0; i < copySelectors.length; i++ ) {
80 $from = $previewDataHolder.find( copySelectors[i] );
81
82 if ( copySelectors[i] === '#wikiPreview' ) {
83 $next = $wikiPreview.next();
84 // If there is no next node, use parent instead.
85 // Only query parent if needed, false otherwise.
86 $parent = !$next.length && $wikiPreview.parent();
87
88 $wikiPreview
89 .detach()
90 .empty()
91 .append( $from.contents() )
92 .attr( 'class', $from.attr( 'class' ) );
93
94 mw.hook( 'wikipage.content' ).fire( $wikiPreview );
95
96 // Reattach
97 if ( $parent ) {
98 $parent.append( $wikiPreview );
99 } else {
100 $next.before( $wikiPreview );
101 }
102
103 } else {
104 $( copySelectors[i] )
105 .empty()
106 .append( $from.contents() )
107 .attr( 'class', $from.attr( 'class' ) );
108 }
109 }
110
111 // Deprecated: Use mw.hook instead
112 $( mw ).trigger( 'LivePreviewDone', [copySelectors] );
113
114 $spinner.remove();
115 $copyElements.animate( {
116 opacity: 1
117 }, 'fast' );
118 } );
119 }
120
121 $( function () {
122 // Do not enable on user .js/.css pages, as there's no sane way of "previewing"
123 // the scripts or styles without reloading the page.
124 if ( $( '#mw-userjsyoucanpreview' ).length || $( '#mw-usercssyoucanpreview' ).length ) {
125 return;
126 }
127
128 // The following elements can change in a preview but are not output
129 // by the server when they're empty until the preview response.
130 // TODO: Make the server output these always (in a hidden state), so we don't
131 // have to fish and (hopefully) put them in the right place (since skins
132 // can change where they are output).
133
134 if ( !document.getElementById( 'p-lang' ) && document.getElementById( 'p-tb' ) ) {
135 $( '#p-tb' ).after(
136 $( '<div>' ).attr( 'id', 'p-lang' )
137 );
138 }
139
140 if ( !$( '.mw-summary-preview' ).length ) {
141 $( '.editCheckboxes' ).before(
142 $( '<div>' ).addClass( 'mw-summary-preview' )
143 );
144 }
145
146 if ( !document.getElementById( 'wikiDiff' ) && document.getElementById( 'wikiPreview' ) ) {
147 $( '#wikiPreview' ).after(
148 $( '<div>' ).attr( 'id', 'wikiDiff' )
149 );
150 }
151
152 // This should be moved down to '#editform', but is kept on the body for now
153 // because the LiquidThreads extension is re-using this module with only half
154 // the EditPage (doesn't include #editform presumably, bug 55463).
155 $( document.body ).on( 'click', '#wpPreview, #wpDiff', doLivePreview );
156 } );
157
158 }( mediaWiki, jQuery ) );