1+ <!DOCTYPE html>
2+ < html >
3+
4+ < head >
5+ < title > </ title >
6+ < style >
7+ body {
8+ display : grid;
9+ grid-template-columns : auto auto;
10+ gap : 1px ;
11+ }
12+
13+ # grid-container {
14+ display : grid;
15+ grid-template-columns : repeat (29 , 32px );
16+ /* Adjust based on the size of each cell */
17+ grid-template-rows : repeat (29 , 32px );
18+ gap : 2px ;
19+ /* This creates a 1px space between grid items */
20+ justify-content : center;
21+ /* Center the grid horizontally */
22+ align-items : center;
23+ /* Center the grid vertically */
24+ width : fit-content;
25+ /* Adjust the width to fit the content */
26+ }
27+
28+ # grid-container div {
29+ width : 32px ;
30+ /* Width of each cell */
31+ height : 32px ;
32+ /* Height of each cell */
33+ position : relative;
34+ box-sizing : border-box;
35+ /* Include padding and border in the element's size */
36+ }
37+
38+ # grid-container div .selected {
39+ box-shadow : 0 0 0 5px red inset;
40+ /* Create an inner shadow that looks like a border */
41+ }
42+
43+ # grid-container p {
44+ margin : 0 ;
45+ position : absolute;
46+ top : 50% ;
47+ left : 50% ;
48+ transform : translate (-50% , -50% );
49+ font-size : 12px ;
50+ font-weight : bold;
51+ color : white;
52+ text-shadow :
53+ -1px -1px 0 # 000,
54+ 1px -1px 0 # 000,
55+ -1px 1px 0 # 000,
56+ 1px 1px 0 # 000 ;
57+ letter-spacing : 1px ;
58+ }
59+
60+ .inactive {
61+ opacity : 0.4 ;
62+ }
63+
64+ .active {
65+ /* margin: 4px; */
66+ /* outline: 4px green */
67+ }
68+
69+ .palette-item {
70+ display : inline-block;
71+ vertical-align : top;
72+ margin : 5px ;
73+ }
74+
75+ .palette-item p {
76+ display : inline-block;
77+ vertical-align : top;
78+ margin : 0 0 0 10px ;
79+ /* Add some space between the div and the text */
80+ font-size : 12px ;
81+ font-weight : bold;
82+ color : black;
83+ }
84+ </ style >
85+ </ head >
86+
87+ < body >
88+ < div id ="grid-container ">
89+ <!-- Grid will be generated here -->
90+ </ div >
91+ < div id ="palette-container "> </ div >
92+
93+ < script >
94+ function createPalette ( colorData ) {
95+ const container = document . getElementById ( 'palette-container' ) ;
96+
97+ const allColors = colorData . flat ( )
98+
99+ const allUniqueColors = [ ...new Set ( allColors . map ( pixel => pixel . color ) ) ] ;
100+ const allUniquePixels = allUniqueColors . map ( color => allColors . find ( pixel => pixel . color === color ) ) ;
101+
102+ allUniquePixels
103+ . sort ( ( a , b ) => a . number - b . number )
104+ . forEach ( ( { name, number, color } ) => {
105+ const colorContainer = document . createElement ( 'div' ) ;
106+ colorContainer . style . display = 'flex'
107+ const colorDiv = document . createElement ( 'div' ) ;
108+ colorDiv . style . backgroundColor = color ;
109+ colorDiv . style . width = '32px' ;
110+ colorDiv . style . height = '32px' ;
111+ colorDiv . style . border = '1px solid black' ;
112+ colorDiv . className = 'palette-item' ;
113+ const colorDivP = document . createElement ( 'p' ) ;
114+ colorDiv . append ( colorDivP ) ;
115+ colorDivP . textContent = number ;
116+
117+ const p = document . createElement ( 'p' ) ;
118+ p . textContent = `${ number } ${ name } ` ;
119+
120+ colorContainer . appendChild ( colorDiv ) ;
121+ colorContainer . appendChild ( p ) ;
122+ container . appendChild ( colorContainer ) ;
123+ } ) ;
124+ }
125+
126+ function createGrid ( colorData ) {
127+ const container = document . getElementById ( 'grid-container' ) ;
128+ container . innerHTML = '' ; // Clear existing grid
129+
130+ for ( let row = 0 ; row < 29 ; row ++ ) {
131+ for ( let col = 0 ; col < 29 ; col ++ ) {
132+ const div = document . createElement ( 'div' ) ;
133+
134+ const pixel = colorData [ row ] [ col ] ;
135+ div . style . backgroundColor = pixel . color ;
136+
137+ const p = document . createElement ( 'p' ) ;
138+ p . style . display = 'none' ;
139+ p . textContent = pixel ?. number ;
140+ div . appendChild ( p ) ;
141+ container . appendChild ( div ) ;
142+
143+ if ( row === 0 && col === 0 ) {
144+ div . classList . add ( 'selected' ) ;
145+ }
146+ }
147+ }
148+ }
149+
150+ // Function to move the selected class
151+ function moveSelected ( direction ) {
152+ const grid = document . getElementById ( 'grid-container' ) ;
153+ let current = grid . querySelector ( '.selected' ) ;
154+ let rowIndex = Math . floor ( Array . from ( grid . children ) . indexOf ( current ) / 29 ) ;
155+ let colIndex = Array . from ( grid . children ) . indexOf ( current ) % 29 ;
156+
157+ current . classList . remove ( 'selected' ) ;
158+
159+ if ( direction === 'ArrowUp' ) {
160+ if ( rowIndex > 0 ) {
161+ rowIndex -- ;
162+ } else {
163+ rowIndex = 28 ;
164+ }
165+ } else if ( direction === 'ArrowDown' ) {
166+ if ( rowIndex < 28 ) {
167+ rowIndex ++ ;
168+ } else {
169+ rowIndex = 0 ;
170+ }
171+ } else if ( direction === 'ArrowLeft' ) {
172+ if ( colIndex > 0 ) {
173+ colIndex -- ;
174+ } else {
175+ colIndex = 28 ;
176+ rowIndex = rowIndex > 0 ? rowIndex - 1 : 28 ;
177+ }
178+ } else if ( direction === 'ArrowRight' ) {
179+ if ( colIndex < 28 ) {
180+ colIndex ++ ;
181+ } else {
182+ colIndex = 0 ;
183+ rowIndex = rowIndex < 28 ? rowIndex + 1 : 0 ;
184+ }
185+ }
186+
187+ const newSelected = grid . children [ rowIndex * 29 + colIndex ] ;
188+ newSelected . classList . add ( 'selected' ) ;
189+
190+ // Get the innerHTML of the <p> element and set the document's title
191+ const pContent = newSelected . querySelector ( 'p' ) . innerHTML ;
192+ document . title = pContent ;
193+ }
194+
195+ // Function to read JSON file
196+ async function readJSON ( filename ) { }
197+
198+ let selectedPValue = '' ;
199+ function handleSpacebarPress ( ) {
200+ const grid = document . getElementById ( 'grid-container' ) ;
201+ const selectedDiv = grid . querySelector ( '.selected' ) ;
202+ const newSelectedPValue = selectedDiv . querySelector ( 'p' ) . innerHTML ;
203+ const selectedColor = selectedDiv . style . backgroundColor ;
204+
205+ // First make all divs active
206+ Array . from ( grid . children ) . forEach ( div => div . classList . remove ( 'inactive' , 'active' ) ) ;
207+
208+ if ( newSelectedPValue !== selectedPValue ) {
209+ // Add 'inactive' class to divs not matching the color
210+ Array . from ( grid . children ) . forEach ( div => {
211+ if ( div . style . backgroundColor !== selectedColor ) {
212+ div . classList . add ( 'inactive' ) ;
213+ } else {
214+ div . classList . add ( 'active' ) ;
215+
216+ }
217+ } ) ;
218+ selectedPValue = newSelectedPValue ;
219+ } else {
220+
221+ selectedPValue = '' ;
222+ }
223+ }
224+
225+ // Event listener for arrow keys
226+ document . addEventListener ( 'keydown' , function ( event ) {
227+ if ( [ 'ArrowUp' , 'ArrowDown' , 'ArrowLeft' , 'ArrowRight' ] . includes ( event . key ) ) {
228+ moveSelected ( event . key ) ;
229+ }
230+ } ) ;
231+
232+ document . addEventListener ( 'DOMContentLoaded' , async function ( ) {
233+ const queryString = window . location . search ;
234+ const urlParams = new URLSearchParams ( queryString ) ;
235+ const local = urlParams . get ( 'u' ) ;
236+ let url = local ;
237+ if ( ! local ) {
238+ const load = urlParams . get ( 't' ) ;
239+ url = `https://tinyurl.com/${ load . replaceAll ( "_" , "ZZ" ) } ` ;
240+ }
241+
242+ const imageData = await ( await fetch ( url ) ) . json ( ) ;
243+ createGrid ( imageData ) ;
244+ createPalette ( imageData ) ;
245+ } ) ;
246+
247+ document . addEventListener ( 'keydown' , function ( event ) {
248+ if ( event . key === ' ' ) {
249+ handleSpacebarPress ( ) ;
250+ }
251+ } ) ;
252+ </ script >
253+ </ body >
254+
255+ </ html >
0 commit comments