[mw.debug] Clean up
[mediawiki.git] / resources / mediawiki / mediawiki.debug.js
bloba2bfbcbe30677755cba1f5c93795501a37d25395
1 /**
2  * JavaScript for the new debug toolbar, enabled through $wgDebugToolbar.
3  *
4  * @author John Du Hart
5  * @since 1.19
6  */
8 ( function ( $, mw, undefined ) {
9 "use strict";
11         var hovzer = $.getFootHovzer();
13         var debug = mw.Debug = {
14                 /**
15                  * Toolbar container element
16                  *
17                  * @var {jQuery}
18                  */
19                 $container: null,
21                 /**
22                  * Object containing data for the debug toolbar
23                  *
24                  * @var {Object}
25                  */
26                 data: {},
28                 /**
29                  * Initializes the debugging pane.
30                  * Shouldn't be called before the document is ready
31                  * (since it binds to elements on the page).
32                  *
33                  * @param {Object} data, defaults to 'debugInfo' from mw.config
34                  */
35                 init: function ( data ) {
37                         this.data = data || mw.config.get( 'debugInfo' );
38                         this.buildHtml();
40                         // Insert the container into the DOM
41                         hovzer.$.append( this.$container );
42                         hovzer.update();
44                         $( '.mw-debug-panelink' ).click( this.switchPane );
45                 },
47                 /**
48                  * Switches between panes
49                  *
50                  * @todo Store cookie for last pane open
51                  * @context {Element}
52                  * @param {jQuery.Event} e
53                  */
54                 switchPane: function ( e ) {
55                         var currentPaneId = debug.$container.data( 'currentPane' ),
56                                 requestedPaneId = $(this).prop( 'id' ).substr( 9 ),
57                                 $currentPane = $( '#mw-debug-pane-' + currentPaneId ),
58                                 $requestedPane = $( '#mw-debug-pane-' + requestedPaneId ),
59                                 hovDone = false;
61                         function updateHov() {
62                                 if ( !hovDone ) {
63                                         hovzer.update();
64                                         hovDone = true;
65                                 }
66                         }
68                         // Skip hash fragment handling. Prevents screen from jumping.
69                         e.preventDefault();
71                         $( this ).addClass( 'current ');
72                         $( '.mw-debug-panelink' ).not( this ).removeClass( 'current ');
74                         // Hide the current pane
75                         if ( requestedPaneId === currentPaneId ) {
76                                 $currentPane.slideUp( updateHov );
77                                 debug.$container.data( 'currentPane', null );
78                                 return;
79                         }
81                         debug.$container.data( 'currentPane', requestedPaneId );
83                         if ( currentPaneId === undefined || currentPaneId === null ) {
84                                 $requestedPane.slideDown( updateHov );
85                         } else {
86                                 $currentPane.hide();
87                                 $requestedPane.show();
88                                 updateHov();
89                         }
90                 },
92                 /**
93                  * Constructs the HTML for the debugging toolbar
94                  */
95                 buildHtml: function () {
96                         var $container, $bits, panes, id;
98                         $container = $( '<div id="mw-debug-toolbar" class="mw-debug"></div>' );
100                         $bits = $( '<div class="mw-debug-bits"></div>' );
102                         /**
103                          * Returns a jQuery element for a debug-bit div
104                          *
105                          * @param id
106                          * @return {jQuery}
107                          */
108                         function bitDiv( id ) {
109                                 return $( '<div>' ).attr({
110                                         id: 'mw-debug-' + id,
111                                         'class': 'mw-debug-bit'
112                                 })
113                                 .appendTo( $bits );
114                         }
116                         /**
117                          * Returns a jQuery element for a pane link
118                          *
119                          * @param id
120                          * @param text
121                          * @return {jQuery}
122                          */
123                         function paneLabel( id, text ) {
124                                 return $( '<a>' )
125                                         .attr({
126                                                 'class': 'mw-debug-panelabel',
127                                                 href: '#mw-debug-pane-' + id
128                                         })
129                                         .text( text );
130                         }
132                         /**
133                          * Returns a jQuery element for a debug-bit div with a for a pane link
134                          *
135                          * @param id CSS id snippet. Will be prefixed with 'mw-debug-'
136                          * @param text Text to show
137                          * @param count Optional count to show
138                          * @return {jQuery}
139                          */
140                         function paneTriggerBitDiv( id, text, count ) {
141                                 if( count ) {
142                                         text = text + ' (' + count + ')';
143                                 }
144                                 return $( '<div>' ).attr({
145                                         id: 'mw-debug-' + id,
146                                         'class': 'mw-debug-bit mw-debug-panelink'
147                                 })
148                                 .append( paneLabel( id, text ) )
149                                 .appendTo( $bits );
150                         }
152                         paneTriggerBitDiv( 'console', 'Console', this.data.log.length );
154                         paneTriggerBitDiv( 'querylist', 'Queries', this.data.queries.length );
156                         paneTriggerBitDiv( 'debuglog', 'Debug log', this.data.debugLog.length );
158                         paneTriggerBitDiv( 'request', 'Request' );
160                         paneTriggerBitDiv( 'includes', 'PHP includes', this.data.includes.length );
162                         bitDiv( 'mwversion' )
163                                 .append( $( '<a href="//www.mediawiki.org/"></a>' ).text( 'MediaWiki' ) )
164                                 .append( ': ' + this.data.mwVersion );
166                         bitDiv( 'phpversion' )
167                                 .append( $( '<a href="//www.php.net/"></a>' ).text( 'PHP' ) )
168                                 .append( ': ' + this.data.phpVersion );
170                         bitDiv( 'time' )
171                                 .text( 'Time: ' + this.data.time.toFixed( 5 ) );
173                         bitDiv( 'memory' )
174                                 .text( 'Memory: ' + this.data.memory )
175                                 .append( $( '<span title="Peak usage"></span>' ).text( ' (' + this.data.memoryPeak + ')' ) );
176                                 
178                         $bits.appendTo( $container );
180                         panes = {
181                                 console: this.buildConsoleTable(),
182                                 querylist: this.buildQueryTable(),
183                                 debuglog: this.buildDebugLogTable(),
184                                 request: this.buildRequestPane(),
185                                 includes: this.buildIncludesPane()
186                         };
188                         for ( id in panes ) {
189                                 if ( !panes.hasOwnProperty( id ) ) {
190                                         continue;
191                                 }
193                                 $( '<div>' )
194                                         .attr({
195                                                 'class': 'mw-debug-pane',
196                                                 id: 'mw-debug-pane-' + id
197                                         })
198                                         .append( panes[id] )
199                                         .appendTo( $container );
200                         }
202                         this.$container = $container;
203                 },
205                 /**
206                  * Builds the console panel
207                  */
208                 buildConsoleTable: function () {
209                         var $table, entryTypeText, i, length, entry;
211                         $table = $( '<table id="mw-debug-console">' );
213                         $('<colgroup>').css( 'width', /*padding=*/20 + ( 10*/*fontSize*/11 ) ).appendTo( $table );
214                         $('<colgroup>').appendTo( $table );
215                         $('<colgroup>').css( 'width', 350 ).appendTo( $table );
218                         entryTypeText = function( entryType ) {
219                                 switch ( entryType ) {
220                                         case 'log':
221                                                 return 'Log';
222                                         case 'warn':
223                                                 return 'Warning';
224                                         case 'deprecated':
225                                                 return 'Deprecated';
226                                         default:
227                                                 return 'Unknown';
228                                 }
229                         };
231                         for ( i = 0, length = this.data.log.length; i < length; i += 1 ) {
232                                 entry = this.data.log[i];
233                                 entry.typeText = entryTypeText( entry.type );
235                                 $( '<tr>' )
236                                         .append( $( '<td>' )
237                                                 .text( entry.typeText )
238                                                 .attr( 'class', 'mw-debug-console-' + entry.type )
239                                         )
240                                         .append( $( '<td>' ).html( entry.msg ) )
241                                         .append( $( '<td>' ).text( entry.caller ) )
242                                         .appendTo( $table );
243                         }
245                         return $table;
246                 },
248                 /**
249                  * Query list pane
250                  */
251                 buildQueryTable: function () {
252                         var $table, i, length, query;
254                         $table = $( '<table id="mw-debug-querylist"></table>' );
256                         $( '<tr>' )
257                                 .append( $('<th>#</th>').css( 'width', '4em' )    )
258                                 .append( $('<th>SQL</th>') )
259                                 .append( $('<th>Time</th>').css( 'width', '8em'  ) )
260                                 .append( $('<th>Call</th>').css( 'width', '18em' ) )
261                         .appendTo( $table );
263                         for ( i = 0, length = this.data.queries.length; i < length; i += 1 ) {
264                                 query = this.data.queries[i];
266                                 $( '<tr>' )
267                                         .append( $( '<td>' ).text( i + 1 ) )
268                                         .append( $( '<td>' ).text( query.sql ) )
269                                         .append( $( '<td class="stats">' ).text( ( query.time * 1000 ).toFixed( 4 ) + 'ms' ) )
270                                         .append( $( '<td>' ).text( query['function'] ) )
271                                 .appendTo( $table );
272                         }
275                         return $table;
276                 },
278                 /**
279                  * Legacy debug log pane
280                  */
281                 buildDebugLogTable: function () {
282                         var $list, i, length, line;
283                         $list = $( '<ul>' );
285                         for ( i = 0, length = this.data.debugLog.length; i < length; i += 1 ) {
286                                 line = this.data.debugLog[i];
287                                 $( '<li>' )
288                                         .html( mw.html.escape( line ).replace( /\n/g, "<br />\n" ) )
289                                         .appendTo( $list );
290                         }
292                         return $list;
293                 },
295                 /**
296                  * Request information pane
297                  */
298                 buildRequestPane: function () {
300                         function buildTable( title, data ) {
301                                 var $unit, $table, key;
303                                 $unit = $( '<div>' ).append( $( '<h2>' ).text( title ) );
305                                 $table = $( '<table>' ).appendTo( $unit );
307                                 $( '<tr>' )
308                                         .html( '<th>Key</th><th>Value</th>' )
309                                         .appendTo( $table );
311                                 for ( key in data ) {
312                                         if ( !data.hasOwnProperty( key ) ) {
313                                                 continue;
314                                         }
316                                         $( '<tr>' )
317                                                 .append( $( '<th>' ).text( key ) )
318                                                 .append( $( '<td>' ).text( data[key] ) )
319                                                 .appendTo( $table );
320                                 }
322                                 return $unit;
323                         }
325                         return $( '<div>' )
326                                 .text( this.data.request.method + ' ' + this.data.request.url )
327                                 .append( buildTable( 'Headers', this.data.request.headers ) )
328                                 .append( buildTable( 'Parameters', this.data.request.params ) );
329                 },
331                 /**
332                  * Included files pane
333                  */
334                 buildIncludesPane: function () {
335                         var $table, i, length, file;
337                         $table = $( '<table>' );
339                         for ( i = 0, length = this.data.includes.length; i < length; i += 1 ) {
340                                 file = this.data.includes[i];
341                                 $( '<tr>' )
342                                         .append( $( '<td>' ).text( file.name ) )
343                                         .append( $( '<td class="nr">' ).text( file.size ) )
344                                         .appendTo( $table );
345                         }
347                         return $table;
348                 }
349         };
351 } )( jQuery, mediaWiki );