@@ -2,6 +2,21 @@ class TabbedTextControl {
22 constructor ( parentElement , theImportExportControls ) {
33 this . parent = parentElement ;
44 this . importExportController = theImportExportControls ;
5+ this . defaultTabId = 'csv' ;
6+ this . tabDefinitions = [
7+ { id : 'markdown' , label : 'Markdown' , type : 'markdown' } ,
8+ { id : 'csv' , label : 'CSV' , type : 'csv' } ,
9+ { id : 'dsv' , label : 'Delimited' , type : 'dsv' } ,
10+ { id : 'json' , label : 'JSON' , type : 'json' } ,
11+ {
12+ id : 'code' ,
13+ label : 'Code' ,
14+ subtasks : [ { id : 'javascript' , label : 'JavaScript' , type : 'javascript' } ] ,
15+ } ,
16+ { id : 'gherkin' , label : 'Gherkin' , type : 'gherkin' } ,
17+ { id : 'html' , label : 'HTML' , type : 'html' } ,
18+ { id : 'asciitable' , label : 'ASCII' , type : 'asciitable' } ,
19+ ] ;
520 }
621
722 // TODO : populate this from the registered importers and exporters rather than hard coding
@@ -10,37 +25,15 @@ class TabbedTextControl {
1025 <div class="conversionTabs">
1126 <div id="conversionTypes" class="conversionTypes">
1227 <ul class="conversionTypesList">
13- <li id="type-markdown" class="type-select">
14- <a class="type-select-action" data-type="markdown" href="#">Markdown</a>
15- </li>
16- <li id="type-csv" class="type-select active-type">
17- <a class="type-select-action" data-type="csv" href="#">CSV</a>
18- </li>
19- <li id="type-dsv" class="type-select">
20- <a class="type-select-action" data-type="dsv" href="#">Delimited</a>
21- </li>
22- <li id="type-json" class="type-select">
23- <a class="type-select-action" data-type="json" href="#">JSON</a>
24- </li>
25- <li id="type-javascript" class="type-select">
26- <a class="type-select-action" data-type="javascript" href="#">JavaScript</a>
27- </li>
28- <li id="type-gherkin" class="type-select">
29- <a class="type-select-action" data-type="gherkin" href="#">Gherkin</a>
30- </li>
31- <li id="type-html" class="type-select">
32- <a class="type-select-action" data-type="html" href="#">HTML</a>
33- </li>
34- <li id="type-asciitable" class="type-select">
35- <a class="type-select-action" data-type="asciitable" href="#">ASCII</a>
36- </li>
28+ ${ this . _renderMainTabMarkup ( ) }
3729 </ul>
3830 </div>
3931 <div class="rightbuttons">
4032 <button title="Toggle Preview/Edit mode" id="previewEditModeButton">Preview</button>
4133 <button title="Copy text to clipboard" id="copyTextButton">Copy</button>
4234 </div>
4335 </div>
36+ <div id="conversionSubtasks" class="conversionSubtasks" style="display: none"></div>
4437
4538 <div class="edit-area">
4639 <div class="options-parent" style="display: none"></div>
@@ -50,18 +43,10 @@ class TabbedTextControl {
5043 </div>
5144 ` ;
5245
53- this . parent . querySelectorAll ( '.type-select-action' ) . forEach ( ( lielem ) =>
54- lielem . addEventListener ( 'click' , ( e ) => {
55- // set the display buttons
56- this . parent . querySelectorAll ( '.type-select' ) . forEach ( ( elem ) => elem . classList . remove ( 'active-type' ) ) ;
57-
58- e . target . parentElement . classList . add ( 'active-type' ) ;
59-
60- // switched tab so re-render text
61- this . importExportController . renderTextFromGrid ( ) ;
62- this . importExportController . setFileFormatType ( ) ;
63- this . importExportController . setOptionsViewForFormatType ( ) ;
64- // don't try to navigate
46+ this . parent . querySelectorAll ( '.type-select-action' ) . forEach ( ( linkElem ) =>
47+ linkElem . addEventListener ( 'click' , ( e ) => {
48+ e . preventDefault ( ) ;
49+ this . _handleMainTabSelection ( e . currentTarget . dataset . tabId ) ;
6550 return false ;
6651 } )
6752 ) ;
@@ -80,9 +65,125 @@ class TabbedTextControl {
8065 } ) ;
8166 }
8267
68+ this . _handleMainTabSelection ( this . defaultTabId , { notifyController : false } ) ;
8369 this . _syncPreviewEditButtonLabel ( ) ;
8470 }
8571
72+ _renderMainTabMarkup ( ) {
73+ return this . tabDefinitions
74+ . map ( ( definition ) => {
75+ const typeAttributes = definition . type ? `data-type="${ definition . type } "` : `data-group="${ definition . id } "` ;
76+
77+ return `
78+ <li id="type-${ definition . id } " class="type-select" data-tab-id="${ definition . id } ">
79+ <a class="type-select-action" data-tab-id="${ definition . id } " ${ typeAttributes } href="#">${ definition . label } </a>
80+ </li>` ;
81+ } )
82+ . join ( '' ) ;
83+ }
84+
85+ _handleMainTabSelection ( tabId , { notifyController = true } = { } ) {
86+ const definition = this . _getTabDefinition ( tabId ) ;
87+ if ( ! definition ) {
88+ return false ;
89+ }
90+
91+ if ( ! definition . subtasks ) {
92+ this . _activateDirectType ( tabId , definition . type , { notifyController } ) ;
93+ return false ;
94+ }
95+
96+ this . _renderSubtasks ( definition ) ;
97+ this . _activateGroupedType ( tabId , definition . subtasks [ 0 ] . type , { notifyController } ) ;
98+ return false ;
99+ }
100+
101+ _renderSubtasks ( definition ) {
102+ const subtaskHost = this . parent . querySelector ( '#conversionSubtasks' ) ;
103+ if ( ! subtaskHost ) {
104+ return ;
105+ }
106+
107+ subtaskHost . innerHTML = `
108+ <ul class="conversionSubtasksList">
109+ ${ definition . subtasks
110+ . map (
111+ ( subtask ) => `
112+ <li class="subtask-select" data-type="${ subtask . type } ">
113+ <a class="subtask-select-action" data-type="${ subtask . type } " href="#">${ subtask . label } </a>
114+ </li>`
115+ )
116+ . join ( '' ) }
117+ </ul>` ;
118+ subtaskHost . style . display = 'block' ;
119+
120+ subtaskHost . querySelectorAll ( '.subtask-select-action' ) . forEach ( ( linkElem ) =>
121+ linkElem . addEventListener ( 'click' , ( e ) => {
122+ e . preventDefault ( ) ;
123+ this . _activateGroupedType ( definition . id , e . currentTarget . dataset . type , { notifyController : true } ) ;
124+ return false ;
125+ } )
126+ ) ;
127+
128+ subtaskHost . querySelectorAll ( 'li.subtask-select' ) . forEach ( ( listElem ) =>
129+ listElem . addEventListener ( 'click' , ( e ) => {
130+ e . target . querySelector ( 'a.subtask-select-action' ) ?. click ( ) ;
131+ } )
132+ ) ;
133+ }
134+
135+ _activateDirectType ( tabId , type , { notifyController = true } = { } ) {
136+ this . _clearActiveSelections ( ) ;
137+ this . parent . querySelector ( `#type-${ tabId } ` ) ?. classList . add ( 'active-type' ) ;
138+ this . _hideSubtasks ( ) ;
139+ if ( notifyController ) {
140+ this . _notifyTypeChanged ( ) ;
141+ }
142+ }
143+
144+ _activateGroupedType ( tabId , type , { notifyController = true } = { } ) {
145+ this . _clearActiveSelections ( ) ;
146+ this . parent . querySelector ( `#type-${ tabId } ` ) ?. classList . add ( 'active-main-type' ) ;
147+
148+ const subtaskHost = this . parent . querySelector ( '#conversionSubtasks' ) ;
149+ const activeSubtask = subtaskHost ?. querySelector ( `.subtask-select[data-type="${ type } "]` ) ;
150+ if ( activeSubtask ) {
151+ activeSubtask . classList . add ( 'active-type' ) ;
152+ }
153+
154+ if ( notifyController ) {
155+ this . _notifyTypeChanged ( ) ;
156+ }
157+ }
158+
159+ _clearActiveSelections ( ) {
160+ this . parent . querySelectorAll ( '.type-select' ) . forEach ( ( elem ) => {
161+ elem . classList . remove ( 'active-type' ) ;
162+ elem . classList . remove ( 'active-main-type' ) ;
163+ } ) ;
164+
165+ this . parent . querySelectorAll ( '.subtask-select' ) . forEach ( ( elem ) => elem . classList . remove ( 'active-type' ) ) ;
166+ }
167+
168+ _hideSubtasks ( ) {
169+ const subtaskHost = this . parent . querySelector ( '#conversionSubtasks' ) ;
170+ if ( ! subtaskHost ) {
171+ return ;
172+ }
173+ subtaskHost . innerHTML = '' ;
174+ subtaskHost . style . display = 'none' ;
175+ }
176+
177+ _notifyTypeChanged ( ) {
178+ this . importExportController . renderTextFromGrid ( ) ;
179+ this . importExportController . setFileFormatType ( ) ;
180+ this . importExportController . setOptionsViewForFormatType ( ) ;
181+ }
182+
183+ _getTabDefinition ( tabId ) {
184+ return this . tabDefinitions . find ( ( definition ) => definition . id === tabId ) ;
185+ }
186+
86187 _syncPreviewEditButtonLabel ( ) {
87188 const modeButton = this . parent . querySelector ( '#previewEditModeButton' ) ;
88189 if ( ! modeButton ) {
0 commit comments