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