PageSourceSearch

https://hammerschach-gamer.webmaster-5bb.workers.dev/js/move-history-navigation.js?v=20260917-theme-3

js hammerschach-gamer.webmaster-5bb.workers.dev collected 2026-10-03 08:09:08 UTC 6,895 bytes, 144 lines download raw bytes

1'use strict';
2
3function moveListPgnResultToken(){
4  if(!(onlineGameEnded || gameEnded || timeLost)) return '';
5  const finalGame = buildGameFromHistory(masterHistory.length);
6  const finalState = gameOverForHistory(masterHistory.length, finalGame);
7  const result = typeof pgnResultFromState === 'function' ? pgnResultFromState(finalState) : '';
8  return result === '1-0' || result === '0-1' || result === '1/2-1/2' ? result : '';
9}
10function renderMoveList(){
11  const theme = currentTheme();
12  const themePly = currentThemePly();
13  if(themeMoveNotice){
14    themeMoveNotice.hidden = !theme;
15    themeMoveNotice.textContent = theme ? ('🎯 Thementurnier: ' + theme.name + ' · ' + themePly + ' vorgegebene Halbzüge. Mit den Pfeilen lässt sich ihre Entstehung vollständig zurückverfolgen.') : '';
16  }
17  const resultToken = moveListPgnResultToken();
18  if(masterHistory.length === 0){
19    let empty = moveListEl.firstElementChild;
20    if(!empty){
21      empty = document.createElement('div');
22      moveListEl.appendChild(empty);
23    }
24    empty.className = resultToken ? 'move-cell move-result' : '';
25    empty.textContent = resultToken || '—';
26    empty.removeAttribute('data-move-index');
27    while(moveListEl.children.length > 1) moveListEl.lastElementChild.remove();
28    return;
29  }
30  const cells = [];
31  for(let i=0; i<masterHistory.length; i+=4){
32    const num1 = Math.floor(i/2) + 1;
33    const num2 = num1 + 1;
34    cells.push({txt:num1 + '.', idx:null}, {txt:masterHistory[i]?.san || '', idx:i}, {txt:masterHistory[i+1]?.san || '', idx:i+1});
35    cells.push({txt:masterHistory[i+2] || masterHistory[i+3] ? num2 + '.' : '', idx:null}, {txt:masterHistory[i+2]?.san || '', idx:i+2}, {txt:masterHistory[i+3]?.san || '', idx:i+3});
36  }
37  if(resultToken) cells.push({txt:resultToken, idx:null, result:true});
38  const navigationLocked = isMoveNavigationLocked();
39  cells.forEach((c, cellIndex) => {
40    let div = moveListEl.children[cellIndex];
41    if(!div){
42      div = document.createElement('div');
43      moveListEl.appendChild(div);
44    }
45    div.className = 'move-cell';
46    if(c.result) div.classList.add('move-result');
47    else if(cellIndex % 6 >= 3) div.classList.add('hide-mobile-pair');
48    div.textContent = c.txt;
49    div.removeAttribute('data-move-index');
50    div.title = '';
51    div.style.cursor = '';
52    if(c.idx !== null){
53      div.dataset.moveIndex = String(c.idx);
54      if(c.idx < themePly) div.classList.add('theme-move');
55      if(c.idx === themePly - 1) div.classList.add('theme-end');
56      if(viewIndex === c.idx + 1) div.classList.add('current');
57      if(navigationLocked){
58        div.title = 'Bitte die Daily-Zugvorschau zuerst bestätigen oder zurücknehmen.';
59        div.style.cursor = 'default';
60      } else {
61        div.title = 'Zu dieser Stellung springen';
62        div.style.cursor = 'pointer';
63      }
64    }
65  });
66  while(moveListEl.children.length > cells.length) moveListEl.lastElementChild.remove();
67}
68function updateBoardNavControls(){
69  if(!boardNavStartBtn || !boardNavBackBtn || !boardNavForwardBtn || !boardNavEndBtn) return;
70  let current = viewIndex;
71  let total = masterHistory.length;
72  let locked = isMoveNavigationLocked();
73  let labels = ['Anfang der Partie','Einen Halbzug zurück','Einen Halbzug vor','Letzte Stellung'];
74  if(variationModeActive){
75    current = variationHistory.length;
76    total = completeVariationLine().length;
77    locked = false;
78    labels = variationPurpose === 'conditional'
79      ? ['Ausgangsstellung der Bedingung','Einen vorbereiteten Zug zurück','Einen vorbereiteten Zug vor','Letzte vorbereitete Stellung']
80      : ['Ausgangsstellung der Variante','Einen Variantenzug zurück','Einen Variantenzug vor','Letzte Variantenstellung'];
81  }
82  const buttons = [boardNavStartBtn,boardNavBackBtn,boardNavForwardBtn,boardNavEndBtn];
83  buttons.forEach((button,index) => {
84    button.title = labels[index];
85    button.setAttribute('aria-label',labels[index]);
86  });
87  boardNavStartBtn.disabled = locked || total === 0 || current === 0;
88  boardNavBackBtn.disabled = locked || total === 0 || current === 0;
89  boardNavForwardBtn.disabled = locked || total === 0 || current === total;
90  boardNavEndBtn.disabled = locked || total === 0 || current === total;
91}
92function updateNavControls(){
93  const total = masterHistory.length;
94  const locked = isMoveNavigationLocked();
95  navStartBtn.disabled = locked || total === 0 || viewIndex === 0;
96  navBackBtn.disabled = locked || total === 0 || viewIndex === 0;
97  navForwardBtn.disabled = locked || total === 0 || viewIndex === total;
98  navEndBtn.disabled = locked || total === 0 || viewIndex === total;
99  movesInfoEl.textContent = total === 0 ? '0/0' : viewIndex + '/' + total;
100  updateBoardNavControls();
101}
102function canExportCurrentGamePgn(){
103  return masterHistory.length >
103 0 && !!(onlineGameEnded || gameEnded || timeLost);
104}
105function updatePgnExportUi(){
106  const button = document.getElementById('copyPgnBtn');
107  if(!button) return;
108  const available = canExportCurrentGamePgn();
109  button.hidden = !available;
110  button.disabled = !available;
111  button.title = available ? 'Beendete Partie als PGN-Datei herunterladen' : 'PGN steht erst nach Partieende bereit';
112}
113navStartBtn.addEventListener('click', () => { if(isMoveNavigationLocked()) return; viewIndex = 0; selected = null; renderBoard(); });
114navBackBtn.addEventListener('click', () => { if(isMoveNavigationLocked()) return; viewIndex = Math.max(0, viewIndex - 1); selected = null; renderBoard(); });
115navForwardBtn.addEventListener('click', () => { if(isMoveNavigationLocked()) return; viewIndex = Math.min(masterHistory.length, viewIndex + 1); selected = null; renderBoard(); });
116navEndBtn.addEventListener('click', () => { if(isMoveNavigationLocked()) return; viewIndex = masterHistory.length; selected = null; renderBoard(); });
117if(boardNavStartBtn) boardNavStartBtn.addEventListener('click', () => {
118  if(variationModeActive){ setVariationViewIndex(0); return; }
119  if(isMoveNavigationLocked()) return;
120  viewIndex = 0;
121  selected = null;
122  renderBoard();
123});
124if(boardNavBackBtn) boardNavBackBtn.addEventListener('click', () => {
125  if(variationModeActive){ setVariationViewIndex(variationHistory.length - 1); return; }
126  if(isMoveNavigationLocked()) return;
127  viewIndex = Math.max(0,viewIndex - 1);
128  selected = null;
129  renderBoard();
130});
131if(boardNavForwardBtn) boardNavForwardBtn.addEventListener('click', () => {
132  if(variationModeActive){ setVariationViewIndex(variationHistory.length + 1); return; }
133  if(isMoveNavigationLocked()) return;
134  viewIndex = Math.min(masterHistory.length,viewIndex + 1);
135  selected = null;
136  renderBoard();
137});
138if(boardNavEndBtn) boardNavEndBtn.addEventListener('click', () => {
139  if(variationModeActive){ setVariationViewIndex(completeVariationLine().length); return; }
140  if(isMoveNavigationLocked()) return;
141  viewIndex = masterHistory.length;
142  selected = null;
143  renderBoard();
144});

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.