TheDJ has uploaded a new change for review. https://gerrit.wikimedia.org/r/122601
Change subject: Add a status bar to the CodeEditor ...................................................................... Add a status bar to the CodeEditor - Show counts of errors/warnings/info annotations. This is useful because the annotations are in the gutter, so in big files it takes a lot of scrolling to look for errors - Clicking the totals count skips you to the 'next' annotation - If the current line contains an error, show the message of the error in the status bar. - Show the current line:column number, the selection range and the editor mode. - Degrades to a useful and readable but not pretty state in IE7 More complex version of: Ib9f08fcbc0365302756095b9027289736856fc73 Bug: 63294 Change-Id: Ided0804d5eb7864452287087dd1cf5a3dd8ff078 --- M CodeEditor.php A modules/jquery.codeEditor.css M modules/jquery.codeEditor.js 3 files changed, 214 insertions(+), 2 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/CodeEditor refs/changes/01/122601/1 diff --git a/CodeEditor.php b/CodeEditor.php index f261776..cd25758 100644 --- a/CodeEditor.php +++ b/CodeEditor.php @@ -14,7 +14,7 @@ 'path' => __FILE__, 'name' => 'CodeEditor', 'url' => 'https://www.mediawiki.org/wiki/Extension:CodeEditor', - 'author' => array( 'Brion Vibber', 'authors of Ace (ajax.org)' ), + 'author' => array( 'Brion Vibber', 'Derk-Jan Hartman', 'authors of Ace (ajax.org)' ), 'descriptionmsg' => 'codeeditor-desc', ); @@ -43,6 +43,7 @@ $wgResourceModules['jquery.codeEditor'] = array( 'scripts' => 'jquery.codeEditor.js', + 'styles' => 'jquery.codeEditor.css', 'dependencies' => array( 'jquery.wikiEditor', 'ext.codeEditor.ace', diff --git a/modules/jquery.codeEditor.css b/modules/jquery.codeEditor.css new file mode 100644 index 0000000..00eab13 --- /dev/null +++ b/modules/jquery.codeEditor.css @@ -0,0 +1,38 @@ +.codeEditor-status { + clear: both; + width: 100%; + background-color: #F0F0F0; + border-top: 1px solid silver; + display: table; +} + +.codeEditor-status .codeEditor-status-worker-cell.ace_gutter-cell { + background-position: 0px center; +} + +.codeEditor-status-worker { + padding: 0 0.3em; + cursor: pointer; + display: table-cell; + *float: left; + *width: 10em; +} + +.codeEditor-status-message { + border-left: 1px solid silver; + border-right: 1px solid silver; + padding: 0 0.3em; + width: 100%; + display: table-cell; + *float: left; + *width: auto; +} + +.codeEditor-status-line { + padding: 0 0.3em; + text-align: right; + white-space: nowrap; + display: table-cell; + *float: right; + *width: 4em; +} diff --git a/modules/jquery.codeEditor.js b/modules/jquery.codeEditor.js index ede9eb6..7223a0a 100644 --- a/modules/jquery.codeEditor.js +++ b/modules/jquery.codeEditor.js @@ -221,6 +221,8 @@ } } ); + context.fn.setupStatusBar(); + summary = $( '#wpSummary' ); // Let modules know we're ready to start working with the content context.fn.trigger( 'ready' ); @@ -242,6 +244,7 @@ // @todo fetch cursor, scroll position // Drop the fancy editor widget... + context.fn.removeStatusBar(); context.$codeEditorContainer.remove(); context.$codeEditorContainer = undefined; context.$iframe = undefined; @@ -276,7 +279,177 @@ } onHashChange(); - $( window ).bind( 'hashchange', onHashChange ); + $( window ).on( 'hashchange', onHashChange ); + }, + /** + * This creates a Statusbar, that allows you to see a count of the + */ + 'setupStatusBar': function ( ) { + var shouldUpdateAnnotations, + shouldUpdateSelection, + shouldUpdateLineInfo, + nextAnnotation, + delayedUpdate, + editor = context.codeEditor, + lang = require( 'ace/lib/lang' ), + $errors = $( '<span class="codeEditor-status-worker-cell ace_gutter-cell ace_error">0</span>' ), + $warnings = $( '<span class="codeEditor-status-worker-cell ace_gutter-cell ace_warning">0</span>' ), + $infos = $( '<span class="codeEditor-status-worker-cell ace_gutter-cell ace_info">0</span>' ), + $message = $( '<div/>' ).addClass( 'codeEditor-status-message' ), + $lineAndMode = $( '<div/>' ).addClass( 'codeEditor-status-line' ), + $workerStatus = $( '<div/>' ) + .addClass( 'codeEditor-status-worker' ) + .append( $errors ) + .append( $warnings ) + .append( $infos ); + + context.$statusBar = $( '<div/>' ) + .addClass( 'codeEditor-status' ) + .append( $workerStatus ) + .append( $message ) + .append( $lineAndMode ); + + // Function to delay/debounce updates for the StatusBar + delayedUpdate = lang.delayedCall( function() { + updateStatusBar( editor ); + }.bind( this ) ); + + /** + * Click handler that allows you to skip to the next annotation + */ + $workerStatus.on( 'click', function( e ) { + if( nextAnnotation ) { + context.codeEditor.navigateTo( nextAnnotation.row, nextAnnotation.column ); + // Scroll up a bit to give some context + context.codeEditor.scrollToRow( nextAnnotation.row - 3 ); + e.preventDefault(); + } + } ); + + /* Help function to concatenate strings with different separators */ + function addToStatus( status, str, separator ) { + if ( str ) { + status.push( str, separator || '|' ); + } + } + + /** + * Update all the information in the status bar + */ + function updateStatusBar() { + var annotation, + errors = 0, + warnings = 0, + infos = 0, + distance = NaN, + shortestDistance = Infinity, + closestAnnotation, + currentLine = editor.selection.lead.row, + annotations = context.codeEditor.getSession().getAnnotations(); + + // Reset the next annotation + nextAnnotation = null; + + for ( var i = 0; i < annotations.length; i++ ) { + annotation = annotations[i]; + distance = Math.abs( currentLine - annotation.row ); + + if ( distance < shortestDistance ) { + shortestDistance = distance; + closestAnnotation = annotation; + } + if ( nextAnnotation === null && annotation.row > currentLine ) { + nextAnnotation = annotation; + } + + switch ( annotations[i].type ) { + case 'error': + errors++; + break; + case 'warning': + warnings++; + break; + case 'info': + infos++; + break; + } + } + // Wrap around to the beginning for nextAnnotation + if ( nextAnnotation === null && annotations.length > 0 ) { + nextAnnotation = annotations[0]; + } + // Update the annotation counts + if ( shouldUpdateAnnotations ) { + $errors.text( errors ); + $warnings.text( warnings ); + $infos.text( infos ); + } + + // Show the message of the current line, if we have not already done so + if ( closestAnnotation && + currentLine === closestAnnotation.row && + closestAnnotation !== $message.data( 'annotation') ) { + $message.data( 'annotation', closestAnnotation ); + $message.text( $.ucFirst( closestAnnotation.type ) + ': ' + closestAnnotation.text ); + } else if ( null !== $message.data( 'annotation' ) && ( closestAnnotation && currentLine !== closestAnnotation.row ) ) { + // If we are on a different line without an annotation, then blank the message + $message.data( 'annotation', null ); + $message.text( '' ); + } + + // The cursor position has changed + if ( shouldUpdateSelection || shouldUpdateLineInfo ) { + // Adapted from Ajax.org's ace/ext/statusbar module + var status = []; + + + + if ( editor.$vimModeHandler ) { + addToStatus( status, editor.$vimModeHandler.getStatusText() ); + } else if ( editor.commands.recording ) { + addToStatus( status, 'REC' ); + } + + var c = editor.selection.lead; + addToStatus( status, ( c.row + 1 ) + ':' + c.column, ''); + if ( !editor.selection.isEmpty() ) { + var r = editor.getSelectionRange(); + addToStatus( status, '(' + ( r.end.row - r.start.row ) + ':' + ( r.end.column - r.start.column ) + ')' ); + } + status.pop(); + $lineAndMode.text( status.join('') ); + } + + shouldUpdateLineInfo = shouldUpdateSelection = shouldUpdateAnnotations = false; + } + + editor.getSession().on( 'changeAnnotation', function() { + shouldUpdateAnnotations = true; + delayedUpdate.schedule( 100 ); + } ); + editor.on( 'changeStatus', function() { + shouldUpdateLineInfo = true; + delayedUpdate.schedule( 100 ); + } ); + editor.on( 'changeSelection', function() { + shouldUpdateSelection = true; + delayedUpdate.schedule( 100 ); + } ); + + // Force update + shouldUpdateLineInfo = shouldUpdateSelection = shouldUpdateAnnotations = true; + updateStatusBar( editor ); + + context.$statusBar.insertAfter( $( '.wikiEditor-ui-view' ) ); + }, + removeStatusBar: function() { + context.codeEditor.getSession().removeListener( 'changeAnnotation' ); + context.codeEditor.removeListener( 'changeSelection' ); + context.codeEditor.removeListener( 'changeStatus' ); + context.nextAnnotation = null; + context.$statusBar = null; + + $('.codeEditor-status').remove(); } } ); -- To view, visit https://gerrit.wikimedia.org/r/122601 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: newchange Gerrit-Change-Id: Ided0804d5eb7864452287087dd1cf5a3dd8ff078 Gerrit-PatchSet: 1 Gerrit-Project: mediawiki/extensions/CodeEditor Gerrit-Branch: master Gerrit-Owner: TheDJ <hartman.w...@gmail.com> _______________________________________________ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits