/** * JavaScript for the new debug toolbar, enabled with $wgDebugToolbar * * @author John Du Hart * @since 1.19 */ ( function ( $, mw, undefined ) { "use strict"; var hovzer = $.getFootHovzer(); var debug = mw.Debug = { /** * Toolbar container element * * @var {jQuery} */ $container: null, /** * Object containing data for the debug toolbar * * @var {Object} */ data: {}, /** * Initializes the debugging pane * * @param {Object} data */ init: function ( data ) { this.data = data; this.buildHtml(); // Insert the container into the DOM hovzer.$.append( this.$container ); hovzer.update(); $( '.mw-debug-panelink' ).click( this.switchPane ); }, /** * Switches between panes * * @todo Store cookie for last pane open * @context {Element} * @param {jQuery.Event} e */ switchPane: function ( e ) { var currentPaneId = debug.$container.data( 'currentPane' ), requestedPaneId = $(this).prop( 'id' ).substr( 9 ), $currentPane = $( '#mw-debug-pane-' + currentPaneId ), $requestedPane = $( '#mw-debug-pane-' + requestedPaneId ), hovDone = false; function updateHov() { if ( !hovDone ) { hovzer.update(); hovDone = true; } } $( this ).addClass( 'current '); $( '.mw-debug-panelink' ).not( this ).removeClass( 'current '); // Hide the current pane if ( requestedPaneId === currentPaneId ) { $currentPane.slideUp( updateHov ); debug.$container.data( 'currentPane', null ); return; } debug.$container.data( 'currentPane', requestedPaneId ); if ( currentPaneId === undefined || currentPaneId === null ) { $requestedPane.slideDown( updateHov ); } else { $currentPane.hide(); $requestedPane.show(); updateHov(); } }, /** * Constructs the HTML for the debugging toolbar */ buildHtml: function () { var $container, $bits, panes, id; $container = $( '
' ); $bits = $( '
' ); /** * Returns a jQuery element for a debug-bit div * * @param id * @return {jQuery} */ function bitDiv( id ) { return $( '
' ).attr({ id: 'mw-debug-' + id, 'class': 'mw-debug-bit' }) .appendTo( $bits ); } /** * Returns a jQuery element for a pane link * * @param id * @param text * @return {jQuery} */ function paneLabel( id, text ) { return $( '' ) .attr({ 'class': 'mw-debug-panelabel', href: '#mw-debug-pane-' + id }) .text( text ); } /** * Returns a jQuery element for a debug-bit div with a for a pane link * * @param id * @return {jQuery} */ function paneTriggerBitDiv( id, text ) { return $( '
' ).attr({ id: 'mw-debug-' + id, 'class': 'mw-debug-bit mw-debug-panelink' }) .append( paneLabel( id, text ) ) .appendTo( $bits ); } paneTriggerBitDiv( 'console', 'Console (' + this.data.log.length + ')' ); paneTriggerBitDiv( 'querylist', 'Queries: ' + this.data.queries.length ); paneTriggerBitDiv( 'debuglog', 'Debug Log (' + this.data.debugLog.length + ' lines)' ); paneTriggerBitDiv( 'request', 'Request' ); paneTriggerBitDiv( 'includes', this.data.includes.length + ' Files Included' ); bitDiv( 'mwversion' ) .append( $( '' ).text( 'MediaWiki' ) ) .append( ': ' + this.data.mwVersion ); bitDiv( 'phpversion' ) .append( $( '' ).text( 'PHP' ) ) .append( ': ' + this.data.phpVersion ); bitDiv( 'time' ) .text( 'Time: ' + this.data.time.toFixed( 5 ) ); bitDiv( 'memory' ) .text( 'Memory: ' + this.data.memory ) .append( $( '' ).text( ' (' + this.data.memoryPeak + ')' ) ); $bits.appendTo( $container ); panes = { console: this.buildConsoleTable(), querylist: this.buildQueryTable(), debuglog: this.buildDebugLogTable(), request: this.buildRequestPane(), includes: this.buildIncludesPane() }; for ( id in panes ) { if ( !panes.hasOwnProperty( id ) ) { continue; } $( '
' ) .attr({ 'class': 'mw-debug-pane', id: 'mw-debug-pane-' + id }) .append( panes[id] ) .appendTo( $container ); } this.$container = $container; }, /** * Builds the console panel */ buildConsoleTable: function () { var $table, entryTypeText, i, length, entry; $table = $( '' ); $('').css( 'width', /*padding=*/20 + ( 10*/*fontSize*/11 ) ).appendTo( $table ); $('').appendTo( $table ); $('').css( 'width', 350 ).appendTo( $table ); entryTypeText = function( entryType ) { switch ( entryType ) { case 'log': return 'Log'; case 'warn': return 'Warning'; case 'deprecated': return 'Deprecated'; default: return 'Unknown'; } }; for ( i = 0, length = this.data.log.length; i < length; i += 1 ) { entry = this.data.log[i]; entry.typeText = entryTypeText( entry.type ); $( '' ) .append( $( '').css( 'width', /*padding=*/20 + ( String( this.data.queries.length ).length*/*fontSize*/11 ) ).appendTo( $table ); $('').appendTo( $table ); $('').css( 'width', 350 ).appendTo( $table ); for ( i = 0, length = this.data.queries.length; i < length; i += 1 ) { query = this.data.queries[i]; $( '' ) .append( $( '
' ) .text( entry.typeText ) .attr( 'class', 'mw-debug-console-' + entry.type ) ) .append( $( '' ).html( entry.msg ) ) .append( $( '' ).text( entry.caller ) ) .appendTo( $table ); } return $table; }, /** * Query list pane */ buildQueryTable: function () { var $table, i, length, query; $table = $( '
' ); // Widths on table cells and columns behave weird in some browsers like Chrome, // in that, contrary to the W3 box model, padding does not increase cells having a fixed width $('
' ).text( i + 1 ) ) .append( $( '' ).text( query.sql ) ) .append( $( '' ) .append( $( '' ).text( '(' + query.time.toFixed( 4 ) + 'ms) ' ) ) .append( query['function'] ) ) .appendTo( $table ); } return $table; }, /** * Legacy debug log pane */ buildDebugLogTable: function () { var $list, i, length, line; $list = $( '
    ' ); for ( i = 0, length = this.data.debugLog.length; i < length; i += 1 ) { line = this.data.debugLog[i]; $( '
  • ' ) .html( mw.html.escape( line ).replace( /\n/g, "
    \n" ) ) .appendTo( $list ); } return $list; }, /** * Request information pane */ buildRequestPane: function () { function buildTable( title, data ) { var $unit, $table, key; $unit = $( '
    ' ).append( $( '

    ' ).text( title ) ); $table = $( '' ).appendTo( $unit ); $( '' ) .html( '' ) .appendTo( $table ); for ( key in data ) { if ( !data.hasOwnProperty( key ) ) { continue; } $( '' ) .append( $( '
    KeyValue
    ' ).text( key ) ) .append( $( '' ).text( data[key] ) ) .appendTo( $table ); } return $unit; } return $( '
    ' ) .text( this.data.request.method + ' ' + this.data.request.url ) .append( buildTable( 'Headers', this.data.request.headers ) ) .append( buildTable( 'Parameters', this.data.request.params ) ); }, /** * Included files pane */ buildIncludesPane: function () { var $table, i, length, file; $table = $( '' ); for ( i = 0, length = this.data.includes.length; i < length; i += 1 ) { file = this.data.includes[i]; $( '' ) .append( $( '
    ' ).text( file.name ) ) .append( $( '' ).text( file.size ) ) .appendTo( $table ); } return $table; } }; } )( jQuery, mediaWiki );