@@ -10,6 +10,11 @@ codeInput.plugins.GoToLine = class extends codeInput.Plugin {
1010 instructions = {
1111 closeDialog : "Close Dialog and Return to Editor" ,
1212 input : "Line:Column / Line no. then Enter" ,
13+ guidanceFormat : "Wrong format. Enter a line number (e.g. 1) or a line number then colon then column number (e.g. 1:3)." ,
14+ guidanceLineRange : ( current , max ) => { return `Line number (currently ${ current } ) should be between 1 and ${ max } inclusive.` } ,
15+ guidanceColumnRange : ( line , current , max ) => { return `On line ${ line } , column number (currently ${ current } ) should be between 1 and ${ max } inclusive.` } ,
16+ guidanceValidLine : ( line , column ) => { return `Press Enter to go to line ${ line } .` } ,
17+ guidanceValidColumn : ( line , column ) => { return `Press Enter to go to line ${ line } , column ${ column } .` } ,
1318 } ;
1419
1520 /**
@@ -33,32 +38,51 @@ codeInput.plugins.GoToLine = class extends codeInput.Plugin {
3338
3439 /* Called with a dialog box keyup event to check the validity of the line number entered and submit the dialog if Enter is pressed */
3540 checkPrompt ( dialog , event ) {
41+ if ( event . key == 'Escape' ) return this . cancelPrompt ( dialog , event ) ;
42+
3643 // Line number(:column number)
3744 const lines = dialog . textarea . value . split ( '\n' ) ;
3845 const maxLineNo = lines . length ;
3946 const lineNo = Number ( dialog . input . value . split ( ':' ) [ 0 ] ) ;
4047 let columnNo = 0 ; // Means go to start of indented line
4148 let maxColumnNo = 1 ;
4249 const querySplitByColons = dialog . input . value . split ( ':' ) ;
43- if ( querySplitByColons . length > 2 ) return dialog . input . classList . add ( 'code-input_go-to-line_error' ) ;
4450
45- if ( event . key == 'Escape' ) return this . cancelPrompt ( dialog , event ) ;
51+ // Invalid format
52+ if ( querySplitByColons . length > 2 || ! / ^ [ 0 - 9 : ] * $ / . test ( dialog . input . value ) ) {
53+ dialog . guidance . textContent = this . instructions . guidanceFormat ;
54+ return dialog . input . classList . add ( 'code-input_go-to-line_error' ) ;
55+ }
4656
57+ // Number(s) present
4758 if ( dialog . input . value ) {
48- if ( ! / ^ [ 0 - 9 : ] * $ / . test ( dialog . input . value ) || lineNo < 1 || lineNo > maxLineNo ) {
59+ if ( lineNo < 1 || lineNo > maxLineNo ) {
60+ // Out-of-range line number
61+ dialog . guidance . textContent = this . instructions . guidanceLineRange ( lineNo , maxLineNo ) ;
4962 return dialog . input . classList . add ( 'code-input_go-to-line_error' ) ;
5063 } else {
51- // Check if line:column
64+ // Check if line:column - if so calculate column number
5265 if ( querySplitByColons . length >= 2 ) {
5366 columnNo = Number ( querySplitByColons [ 1 ] ) ;
54- maxColumnNo = lines [ lineNo - 1 ] . length ;
67+ maxColumnNo = lines [ lineNo - 1 ] . length + 1 ; // column 1 always works since at start of line
5568 }
5669 if ( columnNo < 0 || columnNo > maxColumnNo ) {
70+ dialog . guidance . textContent = this . instructions . guidanceColumnRange ( lineNo , columnNo , maxColumnNo ) ;
5771 return dialog . input . classList . add ( 'code-input_go-to-line_error' ) ;
5872 } else {
73+ if ( columnNo === 0 ) {
74+ // No column specified, or 0 which for backwards compatibility acts
75+ // like none selected
76+ dialog . guidance . textContent = this . instructions . guidanceValidLine ( lineNo ) ;
77+ } else {
78+ dialog . guidance . textContent = this . instructions . guidanceValidColumn ( lineNo , columnNo ) ;
79+ }
5980 dialog . input . classList . remove ( 'code-input_go-to-line_error' ) ;
6081 }
6182 }
83+ } else {
84+ // No value
85+ dialog . guidance . textContent = "" ;
6286 }
6387
6488 if ( event . key == 'Enter' ) {
@@ -91,6 +115,7 @@ codeInput.plugins.GoToLine = class extends codeInput.Plugin {
91115 const textarea = codeInput . textareaElement ;
92116
93117 const dialog = document . createElement ( 'div' ) ;
118+
94119 const input = document . createElement ( 'input' ) ;
95120
96121 // TODO: Make a button element (semantic HTML for accessibility) in next major version
@@ -100,15 +125,21 @@ codeInput.plugins.GoToLine = class extends codeInput.Plugin {
100125 cancel . setAttribute ( "tabindex" , 0 ) ; // Visible to keyboard navigation
101126 cancel . setAttribute ( "title" , this . instructions . closeDialog ) ;
102127
128+ const guidance = document . createElement ( 'p' ) ;
129+ guidance . setAttribute ( "aria-live" , "assertive" ) ; // Screen reader must read the status message.
130+ guidance . textContent = "" ;
131+
103132 dialog . appendChild ( input ) ;
104133 dialog . appendChild ( cancel ) ;
134+ dialog . appendChild ( guidance ) ;
105135
106136 dialog . className = 'code-input_go-to-line_dialog' ;
107137 input . spellcheck = false ;
108138 input . placeholder = this . instructions . input ;
109139 dialog . codeInput = codeInput ;
110140 dialog . textarea = textarea ;
111141 dialog . input = input ;
142+ dialog . guidance = guidance ;
112143
113144 input . addEventListener ( 'keypress' , ( event ) => {
114145 /* Stop enter from submitting form */
0 commit comments