@@ -7,18 +7,23 @@ document.addEventListener('DOMContentLoaded', () => {
77 const copyLatexBtn = document . getElementById ( 'copyLatexBtn' ) ;
88 const copyCSVBtn = document . getElementById ( 'copyCSVBtn' ) ;
99 const copyHTMLBtn = document . getElementById ( 'copyHTMLBtn' ) ;
10+ const copyKMapCSVBtn = document . getElementById ( 'copyKMapCSVBtn' ) ;
11+ const copyKMapHTMLBtn = document . getElementById ( 'copyKMapHTMLBtn' ) ;
1012 const errorMessage = document . getElementById ( 'errorMessage' ) ;
1113 const truthTableContainer = document . getElementById ( 'truthTableContainer' ) ;
14+ const kmapContainer = document . getElementById ( 'kmapContainer' ) ;
1215 const gatesSvg = document . getElementById ( 'gatesSvg' ) ;
1316 const cmosSvg = document . getElementById ( 'cmosSvg' ) ;
1417
1518 const tabBlockDiagram = document . getElementById ( 'tabBlockDiagram' ) ;
1619 const tabCMOS = document . getElementById ( 'tabCMOS' ) ;
1720 const tabTruthTable = document . getElementById ( 'tabTruthTable' ) ;
21+ const tabKMap = document . getElementById ( 'tabKMap' ) ;
1822
1923 const blockDiagramTab = document . getElementById ( 'blockDiagramTab' ) ;
2024 const cmosTab = document . getElementById ( 'cmosTab' ) ;
2125 const truthTableTab = document . getElementById ( 'truthTableTab' ) ;
26+ const kmapTab = document . getElementById ( 'kmapTab' ) ;
2227
2328 // Format help modal elements
2429 const formatHelpBtn = document . getElementById ( 'formatHelpBtn' ) ;
@@ -70,6 +75,7 @@ document.addEventListener('DOMContentLoaded', () => {
7075 currentVisualizer . renderCMOSDiagram ( cmosSvg ) ;
7176
7277 currentVisualizer . renderTruthTable ( truthTableContainer ) ;
78+ currentVisualizer . renderKMap ( kmapContainer ) ;
7379 } catch ( error ) {
7480 showError ( error . message ) ;
7581 }
@@ -97,6 +103,33 @@ document.addEventListener('DOMContentLoaded', () => {
97103 document . body . removeChild ( ta ) ;
98104 }
99105
106+ // Build Google-Docs-friendly HTML from a table element.
107+ function buildCopyableHTML ( tableEl ) {
108+ const clone = tableEl . cloneNode ( true ) ;
109+ clone . setAttribute ( 'border' , '1' ) ;
110+ clone . style . borderCollapse = 'collapse' ;
111+ clone . querySelectorAll ( 'th, td' ) . forEach ( cell => {
112+ cell . style . border = '1px solid #000' ;
113+ cell . style . padding = '4px 8px' ;
114+ cell . style . textAlign = 'center' ;
115+ } ) ;
116+ clone . querySelectorAll ( 'th' ) . forEach ( th => {
117+ th . style . backgroundColor = '#f5f5f5' ;
118+ th . style . fontWeight = 'bold' ;
119+ } ) ;
120+ return '<html><body><!--StartFragment-->' + clone . outerHTML + '<!--EndFragment--></body></html>' ;
121+ }
122+
123+ function getPlainText ( tableEl ) {
124+ const rows = [ ] ;
125+ tableEl . querySelectorAll ( 'tr' ) . forEach ( tr => {
126+ const cells = [ ] ;
127+ tr . querySelectorAll ( 'th, td' ) . forEach ( cell => cells . push ( cell . textContent ) ) ;
128+ rows . push ( cells . join ( '\t' ) ) ;
129+ } ) ;
130+ return rows . join ( '\n' ) ;
131+ }
132+
100133 // Copy as CSV (comma-separated)
101134 copyCSVBtn . addEventListener ( 'click' , ( ) => {
102135 if ( ! currentVisualizer ) return ;
@@ -109,18 +142,42 @@ document.addEventListener('DOMContentLoaded', () => {
109142 navigator . clipboard . writeText ( csv ) ;
110143 } ) ;
111144
112- // Copy rendered HTML table (preserves formatting when pasting into rich-text editors )
145+ // Copy rendered HTML table (preserves formatting in Google Docs, Word, etc. )
113146 copyHTMLBtn . addEventListener ( 'click' , ( ) => {
114147 const tableEl = truthTableContainer . querySelector ( 'table' ) ;
115148 if ( ! tableEl ) return ;
116- const htmlStr = tableEl . outerHTML ;
117- const plainRows = [ ] ;
149+ const htmlStr = buildCopyableHTML ( tableEl ) ;
150+ const plainText = getPlainText ( tableEl ) ;
151+ const blob = new Blob ( [ htmlStr ] , { type : 'text/html' } ) ;
152+ const textBlob = new Blob ( [ plainText ] , { type : 'text/plain' } ) ;
153+ navigator . clipboard . write ( [
154+ new ClipboardItem ( {
155+ 'text/html' : blob ,
156+ 'text/plain' : textBlob
157+ } )
158+ ] ) ;
159+ } ) ;
160+
161+ // Copy K-map as CSV
162+ copyKMapCSVBtn . addEventListener ( 'click' , ( ) => {
163+ const tableEl = kmapContainer . querySelector ( 'table' ) ;
164+ if ( ! tableEl ) return ;
165+ const rows = [ ] ;
118166 tableEl . querySelectorAll ( 'tr' ) . forEach ( tr => {
119167 const cells = [ ] ;
120168 tr . querySelectorAll ( 'th, td' ) . forEach ( cell => cells . push ( cell . textContent ) ) ;
121- plainRows . push ( cells . join ( '\t ' ) ) ;
169+ rows . push ( cells . join ( ', ' ) ) ;
122170 } ) ;
123- const plainText = plainRows . join ( '\n' ) ;
171+ const csv = rows . join ( '\n' ) ;
172+ navigator . clipboard . writeText ( csv ) ;
173+ } ) ;
174+
175+ // Copy K-map as HTML table
176+ copyKMapHTMLBtn . addEventListener ( 'click' , ( ) => {
177+ const tableEl = kmapContainer . querySelector ( 'table' ) ;
178+ if ( ! tableEl ) return ;
179+ const htmlStr = buildCopyableHTML ( tableEl ) ;
180+ const plainText = getPlainText ( tableEl ) ;
124181 const blob = new Blob ( [ htmlStr ] , { type : 'text/html' } ) ;
125182 const textBlob = new Blob ( [ plainText ] , { type : 'text/plain' } ) ;
126183 navigator . clipboard . write ( [
@@ -132,8 +189,8 @@ document.addEventListener('DOMContentLoaded', () => {
132189 } ) ;
133190
134191 // Tab switching
135- const tabs = { block : tabBlockDiagram , cmos : tabCMOS , truth : tabTruthTable } ;
136- const contents = { block : blockDiagramTab , cmos : cmosTab , truth : truthTableTab } ;
192+ const tabs = { block : tabBlockDiagram , cmos : tabCMOS , truth : tabTruthTable , kmap : tabKMap } ;
193+ const contents = { block : blockDiagramTab , cmos : cmosTab , truth : truthTableTab , kmap : kmapTab } ;
137194
138195 Object . keys ( tabs ) . forEach ( key => {
139196 tabs [ key ] . addEventListener ( 'click' , ( ) => {
0 commit comments