%PDF- %PDF-
Direktori : /www/varak.net/wiki.varak.net/extensions/VisualEditor/lib/ve/src/ui/ |
Current File : /www/varak.net/wiki.varak.net/extensions/VisualEditor/lib/ve/src/ui/ve.ui.DebugBar.js |
/*! * VisualEditor DebugBar class. * * @copyright 2011-2016 VisualEditor Team and others; see http://ve.mit-license.org */ /** * Debug bar * * @class * @extends OO.ui.Element * * @constructor * @param {ve.ui.Surface} surface Surface to debug * @param {Object} [config] Configuration options */ ve.ui.DebugBar = function VeUiDebugBar( surface, config ) { var closeButton; // Parent constructor ve.ui.DebugBar.super.call( this, config ); this.surface = surface; this.$commands = $( '<div>' ).addClass( 've-ui-debugBar-commands' ); this.$linmodData = $( '<td>' ).addClass( 've-ui-debugBar-dump-linmod-data' ); this.$linmodMetadata = $( '<td>' ).addClass( 've-ui-debugBar-dump-linmod-metadata' ); this.$viewTree = $( '<td>' ).addClass( 've-ui-debugBar-view-tree' ); this.$modelTree = $( '<td>' ).addClass( 've-ui-debugBar-model-tree' ); closeButton = new OO.ui.ButtonWidget( { icon: 'close', label: 'Close' } ); // Widgets this.selectionLabel = new OO.ui.LabelWidget( { classes: [ 've-ui-debugBar-selectionLabel' ] } ); this.logRangeButton = new OO.ui.ButtonWidget( { label: 'Log', disabled: true } ); this.showModelToggle = new OO.ui.ToggleButtonWidget( { label: 'Show model' } ); this.updateModelToggle = new OO.ui.ToggleButtonWidget( { label: 'Update on changes' } ); this.inputDebuggingToggle = new OO.ui.ToggleButtonWidget( { label: 'Input debugging' } ); this.filibusterToggle = new OO.ui.ToggleButtonWidget( { label: 'Filibuster' } ); this.$dump = $( '<div class="ve-ui-debugBar-dump">' ).append( this.updateModelToggle.$element, $( '<table></table>' ).append( $( '<thead><th>Linear model data</th><th>Linear model metadata</th><th>View tree</th><th>Model tree</th></thead>' ), $( '<tbody>' ).append( $( '<tr>' ).append( this.$linmodData, this.$linmodMetadata, this.$viewTree, this.$modelTree ) ) ) ).hide(); this.$filibuster = $( '<div class="ve-ui-debugBar-filibuster"></div>' ); // Events this.logRangeButton.on( 'click', this.onLogRangeButtonClick.bind( this ) ); this.showModelToggle.on( 'change', this.onShowModelToggleChange.bind( this ) ); this.updateModelToggle.on( 'change', this.onUpdateModelToggleChange.bind( this ) ); this.inputDebuggingToggle.on( 'change', this.onInputDebuggingToggleChange.bind( this ) ); this.filibusterToggle.on( 'click', this.onFilibusterToggleClick.bind( this ) ); closeButton.on( 'click', this.$element.remove.bind( this.$element ) ); this.getSurface().getModel().connect( this, { select: 'onSurfaceSelect' } ); this.onSurfaceSelect( this.getSurface().getModel().getSelection() ); this.$element.addClass( 've-ui-debugBar' ); this.$element.append( this.$commands.append( this.selectionLabel.$element, this.logRangeButton.$element, $( this.constructor.static.dividerTemplate ), this.showModelToggle.$element, this.inputDebuggingToggle.$element, this.filibusterToggle.$element, $( this.constructor.static.dividerTemplate ), closeButton.$element ), this.$dump, this.$filibuster ); this.target = null; }; /* Inheritance */ OO.inheritClass( ve.ui.DebugBar, OO.ui.Element ); /** * Divider HTML template * * @property {string} */ ve.ui.DebugBar.static.dividerTemplate = '<span class="ve-ui-debugBar-commands-divider"> </span>'; /** * Get surface the debug bar is attached to * * @return {ve.ui.Surface|null} Surface */ ve.ui.DebugBar.prototype.getSurface = function () { return this.surface; }; /** * Handle select events on the attached surface * * @param {ve.dm.Selection} selection */ ve.ui.DebugBar.prototype.onSurfaceSelect = function ( selection ) { this.selectionLabel.setLabel( selection.getDescription() ); this.logRangeButton.setDisabled( !( ( selection instanceof ve.dm.LinearSelection && !selection.isCollapsed() ) || selection instanceof ve.dm.TableSelection ) ); }; /** * Handle click events on the log range button * * @param {jQuery.Event} e Event */ ve.ui.DebugBar.prototype.onLogRangeButtonClick = function () { var i, ranges, selection = this.getSurface().getModel().getSelection(); if ( selection instanceof ve.dm.LinearSelection || selection instanceof ve.dm.TableSelection ) { ranges = selection.getRanges(); for ( i = 0; i < ranges.length; i++ ) { ve.dir( this.getSurface().view.documentView.model.data.slice( ranges[ i ].start, ranges[ i ].end ) ); } } }; /** * Handle change events on the show model toggle * * @param {boolean} value Value */ ve.ui.DebugBar.prototype.onShowModelToggleChange = function ( value ) { if ( value ) { this.updateDump(); this.$dump.show(); } else { this.updateModelToggle.setValue( false ); this.$dump.hide(); } }; /** * Update the model dump */ ve.ui.DebugBar.prototype.updateDump = function () { var surface = this.getSurface(), documentModel = surface.getModel().getDocument(), documentView = surface.getView().getDocument(); // linear model dump this.$linmodData.html( this.generateListFromLinearData( documentModel.data ) ); this.$linmodMetadata.html( this.generateListFromLinearData( documentModel.metadata ) ); this.$modelTree.html( this.generateListFromNode( documentModel.getDocumentNode() ) ); this.$viewTree.html( this.generateListFromNode( documentView.getDocumentNode() ) ); }; /** * Get an ordered list representation of some linear data * * @param {ve.dm.LinearData} linearData Linear data * @return {jQuery} Ordered list */ ve.ui.DebugBar.prototype.generateListFromLinearData = function ( linearData ) { var i, $li, $label, element, text, annotations, data, $ol = $( '<ol start="0"></ol>' ); data = linearData instanceof ve.dm.LinearData ? linearData.data : linearData; for ( i = 0; i < data.length; i++ ) { $li = $( '<li>' ); $label = $( '<span>' ); element = data[ i ]; annotations = null; if ( linearData instanceof ve.dm.MetaLinearData ) { if ( element && element.length ) { $li.append( this.generateListFromLinearData( element ) ); } else { $li.append( $( '<span>undefined</span>' ).addClass( 've-ui-debugBar-dump-undefined' ) ); } } else { if ( element.type ) { $label.addClass( 've-ui-debugBar-dump-element' ); text = element.type; annotations = element.annotations; } else if ( Array.isArray( element ) ) { $label.addClass( 've-ui-debugBar-dump-achar' ); text = element[ 0 ]; annotations = element[ 1 ]; } else { $label.addClass( 've-ui-debugBar-dump-char' ); text = element; } $label.html( ( text.match( /\S/ ) ? text : ' ' ) + ' ' ); if ( annotations ) { $label.append( /*jshint loopfunc:true */ $( '<span>' ).text( '[' + this.getSurface().getModel().getDocument().getStore().values( annotations ).map( function ( ann ) { return JSON.stringify( ann.getComparableObject() ); } ).join( ', ' ) + ']' ) ); } $li.append( $label ); } $ol.append( $li ); } return $ol; }; /** * Generate an ordered list describing a node * * @param {ve.Node} node Node * @return {jQuery} Ordered list */ ve.ui.DebugBar.prototype.generateListFromNode = function ( node ) { var $li, i, $label, $ol = $( '<ol start="0"></ol>' ); for ( i = 0; i < node.children.length; i++ ) { $li = $( '<li>' ); $label = $( '<span>' ).addClass( 've-ui-debugBar-dump-element' ); if ( node.children[ i ].length !== undefined ) { $li.append( $label .text( node.children[ i ].type ) .append( $( '<span>' ).text( ' (' + node.children[ i ].length + ')' ) ) ); } else { $li.append( $label.text( node.children[ i ].type ) ); } if ( node.children[ i ].children ) { $li.append( this.generateListFromNode( node.children[ i ] ) ); } $ol.append( $li ); } return $ol; }; /** * Handle change events on the update model toggle button * * @param {boolean} value Value */ ve.ui.DebugBar.prototype.onUpdateModelToggleChange = function ( value ) { if ( value ) { this.updateDump(); this.getSurface().model.connect( this, { documentUpdate: 'updateDump' } ); } else { this.getSurface().model.disconnect( this, { documentUpdate: 'updateDump' } ); } }; /** * Handle click events on the input debugging toggle button * * @param {boolean} value Value */ ve.ui.DebugBar.prototype.onInputDebuggingToggleChange = function ( value ) { var surfaceModel = this.getSurface().getModel(), selection = surfaceModel.getSelection(); ve.inputDebug = value; // Clear the cursor before rebuilding, it will be restored later surfaceModel.setNullSelection(); setTimeout( function () { surfaceModel.getDocument().rebuildTree(); surfaceModel.setSelection( selection ); } ); }; /** * Handle click events on the filibuster toggle button * * @param {jQuery.Event} e Event */ ve.ui.DebugBar.prototype.onFilibusterToggleClick = function () { var debugBar = this; if ( this.filibusterToggle.getValue() ) { this.filibusterToggle.setLabel( 'Stop Filibuster' ); this.$filibuster.off( 'click' ); this.$filibuster.hide(); this.$filibuster.empty(); this.getSurface().startFilibuster(); } else { this.getSurface().stopFilibuster(); this.$filibuster.html( this.getSurface().filibuster.getObservationsHtml() ); this.$filibuster.show(); this.$filibuster.on( 'click', function ( e ) { var path, $li = $( e.target ).closest( '.ve-filibuster-frame' ); if ( $li.hasClass( 've-filibuster-frame-expandable' ) ) { $li.removeClass( 've-filibuster-frame-expandable' ); path = $li.data( 've-filibuster-frame' ); if ( !path ) { return; } $li.children( 'span' ).replaceWith( $( debugBar.getSurface().filibuster.getObservationsHtml( path ) ) ); $li.toggleClass( 've-filibuster-frame-expanded' ); } else if ( $li.children( 'ul' ).length ) { $li.toggleClass( 've-filibuster-frame-collapsed' ); $li.toggleClass( 've-filibuster-frame-expanded' ); } } ); this.filibusterToggle.setLabel( 'Filibuster' ); } }; /** * Destroy the debug bar */ ve.ui.DebugBar.prototype.destroy = function () { this.getSurface().getModel().disconnect(); this.$element.remove(); };