1- // ui.js - legend chip construction, refreshUI(), #doneCheck handler,
1+ // ui.js - legend chip construction, refreshUI(), #markAllBtn handler,
22// #resetBtn wiring.
33
44import { COLORS , TOTAL , CELL_COUNT , N } from './pattern.js' ;
@@ -30,19 +30,20 @@ COLORS.forEach((c,i)=>{
3030} ) ;
3131
3232/* ---------- complete toggle + progress ---------- */
33- const box = document . getElementById ( 'completeBox' ) ;
34- const check = document . getElementById ( 'doneCheck' ) ;
35- const clabel = document . getElementById ( 'completeLabel ' ) ;
36- check . addEventListener ( 'change ' , ( ) => {
33+ // toolbar "mark all" toggle: marks every cell of the selected colour as
34+ // stitched (or, when the colour is already complete, unmarks them all).
35+ const markAllBtn = document . getElementById ( 'markAllBtn ' ) ;
36+ markAllBtn . addEventListener ( 'click ' , ( ) => {
3737 if ( state . selected == null ) return ;
3838 const v = state . selected ;
39+ const on = ! isColourComplete ( v ) ;
3940 const cellsToToggle = [ ] ;
4041 for ( let i = 0 ; i < CELL_COUNT ; i ++ ) {
41- if ( colourAt ( i ) === v && isStitched ( i ) !== check . checked ) cellsToToggle . push ( i ) ;
42+ if ( colourAt ( i ) === v && isStitched ( i ) !== on ) cellsToToggle . push ( i ) ;
4243 }
43- cellsToToggle . forEach ( i => setStitched ( i , check . checked ) ) ;
44- logEvent ( { kind :'bulk' , c :v , cells :cellsToToggle , unmark : ! check . checked } ) ;
45- if ( check . checked && isColourComplete ( v ) ) celebrateBulk ( 'Colour finished!' ) ;
44+ cellsToToggle . forEach ( i => setStitched ( i , on ) ) ;
45+ logEvent ( { kind :'bulk' , c :v , cells :cellsToToggle , unmark : ! on } ) ;
46+ if ( on && isColourComplete ( v ) ) celebrateBulk ( 'Colour finished!' ) ;
4647 refreshUI ( ) ; draw ( ) ;
4748} ) ;
4849// cheap reuse of input.js's celebration banner for the bulk "mark all" path (4.6)
@@ -68,12 +69,22 @@ export function refreshUI(){
6869 } ) ;
6970 if ( state . selected != null ) {
7071 const c = COLORS [ state . selected - 1 ] ;
71- clabel . textContent = `Mark all of DMC ${ c [ 0 ] } · ${ c [ 1 ] } as stitched` ;
72- check . checked = isColourComplete ( state . selected ) ;
73- box . classList . add ( 'show' ) ;
72+ const complete = isColourComplete ( state . selected ) ;
73+ const lbl = complete
74+ ? `Unmark all of DMC ${ c [ 0 ] } · ${ c [ 1 ] } `
75+ : `Mark all of DMC ${ c [ 0 ] } · ${ c [ 1 ] } as stitched` ;
76+ markAllBtn . disabled = false ;
77+ markAllBtn . classList . toggle ( 'on' , complete ) ;
78+ markAllBtn . setAttribute ( 'aria-pressed' , String ( complete ) ) ;
79+ markAllBtn . setAttribute ( 'aria-label' , lbl ) ;
80+ markAllBtn . title = lbl ;
7481 document . getElementById ( 'chip' + state . selected )
7582 . scrollIntoView ( { behavior :'smooth' , inline :'center' , block :'nearest' } ) ;
76- } else box . classList . remove ( 'show' ) ;
83+ } else {
84+ markAllBtn . disabled = true ;
85+ markAllBtn . classList . remove ( 'on' ) ;
86+ markAllBtn . setAttribute ( 'aria-pressed' , 'false' ) ;
87+ }
7788 const doneCount = state . stitchedCount . reduce ( ( s , n ) => s + n , 0 ) ;
7889 const pct = Math . round ( doneCount / TOTAL * 100 ) ;
7990 document . getElementById ( 'pctNum' ) . textContent = pct ;
@@ -265,13 +276,25 @@ heatmapBtn.addEventListener('click', ()=>{
265276// fresh one (6.3). The remaining settings (railroading, topLegDirection,
266277// blockOrder) only affect drawing/labels or blockOrderList, so they just
267278// redraw + refresh.
279+ let prevBlockOrder = state . settings . blockOrder ;
268280const ROUTE_AFFECTING_KEYS = new Set ( [
269281 'maxCarry' , 'threadLength' , 'fabricCount' , 'strands' ,
270282 'origin' , 'darkCarryGuard' , 'confettiFirst' ,
271283] ) ;
272284
273285function applySettingChange ( key ) {
274286 markDirty ( ) ;
287+ if ( key === 'blockOrder' && state . selected != null ) {
288+ // keep the block currently in view, but re-index it into the new order so
289+ // prev/next walk the newly chosen sequence from here
290+ const oldList = blockOrderList ( state . selected , prevBlockOrder ) ;
291+ const cur = oldList [ blockIdx ] ;
292+ const newList = blockOrderList ( state . selected ) ;
293+ const ni = cur ? newList . findIndex ( b => b . br === cur . br && b . bc === cur . bc ) : - 1 ;
294+ blockIdx = ni >= 0 ? ni : 0 ;
295+ const b = newList [ blockIdx ] ; if ( b ) gotoBlock ( b . br , b . bc ) ;
296+ }
297+ prevBlockOrder = state . settings . blockOrder ;
275298 if ( ROUTE_AFFECTING_KEYS . has ( key ) ) {
276299 invalidateAllRoutes ( ) ;
277300 if ( state . selected != null ) requestRoute ( state . selected ) ;
@@ -297,6 +320,7 @@ const conservativeCarryBtn = document.getElementById('conservativeCarryBtn');
297320
298321function fillSettingsForm ( ) {
299322 const s = state . settings ;
323+ prevBlockOrder = s . blockOrder ; // settings may have been loaded from storage after module init
300324 setFabricCount . value = s . fabricCount ;
301325 setStrands . value = s . strands ;
302326 setMaxCarry . value = s . maxCarry ;
0 commit comments