Adding new debugging toolbar
[lhc/web/wiklou.git] / resources / mediawiki / mediawiki.debug.js
1 /**
2 * Javascript for the new debug toolbar, enabled with $wgDebugToolbar
3 *
4 * @author John Du Hart
5 * @since 1.19
6 */
7
8 ( function( $ ) {
9
10 var debug = mw.Debug = {
11 /**
12 * Toolbar container element
13 *
14 * @var {jQuery}
15 */
16 $container: null,
17
18 /**
19 * Array containing data for the debug toolbar
20 *
21 * @var {Array}
22 */
23 data: {},
24
25 /**
26 * Initializes the debugging pane
27 *
28 * @param {Array} data
29 */
30 init: function( data ) {
31 this.data = data;
32 this.buildHtml();
33
34 // Insert the container into the DOM
35 $( 'body' ).append( this.$container );
36
37 $( '.mw-debug-panelink' ).click( this.switchPane );
38 },
39
40 /**
41 * Switches between panes
42 *
43 * @todo Store cookie for last pane open
44 * @context {Element}
45 * @param {jQuery.Event} e
46 */
47 switchPane: function( e ) {
48 var currentPaneId = debug.$container.data( 'currentPane' ),
49 requestedPaneId = $(this).parent().attr( 'id' ).substr( 9 ),
50 $currentPane = $( '#mw-debug-pane-' + currentPaneId ),
51 $requestedPane = $( '#mw-debug-pane-' + requestedPaneId );
52 e.preventDefault();
53
54 // Hide the current pane
55 if ( requestedPaneId === currentPaneId ) {
56 $currentPane.slideUp();
57 debug.$container.data( 'currentPane', null );
58 return;
59 }
60
61 debug.$container.data( 'currentPane', requestedPaneId );
62
63 if ( currentPaneId === undefined || currentPaneId === null ) {
64 $requestedPane.slideDown();
65 } else {
66 $currentPane.hide();
67 $requestedPane.show();
68 }
69 },
70
71 /**
72 * Constructs the HTML for the debugging toolbar
73 */
74 buildHtml: function() {
75 this.$container = $( '<div></div>' )
76 .attr({
77 id: 'mw-debug-container',
78 class: 'mw-debug'
79 });
80
81 var html = '';
82
83 html += '<div class="mw-debug-bit" id="mw-debug-mwversion">'
84 + '<a href="//www.mediawiki.org/">MediaWiki</a>: '
85 + this.data.mwVersion + '</div>';
86
87 html += '<div class="mw-debug-bit" id="mw-debug-phpversion">'
88 + '<a href="//www.php.net/">PHP</a>: '
89 + this.data.phpVersion + '</div>';
90
91 html += '<div class="mw-debug-bit" id="mw-debug-time">'
92 + 'Time: ' + this.data.time.toFixed( 5 ) + 's</div>';
93 html += '<div class="mw-debug-bit" id="mw-debug-memory">'
94 + 'Memory: ' + this.data.memory + ' (<span title="Peak usage">'
95 + this.data.memoryPeak + '</span>)</div>';
96
97 var queryLink = '<a href="#" class="mw-debug-panelink" id="mw-debug-query-link">Queries: '
98 + this.data.queries.length + '</a>';
99 html += '<div class="mw-debug-bit" id="mw-debug-querylist">'
100 + queryLink + '</div>';
101
102 var debugLink = '<a href="#" class="mw-debug-panelink" id="mw-debug-debuglog-link">Debug Log ('
103 + this.data.debugLog.length + ' lines)</a>';
104 html += '<div class="mw-debug-bit" id="mw-debug-debuglog">'
105 + debugLink + '</div>';
106
107 var requestLink = '<a href="#" class="mw-debug-panelink" id="mw-debug-request-link">Request</a>';
108 html += '<div class="mw-debug-bit" id="mw-debug-request">'
109 + requestLink + '</div>';
110
111 var filesLink = '<a href="#" class="mw-debug-panelink" id="mw-debug-files-includes">'
112 + this.data.includes.length + ' Files Included</a>';
113 html += '<div class="mw-debug-bit" id="mw-debug-includes">'
114 + filesLink + '</div>';
115
116 html += '<div class="mw-debug-pane" id="mw-debug-pane-querylist">'
117 + this.buildQueryTable() + '</div>';
118 html += '<div class="mw-debug-pane" id="mw-debug-pane-debuglog">'
119 + this.buildDebugLogTable() + '</div>';
120 html += '<div class="mw-debug-pane" id="mw-debug-pane-request">'
121 + this.buildRequestPane() + '</div>';
122 html += '<div class="mw-debug-pane" id="mw-debug-pane-includes">'
123 + this.buildIncludesPane() + '</div>';
124
125 this.$container.html( html );
126 },
127
128 /**
129 * Query list pane
130 */
131 buildQueryTable: function() {
132 var html = '<table id="mw-debug-querylist">';
133
134 for ( var i = 0, length = this.data.queries.length; i < length; i++ ) {
135 var query = this.data.queries[i];
136
137 html += '<tr><td>' + ( i + 1 ) + '</td>';
138
139 html += '<td>' + query.sql + '</td>';
140 html += '<td><span class="mw-debug-query-time">(' + query.time.toFixed( 4 ) + 'ms)</span> ' + query.function + '</td>';
141
142 html += '</tr>';
143 }
144
145 html += '</table>';
146
147 return html;
148 },
149
150 /**
151 * Legacy debug log pane
152 */
153 buildDebugLogTable: function() {
154 var html = '<ul>';
155
156 for ( var i = 0, length = this.data.debugLog.length; i < length; i++ ) {
157 var line = this.data.debugLog[i];
158 html += '<li>' + line.replace( /\n/g, "<br />\n" ) + '</li>';
159 }
160
161 return html + '</ul>';
162 },
163
164 /**
165 * Request information pane
166 */
167 buildRequestPane: function() {
168 var buildTable = function( title, data ) {
169 var t = '<h2>' + title + '</h2>'
170 + '<table> <tr> <th>Key</th> <th>Value</th> </tr>';
171
172 for ( var key in data ) {
173 if ( !data.hasOwnProperty( key ) ) {
174 continue;
175 }
176 var value = data[key];
177
178 t += '<tr><th>' + key + '</th><td>' + value + '</td></tr>';
179 }
180
181 t += '</table>';
182 return t;
183 };
184
185 var html = this.data.request.method + ' ' + this.data.request.url;
186 html += buildTable( 'Headers', this.data.request.headers );
187 html += buildTable( 'Parameters', this.data.request.params );
188
189 return html;
190 },
191
192 /**
193 * Included files pane
194 */
195 buildIncludesPane: function() {
196 var html = '<ul>';
197
198 for ( var i = 0, l = this.data.includes.length; i < l; i++ ) {
199 var file = this.data.includes[i];
200 html += '<li><span class="mw-debug-right">' + file.size + '</span> ' + file.name + '</li>';
201 }
202
203 html += '</ul>';
204 return html;
205 }
206 };
207
208 } )( jQuery );