@alepot55/chessboardjs 2.3.6 → 2.3.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/chessboard.cjs.js +408 -744
- package/dist/chessboard.esm.js +408 -744
- package/dist/chessboard.iife.js +408 -744
- package/dist/chessboard.umd.js +408 -744
- package/package.json +1 -1
- package/src/components/Piece.js +13 -1
- package/src/core/Chessboard.js +323 -660
- package/src/core/ChessboardConfig.js +33 -18
- package/src/core/ChessboardFactory.js +5 -0
- package/src/core/index.js +15 -34
- package/src/errors/messages.js +1 -0
- package/src/index.js +13 -13
- package/src/services/ValidationService.js +14 -1
- package/src/utils/validation.js +5 -1
package/dist/chessboard.cjs.js
CHANGED
|
@@ -128,6 +128,7 @@ const ERROR_MESSAGES = Object.freeze({
|
|
|
128
128
|
invalid_fadeTime: 'Invalid fadeTime: ',
|
|
129
129
|
invalid_fadeAnimation: 'Invalid fadeAnimation: ',
|
|
130
130
|
invalid_ratio: 'Invalid ratio: ',
|
|
131
|
+
invalid_animationStyle: 'Invalid animationStyle: ',
|
|
131
132
|
animation_failed: 'Animation failed: ',
|
|
132
133
|
|
|
133
134
|
// Event handlers
|
|
@@ -379,6 +380,7 @@ const VALID_VALUES = Object.freeze({
|
|
|
379
380
|
movableColors: ['w', 'b', 'white', 'black', 'both', 'none'],
|
|
380
381
|
dropOffBoard: ['snapback', 'trash'],
|
|
381
382
|
easingTypes: ['linear', 'ease', 'ease-in', 'ease-out', 'ease-in-out'],
|
|
383
|
+
animationStyles: ['sequential', 'simultaneous'],
|
|
382
384
|
modes: ['normal', 'creative', 'analysis'],
|
|
383
385
|
promotionPieces: ['q', 'r', 'b', 'n', 'Q', 'R', 'B', 'N']
|
|
384
386
|
});
|
|
@@ -707,6 +709,14 @@ class ValidationService {
|
|
|
707
709
|
return this._validValues.easingTypes.includes(easing);
|
|
708
710
|
}
|
|
709
711
|
|
|
712
|
+
/**
|
|
713
|
+
* Validates animation style
|
|
714
|
+
* @param {string} style - Animation style to validate
|
|
715
|
+
* @returns {boolean} True if valid
|
|
716
|
+
*/
|
|
717
|
+
isValidAnimationStyle(style) {
|
|
718
|
+
return this._validValues.animationStyles.includes(style);
|
|
719
|
+
}
|
|
710
720
|
|
|
711
721
|
/**
|
|
712
722
|
* Validates CSS color format
|
|
@@ -903,7 +913,11 @@ class ValidationService {
|
|
|
903
913
|
if (config.dropOffBoard && !this.isValidDropOffBoard(config.dropOffBoard)) {
|
|
904
914
|
errors.push(ERROR_MESSAGES.invalid_dropOffBoard + config.dropOffBoard);
|
|
905
915
|
}
|
|
906
|
-
|
|
916
|
+
|
|
917
|
+
if (config.animationStyle && !this.isValidAnimationStyle(config.animationStyle)) {
|
|
918
|
+
errors.push(ERROR_MESSAGES.invalid_animationStyle + config.animationStyle);
|
|
919
|
+
}
|
|
920
|
+
|
|
907
921
|
// Validate callbacks
|
|
908
922
|
const callbacks = ['onMove', 'onMoveEnd', 'onChange', 'onDragStart', 'onDragMove', 'onDrop', 'onSnapbackEnd'];
|
|
909
923
|
for (const callback of callbacks) {
|
|
@@ -1081,7 +1095,8 @@ const DEFAULT_CONFIG$1 = Object.freeze({
|
|
|
1081
1095
|
fadeAnimation: 'ease',
|
|
1082
1096
|
ratio: 0.9,
|
|
1083
1097
|
piecesPath: '../assets/themes/default',
|
|
1084
|
-
|
|
1098
|
+
animationStyle: 'simultaneous',
|
|
1099
|
+
simultaneousAnimationDelay: 0,
|
|
1085
1100
|
onMove: () => true,
|
|
1086
1101
|
onMoveEnd: () => true,
|
|
1087
1102
|
onChange: () => true,
|
|
@@ -1115,19 +1130,19 @@ class ChessboardConfig {
|
|
|
1115
1130
|
constructor(settings = {}) {
|
|
1116
1131
|
// Initialize validation service
|
|
1117
1132
|
this._validationService = new ValidationService();
|
|
1118
|
-
|
|
1133
|
+
|
|
1119
1134
|
// Validate input
|
|
1120
1135
|
this._validateInput(settings);
|
|
1121
|
-
|
|
1136
|
+
|
|
1122
1137
|
// Merge with defaults
|
|
1123
1138
|
const config = this._mergeWithDefaults(settings);
|
|
1124
|
-
|
|
1139
|
+
|
|
1125
1140
|
// Process and validate configuration
|
|
1126
1141
|
this._processConfiguration(config);
|
|
1127
|
-
|
|
1142
|
+
|
|
1128
1143
|
// Set CSS properties
|
|
1129
1144
|
this._setCSSProperties(config);
|
|
1130
|
-
|
|
1145
|
+
|
|
1131
1146
|
// Configure mode-specific settings
|
|
1132
1147
|
this._configureModeSettings();
|
|
1133
1148
|
}
|
|
@@ -1142,7 +1157,7 @@ class ChessboardConfig {
|
|
|
1142
1157
|
if (settings !== null && typeof settings !== 'object') {
|
|
1143
1158
|
throw new ConfigurationError('Settings must be an object', 'settings', settings);
|
|
1144
1159
|
}
|
|
1145
|
-
|
|
1160
|
+
|
|
1146
1161
|
// Validate using validation service
|
|
1147
1162
|
try {
|
|
1148
1163
|
this._validationService.validateConfig(settings);
|
|
@@ -1176,7 +1191,7 @@ class ChessboardConfig {
|
|
|
1176
1191
|
this.size = config.size;
|
|
1177
1192
|
this.movableColors = config.movableColors;
|
|
1178
1193
|
this.piecesPath = config.piecesPath;
|
|
1179
|
-
|
|
1194
|
+
|
|
1180
1195
|
// Event handlers
|
|
1181
1196
|
this.onMove = this._validateCallback(config.onMove);
|
|
1182
1197
|
this.onMoveEnd = this._validateCallback(config.onMoveEnd);
|
|
@@ -1204,8 +1219,9 @@ class ChessboardConfig {
|
|
|
1204
1219
|
this.snapbackTime = this._setTime(config.snapbackTime);
|
|
1205
1220
|
this.dropCenterTime = this._setTime(config.dropCenterTime);
|
|
1206
1221
|
this.fadeTime = this._setTime(config.fadeTime);
|
|
1207
|
-
|
|
1222
|
+
|
|
1208
1223
|
// Animation style properties
|
|
1224
|
+
this.animationStyle = this._validateAnimationStyle(config.animationStyle);
|
|
1209
1225
|
this.simultaneousAnimationDelay = this._validateDelay(config.simultaneousAnimationDelay);
|
|
1210
1226
|
}
|
|
1211
1227
|
|
|
@@ -1266,6 +1282,19 @@ class ChessboardConfig {
|
|
|
1266
1282
|
return callback;
|
|
1267
1283
|
}
|
|
1268
1284
|
|
|
1285
|
+
/**
|
|
1286
|
+
* Validates animation style
|
|
1287
|
+
* @private
|
|
1288
|
+
* @param {string} style - Animation style
|
|
1289
|
+
* @returns {string} Validated style
|
|
1290
|
+
* @throws {ConfigurationError} If style is invalid
|
|
1291
|
+
*/
|
|
1292
|
+
_validateAnimationStyle(style) {
|
|
1293
|
+
if (!this._validationService.isValidAnimationStyle(style)) {
|
|
1294
|
+
throw new ConfigurationError('Invalid animation style', 'animationStyle', style);
|
|
1295
|
+
}
|
|
1296
|
+
return style;
|
|
1297
|
+
}
|
|
1269
1298
|
|
|
1270
1299
|
/**
|
|
1271
1300
|
* Validates animation delay
|
|
@@ -1323,11 +1352,11 @@ class ChessboardConfig {
|
|
|
1323
1352
|
}
|
|
1324
1353
|
return value;
|
|
1325
1354
|
}
|
|
1326
|
-
|
|
1355
|
+
|
|
1327
1356
|
if (typeof value === 'string' && value in ANIMATION_TIMES) {
|
|
1328
1357
|
return ANIMATION_TIMES[value];
|
|
1329
1358
|
}
|
|
1330
|
-
|
|
1359
|
+
|
|
1331
1360
|
throw new ConfigurationError('Invalid time value', 'time', value);
|
|
1332
1361
|
}
|
|
1333
1362
|
|
|
@@ -1342,11 +1371,11 @@ class ChessboardConfig {
|
|
|
1342
1371
|
if (typeof value === 'boolean') {
|
|
1343
1372
|
return value;
|
|
1344
1373
|
}
|
|
1345
|
-
|
|
1374
|
+
|
|
1346
1375
|
if (value in BOOLEAN_VALUES) {
|
|
1347
1376
|
return BOOLEAN_VALUES[value];
|
|
1348
1377
|
}
|
|
1349
|
-
|
|
1378
|
+
|
|
1350
1379
|
throw new ConfigurationError('Invalid boolean value', 'boolean', value);
|
|
1351
1380
|
}
|
|
1352
1381
|
|
|
@@ -1362,17 +1391,17 @@ class ChessboardConfig {
|
|
|
1362
1391
|
if (typeof value === 'boolean') {
|
|
1363
1392
|
return value ? TRANSITION_FUNCTIONS.ease : null;
|
|
1364
1393
|
}
|
|
1365
|
-
|
|
1394
|
+
|
|
1366
1395
|
// Handle string values
|
|
1367
1396
|
if (typeof value === 'string' && value in TRANSITION_FUNCTIONS) {
|
|
1368
1397
|
return TRANSITION_FUNCTIONS[value];
|
|
1369
1398
|
}
|
|
1370
|
-
|
|
1399
|
+
|
|
1371
1400
|
// Handle null/undefined
|
|
1372
1401
|
if (value === null || value === undefined) {
|
|
1373
1402
|
return null;
|
|
1374
1403
|
}
|
|
1375
|
-
|
|
1404
|
+
|
|
1376
1405
|
throw new ConfigurationError('Invalid transition function', 'transitionFunction', value);
|
|
1377
1406
|
}
|
|
1378
1407
|
|
|
@@ -1403,6 +1432,7 @@ class ChessboardConfig {
|
|
|
1403
1432
|
fadeTime: this.fadeTime,
|
|
1404
1433
|
fadeAnimation: this.fadeAnimation,
|
|
1405
1434
|
piecesPath: this.piecesPath,
|
|
1435
|
+
animationStyle: this.animationStyle,
|
|
1406
1436
|
simultaneousAnimationDelay: this.simultaneousAnimationDelay,
|
|
1407
1437
|
onlyLegalMoves: this.onlyLegalMoves
|
|
1408
1438
|
};
|
|
@@ -1424,7 +1454,7 @@ class ChessboardConfig {
|
|
|
1424
1454
|
|
|
1425
1455
|
// Apply updates
|
|
1426
1456
|
const newConfig = Object.assign({}, this.toObject(), updates);
|
|
1427
|
-
|
|
1457
|
+
|
|
1428
1458
|
// Re-process configuration
|
|
1429
1459
|
this._processConfiguration(newConfig);
|
|
1430
1460
|
this._setCSSProperties(newConfig);
|
|
@@ -1647,10 +1677,22 @@ class Piece {
|
|
|
1647
1677
|
|
|
1648
1678
|
setDrag(f) {
|
|
1649
1679
|
if (!this.element) { console.debug(`[Piece] setDrag: ${this.id} - element is null`); return; }
|
|
1680
|
+
// Remove previous handlers
|
|
1681
|
+
this.element.onmousedown = null;
|
|
1682
|
+
this.element.ontouchstart = null;
|
|
1683
|
+
this.element.ondragstart = null;
|
|
1684
|
+
if (window.PointerEvent) {
|
|
1685
|
+
this.element.onpointerdown = null;
|
|
1686
|
+
}
|
|
1687
|
+
// Set new handlers
|
|
1650
1688
|
this.element.ondragstart = (e) => { e.preventDefault(); };
|
|
1651
1689
|
this.element.onmousedown = f;
|
|
1652
1690
|
this.element.ontouchstart = f; // Drag touch
|
|
1653
|
-
|
|
1691
|
+
if (window.PointerEvent) {
|
|
1692
|
+
this.element.onpointerdown = f;
|
|
1693
|
+
console.debug(`[Piece] setDrag: pointerdown set for ${this.id}`);
|
|
1694
|
+
}
|
|
1695
|
+
console.debug(`[Piece] setDrag: mousedown/ontouchstart set for ${this.id}`);
|
|
1654
1696
|
}
|
|
1655
1697
|
|
|
1656
1698
|
destroy() {
|
|
@@ -7073,7 +7115,7 @@ class PositionService {
|
|
|
7073
7115
|
* Implements the Facade pattern to provide a unified interface
|
|
7074
7116
|
* @class
|
|
7075
7117
|
*/
|
|
7076
|
-
|
|
7118
|
+
class Chessboard {
|
|
7077
7119
|
/**
|
|
7078
7120
|
* Creates a new Chessboard instance
|
|
7079
7121
|
* @param {Object} config - Configuration object
|
|
@@ -7098,8 +7140,6 @@ let Chessboard$1 = class Chessboard {
|
|
|
7098
7140
|
} catch (error) {
|
|
7099
7141
|
this._handleConstructorError(error);
|
|
7100
7142
|
}
|
|
7101
|
-
this._undoneMoves = [];
|
|
7102
|
-
this._updateBoardPieces(true, true); // Forza popolamento DOM subito
|
|
7103
7143
|
}
|
|
7104
7144
|
|
|
7105
7145
|
/**
|
|
@@ -7143,31 +7183,6 @@ let Chessboard$1 = class Chessboard {
|
|
|
7143
7183
|
}
|
|
7144
7184
|
}
|
|
7145
7185
|
|
|
7146
|
-
/**
|
|
7147
|
-
* Cleans up any partially initialized resources (safe to call multiple times)
|
|
7148
|
-
* @private
|
|
7149
|
-
*/
|
|
7150
|
-
_cleanup() {
|
|
7151
|
-
// Remove event listeners if present
|
|
7152
|
-
if (this.eventService && typeof this.eventService.removeListeners === 'function') {
|
|
7153
|
-
this.eventService.removeListeners();
|
|
7154
|
-
}
|
|
7155
|
-
// Clear timeouts
|
|
7156
|
-
if (this._updateTimeout) {
|
|
7157
|
-
clearTimeout(this._updateTimeout);
|
|
7158
|
-
this._updateTimeout = null;
|
|
7159
|
-
}
|
|
7160
|
-
// Null all services
|
|
7161
|
-
this.validationService = null;
|
|
7162
|
-
this.coordinateService = null;
|
|
7163
|
-
this.positionService = null;
|
|
7164
|
-
this.boardService = null;
|
|
7165
|
-
this.pieceService = null;
|
|
7166
|
-
this.animationService = null;
|
|
7167
|
-
this.moveService = null;
|
|
7168
|
-
this.eventService = null;
|
|
7169
|
-
}
|
|
7170
|
-
|
|
7171
7186
|
/**
|
|
7172
7187
|
* Initializes all services
|
|
7173
7188
|
* @private
|
|
@@ -7236,23 +7251,8 @@ let Chessboard$1 = class Chessboard {
|
|
|
7236
7251
|
/**
|
|
7237
7252
|
* Builds the board DOM structure
|
|
7238
7253
|
* @private
|
|
7239
|
-
* Best practice: always remove squares (destroy JS/DOM) before clearing the board container.
|
|
7240
7254
|
*/
|
|
7241
7255
|
_buildBoard() {
|
|
7242
|
-
console.log('CHIAMATO: _buildBoard');
|
|
7243
|
-
if (this._isUndoRedo) {
|
|
7244
|
-
console.log('SKIP _buildBoard per undo/redo');
|
|
7245
|
-
return;
|
|
7246
|
-
}
|
|
7247
|
-
// Forza la pulizia completa del contenitore board (DOM)
|
|
7248
|
-
const boardContainer = document.getElementById(this.config.id_div);
|
|
7249
|
-
if (boardContainer) boardContainer.innerHTML = '';
|
|
7250
|
-
// Force remove all pieces from all squares (no animation, best practice)
|
|
7251
|
-
if (this.boardService && this.boardService.squares) {
|
|
7252
|
-
Object.values(this.boardService.squares).forEach(sq => sq && sq.forceRemoveAllPieces && sq.forceRemoveAllPieces());
|
|
7253
|
-
}
|
|
7254
|
-
if (this.boardService && this.boardService.removeSquares) this.boardService.removeSquares();
|
|
7255
|
-
if (this.boardService && this.boardService.removeBoard) this.boardService.removeBoard();
|
|
7256
7256
|
this.boardService.buildBoard();
|
|
7257
7257
|
}
|
|
7258
7258
|
|
|
@@ -7261,14 +7261,6 @@ let Chessboard$1 = class Chessboard {
|
|
|
7261
7261
|
* @private
|
|
7262
7262
|
*/
|
|
7263
7263
|
_buildSquares() {
|
|
7264
|
-
console.log('CHIAMATO: _buildSquares');
|
|
7265
|
-
if (this._isUndoRedo) {
|
|
7266
|
-
console.log('SKIP _buildSquares per undo/redo');
|
|
7267
|
-
return;
|
|
7268
|
-
}
|
|
7269
|
-
if (this.boardService && this.boardService.removeSquares) {
|
|
7270
|
-
this.boardService.removeSquares();
|
|
7271
|
-
}
|
|
7272
7264
|
this.boardService.buildSquares((row, col) => {
|
|
7273
7265
|
return this.coordinateService.realCoord(row, col);
|
|
7274
7266
|
});
|
|
@@ -7473,7 +7465,7 @@ let Chessboard$1 = class Chessboard {
|
|
|
7473
7465
|
const capturedPiece = move.to.piece;
|
|
7474
7466
|
|
|
7475
7467
|
// For castle moves in simultaneous mode, we need to coordinate both animations
|
|
7476
|
-
if (isCastleMove) {
|
|
7468
|
+
if (isCastleMove && this.config.animationStyle === 'simultaneous') {
|
|
7477
7469
|
// Start king animation
|
|
7478
7470
|
this.pieceService.translatePiece(
|
|
7479
7471
|
move,
|
|
@@ -7638,7 +7630,6 @@ let Chessboard$1 = class Chessboard {
|
|
|
7638
7630
|
* @param {boolean} [isPositionLoad=false] - Whether this is a position load
|
|
7639
7631
|
*/
|
|
7640
7632
|
_updateBoardPieces(animation = false, isPositionLoad = false) {
|
|
7641
|
-
console.log('CHIAMATO: _updateBoardPieces', { animation, isPositionLoad, isUndoRedo: this._isUndoRedo });
|
|
7642
7633
|
// Check if services are available
|
|
7643
7634
|
if (!this.positionService || !this.moveService || !this.eventService) {
|
|
7644
7635
|
console.log('Cannot update board pieces - services not available');
|
|
@@ -7698,125 +7689,112 @@ let Chessboard$1 = class Chessboard {
|
|
|
7698
7689
|
}
|
|
7699
7690
|
|
|
7700
7691
|
/**
|
|
7701
|
-
*
|
|
7692
|
+
* Performs the actual board update
|
|
7702
7693
|
* @private
|
|
7703
|
-
* @param {boolean} [animation=false] -
|
|
7704
|
-
* @param {boolean} [isPositionLoad=false] -
|
|
7694
|
+
* @param {boolean} [animation=false] - Whether to animate
|
|
7695
|
+
* @param {boolean} [isPositionLoad=false] - Whether this is a position load (affects delay)
|
|
7705
7696
|
*/
|
|
7706
7697
|
_doUpdateBoardPieces(animation = false, isPositionLoad = false) {
|
|
7707
|
-
if
|
|
7708
|
-
if (this._isPromoting)
|
|
7709
|
-
|
|
7698
|
+
// Skip update if we're in the middle of a promotion
|
|
7699
|
+
if (this._isPromoting) {
|
|
7700
|
+
console.log('Skipping board update during promotion');
|
|
7701
|
+
return;
|
|
7702
|
+
}
|
|
7703
|
+
|
|
7704
|
+
// Check if services are available
|
|
7705
|
+
if (!this.positionService || !this.positionService.getGame()) {
|
|
7706
|
+
console.log('Cannot update board pieces - position service not available');
|
|
7707
|
+
return;
|
|
7708
|
+
}
|
|
7709
|
+
|
|
7710
7710
|
const squares = this.boardService.getAllSquares();
|
|
7711
7711
|
const gameStateBefore = this.positionService.getGame().fen();
|
|
7712
|
-
|
|
7713
|
-
|
|
7714
|
-
|
|
7715
|
-
|
|
7716
|
-
|
|
7717
|
-
|
|
7718
|
-
|
|
7719
|
-
|
|
7720
|
-
|
|
7721
|
-
|
|
7722
|
-
|
|
7712
|
+
|
|
7713
|
+
console.log('_doUpdateBoardPieces - current FEN:', gameStateBefore);
|
|
7714
|
+
console.log('_doUpdateBoardPieces - animation:', animation, 'style:', this.config.animationStyle, 'isPositionLoad:', isPositionLoad);
|
|
7715
|
+
|
|
7716
|
+
// Determine which animation style to use
|
|
7717
|
+
const useSimultaneous = this.config.animationStyle === 'simultaneous';
|
|
7718
|
+
console.log('_doUpdateBoardPieces - useSimultaneous:', useSimultaneous);
|
|
7719
|
+
|
|
7720
|
+
if (useSimultaneous) {
|
|
7721
|
+
console.log('Using simultaneous animation');
|
|
7722
|
+
this._doSimultaneousUpdate(squares, gameStateBefore, isPositionLoad);
|
|
7723
|
+
} else {
|
|
7724
|
+
console.log('Using sequential animation');
|
|
7725
|
+
this._doSequentialUpdate(squares, gameStateBefore, animation);
|
|
7723
7726
|
}
|
|
7727
|
+
}
|
|
7724
7728
|
|
|
7725
|
-
|
|
7726
|
-
|
|
7727
|
-
|
|
7729
|
+
/**
|
|
7730
|
+
* Performs sequential piece updates (original behavior)
|
|
7731
|
+
* @private
|
|
7732
|
+
* @param {Object} squares - All squares
|
|
7733
|
+
* @param {string} gameStateBefore - Game state before update
|
|
7734
|
+
* @param {boolean} animation - Whether to animate
|
|
7735
|
+
*/
|
|
7736
|
+
_doSequentialUpdate(squares, gameStateBefore, animation) {
|
|
7737
|
+
// Update each square sequentially
|
|
7728
7738
|
Object.values(squares).forEach(square => {
|
|
7729
|
-
const currentPiece = square.piece;
|
|
7730
7739
|
const expectedPieceId = this.positionService.getGamePieceId(square.id);
|
|
7731
|
-
|
|
7732
|
-
|
|
7733
|
-
if (!currentMap[key]) currentMap[key] = [];
|
|
7734
|
-
currentMap[key].push({ square, id: square.id, piece: currentPiece });
|
|
7735
|
-
}
|
|
7736
|
-
if (expectedPieceId) {
|
|
7737
|
-
const key = expectedPieceId.toLowerCase();
|
|
7738
|
-
if (!expectedMap[key]) expectedMap[key] = [];
|
|
7739
|
-
expectedMap[key].push({ square, id: square.id });
|
|
7740
|
-
}
|
|
7741
|
-
});
|
|
7742
|
-
const animationDelay = isPositionLoad ? 0 : this.config.simultaneousAnimationDelay || 0;
|
|
7743
|
-
let totalAnimations = 0;
|
|
7744
|
-
let animationsCompleted = 0;
|
|
7740
|
+
const currentPiece = square.piece;
|
|
7741
|
+
const currentPieceId = currentPiece ? currentPiece.getId() : null;
|
|
7745
7742
|
|
|
7746
|
-
|
|
7747
|
-
|
|
7748
|
-
|
|
7749
|
-
|
|
7750
|
-
|
|
7751
|
-
|
|
7752
|
-
|
|
7753
|
-
|
|
7754
|
-
|
|
7755
|
-
|
|
7756
|
-
|
|
7757
|
-
|
|
7758
|
-
|
|
7759
|
-
|
|
7760
|
-
|
|
7761
|
-
|
|
7762
|
-
|
|
7763
|
-
|
|
7764
|
-
|
|
7765
|
-
|
|
7766
|
-
|
|
7767
|
-
|
|
7768
|
-
if (localFromMatched[i]) continue;
|
|
7769
|
-
for (let j = 0; j < toList.length; j++) {
|
|
7770
|
-
if (localToMatched[j]) continue;
|
|
7771
|
-
if (distances[i][j] < minDist) {
|
|
7772
|
-
minDist = distances[i][j];
|
|
7773
|
-
minI = i;
|
|
7774
|
-
minJ = j;
|
|
7775
|
-
}
|
|
7743
|
+
// Log only for squares that are changing
|
|
7744
|
+
if (currentPieceId !== expectedPieceId) {
|
|
7745
|
+
console.log(`_doSequentialUpdate - ${square.id}: ${currentPieceId} -> ${expectedPieceId}`);
|
|
7746
|
+
|
|
7747
|
+
// Check if we already have the correct piece (from promotion)
|
|
7748
|
+
if (currentPiece && currentPiece.getId() === expectedPieceId) {
|
|
7749
|
+
console.log(`Piece ${expectedPieceId} already correctly placed on ${square.id}`);
|
|
7750
|
+
} else {
|
|
7751
|
+
// Remove current piece if exists
|
|
7752
|
+
if (currentPiece) {
|
|
7753
|
+
this.pieceService.removePieceFromSquare(square, animation);
|
|
7754
|
+
}
|
|
7755
|
+
|
|
7756
|
+
// Add new piece if needed
|
|
7757
|
+
if (expectedPieceId) {
|
|
7758
|
+
const newPiece = this.pieceService.convertPiece(expectedPieceId);
|
|
7759
|
+
this.pieceService.addPieceOnSquare(
|
|
7760
|
+
square,
|
|
7761
|
+
newPiece,
|
|
7762
|
+
animation,
|
|
7763
|
+
this._createDragFunction.bind(this)
|
|
7764
|
+
);
|
|
7776
7765
|
}
|
|
7777
7766
|
}
|
|
7778
|
-
if (minI === -1 || minJ === -1) break;
|
|
7779
|
-
// Se la posizione è la stessa E il Piece è lo stesso oggetto, non fare nulla (pezzo unchanged)
|
|
7780
|
-
if (fromList[minI].square === toList[minJ].square && squares[toList[minJ].square.id].piece === fromList[minI].piece) {
|
|
7781
|
-
unchanged.push({ square: fromList[minI].square, piece: fromList[minI].piece });
|
|
7782
|
-
localFromMatched[minI] = true;
|
|
7783
|
-
localToMatched[minJ] = true;
|
|
7784
|
-
fromMatched[fromList[minI].square.id] = true;
|
|
7785
|
-
toMatched[toList[minJ].square.id] = true;
|
|
7786
|
-
continue;
|
|
7787
|
-
}
|
|
7788
|
-
// Altrimenti, sposta il pezzo
|
|
7789
|
-
moves.push({ from: fromList[minI].square, to: toList[minJ].square, piece: fromList[minI].piece });
|
|
7790
|
-
localFromMatched[minI] = true;
|
|
7791
|
-
localToMatched[minJ] = true;
|
|
7792
|
-
fromMatched[fromList[minI].square.id] = true;
|
|
7793
|
-
toMatched[toList[minJ].square.id] = true;
|
|
7794
7767
|
}
|
|
7795
7768
|
});
|
|
7796
7769
|
|
|
7797
|
-
//
|
|
7798
|
-
|
|
7799
|
-
Object.keys(currentMap).forEach(key => {
|
|
7800
|
-
currentMap[key].forEach(({ square, piece }) => {
|
|
7801
|
-
if (!fromMatched[square.id]) {
|
|
7802
|
-
removes.push({ square, piece });
|
|
7803
|
-
}
|
|
7804
|
-
});
|
|
7805
|
-
});
|
|
7770
|
+
// Re-add listeners after updating pieces to ensure hover events work correctly
|
|
7771
|
+
this._addListeners();
|
|
7806
7772
|
|
|
7807
|
-
//
|
|
7808
|
-
const
|
|
7809
|
-
|
|
7810
|
-
|
|
7811
|
-
|
|
7812
|
-
|
|
7813
|
-
}
|
|
7814
|
-
});
|
|
7815
|
-
});
|
|
7773
|
+
// Trigger change event if position changed
|
|
7774
|
+
const gameStateAfter = this.positionService.getGame().fen();
|
|
7775
|
+
if (gameStateBefore !== gameStateAfter) {
|
|
7776
|
+
this.config.onChange(gameStateAfter);
|
|
7777
|
+
}
|
|
7778
|
+
}
|
|
7816
7779
|
|
|
7817
|
-
|
|
7818
|
-
|
|
7780
|
+
/**
|
|
7781
|
+
* Performs simultaneous piece updates
|
|
7782
|
+
* @private
|
|
7783
|
+
* @param {Object} squares - All squares
|
|
7784
|
+
* @param {string} gameStateBefore - Game state before update
|
|
7785
|
+
* @param {boolean} [isPositionLoad=false] - Whether this is a position load
|
|
7786
|
+
*/
|
|
7787
|
+
_doSimultaneousUpdate(squares, gameStateBefore, isPositionLoad = false) {
|
|
7788
|
+
console.log('_doSimultaneousUpdate - Starting simultaneous update');
|
|
7789
|
+
|
|
7790
|
+
// Analyze what changes need to be made
|
|
7791
|
+
const changeAnalysis = this._analyzePositionChanges(squares);
|
|
7792
|
+
|
|
7793
|
+
if (changeAnalysis.totalChanges === 0) {
|
|
7794
|
+
console.log('_doSimultaneousUpdate - No changes needed, returning');
|
|
7819
7795
|
this._addListeners();
|
|
7796
|
+
|
|
7797
|
+
// Trigger change event if position changed
|
|
7820
7798
|
const gameStateAfter = this.positionService.getGame().fen();
|
|
7821
7799
|
if (gameStateBefore !== gameStateAfter) {
|
|
7822
7800
|
this.config.onChange(gameStateAfter);
|
|
@@ -7824,64 +7802,10 @@ let Chessboard$1 = class Chessboard {
|
|
|
7824
7802
|
return;
|
|
7825
7803
|
}
|
|
7826
7804
|
|
|
7827
|
-
|
|
7828
|
-
if (unchanged.length > 0) {
|
|
7829
|
-
console.debug('[Chessboard] Unchanged pieces:', unchanged.map(u => u.piece.id + '@' + u.square.id));
|
|
7830
|
-
}
|
|
7831
|
-
|
|
7832
|
-
const onAnimationComplete = () => {
|
|
7833
|
-
animationsCompleted++;
|
|
7834
|
-
if (animationsCompleted === totalAnimations) {
|
|
7835
|
-
// Pulizia finale robusta: rimuovi tutti i pezzi orfani dal DOM e dal riferimento JS
|
|
7836
|
-
Object.values(this.boardService.getAllSquares()).forEach(square => {
|
|
7837
|
-
const expectedPieceId = this.positionService.getGamePieceId(square.id);
|
|
7838
|
-
if (!expectedPieceId && typeof square.forceRemoveAllPieces === 'function') {
|
|
7839
|
-
square.forceRemoveAllPieces();
|
|
7840
|
-
}
|
|
7841
|
-
});
|
|
7842
|
-
this._addListeners();
|
|
7843
|
-
const gameStateAfter = this.positionService.getGame().fen();
|
|
7844
|
-
if (gameStateBefore !== gameStateAfter) {
|
|
7845
|
-
this.config.onChange(gameStateAfter);
|
|
7846
|
-
}
|
|
7847
|
-
}
|
|
7848
|
-
};
|
|
7805
|
+
console.log('_doSimultaneousUpdate - Change analysis:', changeAnalysis);
|
|
7849
7806
|
|
|
7850
|
-
//
|
|
7851
|
-
|
|
7852
|
-
moves.forEach(move => {
|
|
7853
|
-
setTimeout(() => {
|
|
7854
|
-
this.pieceService.translatePiece(
|
|
7855
|
-
move,
|
|
7856
|
-
false,
|
|
7857
|
-
animation,
|
|
7858
|
-
this._createDragFunction.bind(this),
|
|
7859
|
-
onAnimationComplete
|
|
7860
|
-
);
|
|
7861
|
-
}, idx++ * animationDelay);
|
|
7862
|
-
});
|
|
7863
|
-
removes.forEach(op => {
|
|
7864
|
-
setTimeout(() => {
|
|
7865
|
-
if (typeof op.square.forceRemoveAllPieces === 'function') {
|
|
7866
|
-
op.square.forceRemoveAllPieces();
|
|
7867
|
-
onAnimationComplete();
|
|
7868
|
-
} else {
|
|
7869
|
-
this.pieceService.removePieceFromSquare(op.square, animation, onAnimationComplete);
|
|
7870
|
-
}
|
|
7871
|
-
}, idx++ * animationDelay);
|
|
7872
|
-
});
|
|
7873
|
-
adds.forEach(op => {
|
|
7874
|
-
setTimeout(() => {
|
|
7875
|
-
const newPiece = this.pieceService.convertPiece(op.pieceId);
|
|
7876
|
-
this.pieceService.addPieceOnSquare(
|
|
7877
|
-
op.square,
|
|
7878
|
-
newPiece,
|
|
7879
|
-
animation,
|
|
7880
|
-
this._createDragFunction.bind(this),
|
|
7881
|
-
onAnimationComplete
|
|
7882
|
-
);
|
|
7883
|
-
}, idx++ * animationDelay);
|
|
7884
|
-
});
|
|
7807
|
+
// Execute all changes simultaneously
|
|
7808
|
+
this._executeSimultaneousChanges(changeAnalysis, gameStateBefore, isPositionLoad);
|
|
7885
7809
|
}
|
|
7886
7810
|
|
|
7887
7811
|
/**
|
|
@@ -8207,380 +8131,99 @@ let Chessboard$1 = class Chessboard {
|
|
|
8207
8131
|
}
|
|
8208
8132
|
|
|
8209
8133
|
// -------------------
|
|
8210
|
-
// Public API Methods
|
|
8134
|
+
// Public API Methods
|
|
8211
8135
|
// -------------------
|
|
8212
8136
|
|
|
8213
|
-
// --- POSITION & STATE ---
|
|
8214
|
-
/**
|
|
8215
|
-
* Get the current position as FEN
|
|
8216
|
-
* @returns {string}
|
|
8217
|
-
*/
|
|
8218
|
-
getPosition() { return this.fen(); }
|
|
8219
|
-
/**
|
|
8220
|
-
* Set the board position (FEN or object)
|
|
8221
|
-
* @param {string|Object} position
|
|
8222
|
-
* @param {Object} [opts]
|
|
8223
|
-
* @param {boolean} [opts.animate=true]
|
|
8224
|
-
* @returns {boolean}
|
|
8225
|
-
*/
|
|
8226
|
-
setPosition(position, opts = {}) {
|
|
8227
|
-
const animate = opts.animate !== undefined ? opts.animate : true;
|
|
8228
|
-
// Remove highlights and selections
|
|
8229
|
-
if (this.boardService && this.boardService.applyToAllSquares) {
|
|
8230
|
-
this.boardService.applyToAllSquares('removeHint');
|
|
8231
|
-
this.boardService.applyToAllSquares('deselect');
|
|
8232
|
-
this.boardService.applyToAllSquares('unmoved');
|
|
8233
|
-
}
|
|
8234
|
-
if (this.positionService && this.positionService.setGame) {
|
|
8235
|
-
this.positionService.setGame(position);
|
|
8236
|
-
}
|
|
8237
|
-
if (this._updateBoardPieces) {
|
|
8238
|
-
this._updateBoardPieces(animate, true);
|
|
8239
|
-
}
|
|
8240
|
-
// Forza la sincronizzazione dopo setPosition
|
|
8241
|
-
this._updateBoardPieces(true, false);
|
|
8242
|
-
return true;
|
|
8243
|
-
}
|
|
8244
|
-
/**
|
|
8245
|
-
* Reset the board to the starting position
|
|
8246
|
-
* @param {Object} [opts]
|
|
8247
|
-
* @param {boolean} [opts.animate=true]
|
|
8248
|
-
* @returns {boolean}
|
|
8249
|
-
*/
|
|
8250
|
-
reset(opts = {}) {
|
|
8251
|
-
const animate = opts.animate !== undefined ? opts.animate : true;
|
|
8252
|
-
// Use the default starting position from config or fallback
|
|
8253
|
-
const startPosition = this.config && this.config.position ? this.config.position : 'start';
|
|
8254
|
-
this._updateBoardPieces(animate);
|
|
8255
|
-
const result = this.setPosition(startPosition, { animate });
|
|
8256
|
-
// Forza la sincronizzazione dopo reset
|
|
8257
|
-
this._updateBoardPieces(true, false);
|
|
8258
|
-
return result;
|
|
8259
|
-
}
|
|
8260
8137
|
/**
|
|
8261
|
-
*
|
|
8262
|
-
* @
|
|
8263
|
-
* @param {boolean} [opts.animate=true]
|
|
8264
|
-
* @returns {boolean}
|
|
8138
|
+
* Gets the current position as FEN
|
|
8139
|
+
* @returns {string} FEN string
|
|
8265
8140
|
*/
|
|
8266
|
-
|
|
8267
|
-
|
|
8268
|
-
if (!this.positionService || !this.positionService.getGame()) {
|
|
8269
|
-
return false;
|
|
8270
|
-
}
|
|
8271
|
-
if (this._clearVisualState) this._clearVisualState();
|
|
8272
|
-
this.positionService.getGame().clear();
|
|
8273
|
-
// Forza la rimozione di tutti i pezzi dal DOM
|
|
8274
|
-
if (this.boardService && this.boardService.squares) {
|
|
8275
|
-
Object.values(this.boardService.squares).forEach(sq => {
|
|
8276
|
-
if (sq && sq.piece) sq.piece = null;
|
|
8277
|
-
});
|
|
8278
|
-
}
|
|
8279
|
-
if (this._updateBoardPieces) {
|
|
8280
|
-
this._updateBoardPieces(animate, true);
|
|
8281
|
-
}
|
|
8282
|
-
// Forza la sincronizzazione dopo clear
|
|
8283
|
-
this._updateBoardPieces(true, false);
|
|
8284
|
-
return true;
|
|
8141
|
+
fen() {
|
|
8142
|
+
return this.positionService.getGame().fen();
|
|
8285
8143
|
}
|
|
8286
8144
|
|
|
8287
|
-
// --- MOVE MANAGEMENT ---
|
|
8288
|
-
/**
|
|
8289
|
-
* Undo last move
|
|
8290
|
-
* @param {Object} [opts]
|
|
8291
|
-
* @param {boolean} [opts.animate=true]
|
|
8292
|
-
* @returns {boolean}
|
|
8293
|
-
*/
|
|
8294
|
-
undoMove(opts = {}) {
|
|
8295
|
-
const undone = this.positionService.getGame().undo();
|
|
8296
|
-
if (undone) {
|
|
8297
|
-
this._undoneMoves.push(undone);
|
|
8298
|
-
// Forza refresh completo di tutti i pezzi dopo undo
|
|
8299
|
-
this._updateBoardPieces(true, true);
|
|
8300
|
-
return undone;
|
|
8301
|
-
}
|
|
8302
|
-
return null;
|
|
8303
|
-
}
|
|
8304
8145
|
/**
|
|
8305
|
-
*
|
|
8306
|
-
* @
|
|
8307
|
-
* @param {boolean} [opts.animate=true]
|
|
8308
|
-
* @returns {boolean}
|
|
8146
|
+
* Gets current turn
|
|
8147
|
+
* @returns {string} 'w' or 'b'
|
|
8309
8148
|
*/
|
|
8310
|
-
|
|
8311
|
-
|
|
8312
|
-
const move = this._undoneMoves.pop();
|
|
8313
|
-
const moveObj = { from: move.from, to: move.to };
|
|
8314
|
-
if (move.promotion) moveObj.promotion = move.promotion;
|
|
8315
|
-
const result = this.positionService.getGame().move(moveObj);
|
|
8316
|
-
// Forza refresh completo di tutti i pezzi dopo redo
|
|
8317
|
-
this._updateBoardPieces(true, true);
|
|
8318
|
-
return result;
|
|
8319
|
-
}
|
|
8320
|
-
return false;
|
|
8149
|
+
turn() {
|
|
8150
|
+
return this.positionService.getGame().turn();
|
|
8321
8151
|
}
|
|
8322
|
-
/**
|
|
8323
|
-
* Get legal moves for a square
|
|
8324
|
-
* @param {string} square
|
|
8325
|
-
* @returns {Array}
|
|
8326
|
-
*/
|
|
8327
|
-
getLegalMoves(square) { return this.legalMoves(square); }
|
|
8328
8152
|
|
|
8329
|
-
// --- PIECE MANAGEMENT ---
|
|
8330
8153
|
/**
|
|
8331
|
-
*
|
|
8332
|
-
* @param {string}
|
|
8333
|
-
* @
|
|
8334
|
-
|
|
8335
|
-
getPiece(square) {
|
|
8336
|
-
// Sempre leggi lo stato aggiornato dal boardService
|
|
8337
|
-
const squareObj = typeof square === 'string' ? this.boardService.getSquare(square) : square;
|
|
8338
|
-
if (!squareObj || typeof squareObj !== 'object' || !('id' in squareObj)) throw new Error('[getPiece] Parametro square non valido');
|
|
8339
|
-
// Forza sync prima di leggere
|
|
8340
|
-
this._updateBoardPieces(false, false);
|
|
8341
|
-
const piece = squareObj.piece;
|
|
8342
|
-
if (!piece) return null;
|
|
8343
|
-
return (piece.color + piece.type).toLowerCase();
|
|
8344
|
-
}
|
|
8345
|
-
/**
|
|
8346
|
-
* Put a piece on a square
|
|
8347
|
-
* @param {string|Piece} piece
|
|
8348
|
-
* @param {string|Square} square
|
|
8349
|
-
* @param {Object} [opts]
|
|
8350
|
-
* @param {boolean} [opts.animate=true]
|
|
8351
|
-
* @returns {boolean}
|
|
8154
|
+
* Loads a new position
|
|
8155
|
+
* @param {string|Object} position - Position to load
|
|
8156
|
+
* @param {Object} [options={}] - Loading options
|
|
8157
|
+
* @param {boolean} [animation=true] - Whether to animate
|
|
8352
8158
|
*/
|
|
8353
|
-
|
|
8354
|
-
|
|
8355
|
-
|
|
8356
|
-
|
|
8357
|
-
pieceStr = (piece.color + piece.type).toLowerCase();
|
|
8358
|
-
} else if (typeof piece === 'string' && piece.length === 2) {
|
|
8359
|
-
const a = piece[0].toLowerCase();
|
|
8360
|
-
const b = piece[1].toLowerCase();
|
|
8361
|
-
const types = 'kqrbnp';
|
|
8362
|
-
const colors = 'wb';
|
|
8363
|
-
if (types.includes(a) && colors.includes(b)) {
|
|
8364
|
-
pieceStr = b + a;
|
|
8365
|
-
} else if (colors.includes(a) && types.includes(b)) {
|
|
8366
|
-
pieceStr = a + b;
|
|
8367
|
-
} else {
|
|
8368
|
-
throw new Error(`[putPiece] Invalid piece: ${piece}`);
|
|
8369
|
-
}
|
|
8370
|
-
}
|
|
8371
|
-
const squareObj = typeof square === 'string' ? this.boardService.getSquare(square) : square;
|
|
8372
|
-
if (!squareObj || typeof squareObj !== 'object' || !('id' in squareObj)) throw new Error('[putPiece] Parametro square non valido');
|
|
8373
|
-
const pieceObj = this.pieceService.convertPiece(pieceStr);
|
|
8374
|
-
if (!pieceObj || typeof pieceObj !== 'object' || !('type' in pieceObj)) throw new Error('[putPiece] Parametro piece non valido');
|
|
8375
|
-
// Aggiorna solo il motore chess.js
|
|
8376
|
-
const chessJsPiece = { type: pieceObj.type, color: pieceObj.color };
|
|
8377
|
-
const game = this.positionService.getGame();
|
|
8378
|
-
const result = game.put(chessJsPiece, squareObj.id);
|
|
8379
|
-
if (!result) throw new Error(`[putPiece] Game.put failed for ${pieceStr} on ${squareObj.id}`);
|
|
8380
|
-
// Non aggiornare direttamente square.piece!
|
|
8381
|
-
// Riallinea la board JS allo stato del motore
|
|
8382
|
-
this._updateBoardPieces(animate);
|
|
8383
|
-
return true;
|
|
8384
|
-
}
|
|
8385
|
-
/**
|
|
8386
|
-
* Remove a piece from a square
|
|
8387
|
-
* @param {string|Square} square
|
|
8388
|
-
* @param {Object} [opts]
|
|
8389
|
-
* @param {boolean} [opts.animate=true]
|
|
8390
|
-
* @returns {string|null}
|
|
8391
|
-
*/
|
|
8392
|
-
removePiece(square, opts = {}) {
|
|
8393
|
-
const animate = opts.animate !== undefined ? opts.animate : true;
|
|
8394
|
-
const squareObj = typeof square === 'string' ? this.boardService.getSquare(square) : square;
|
|
8395
|
-
if (!squareObj || typeof squareObj !== 'object' || !('id' in squareObj)) throw new Error('[removePiece] Parametro square non valido');
|
|
8396
|
-
// Aggiorna solo il motore chess.js
|
|
8397
|
-
const game = this.positionService.getGame();
|
|
8398
|
-
game.remove(squareObj.id);
|
|
8399
|
-
// Non aggiornare direttamente square.piece!
|
|
8400
|
-
// Riallinea la board JS allo stato del motore
|
|
8401
|
-
this._updateBoardPieces(animate);
|
|
8402
|
-
return true;
|
|
8403
|
-
}
|
|
8159
|
+
load(position, options = {}, animation = true) {
|
|
8160
|
+
this.boardService.applyToAllSquares('removeHint');
|
|
8161
|
+
this.boardService.applyToAllSquares('deselect');
|
|
8162
|
+
this.boardService.applyToAllSquares('unmoved');
|
|
8404
8163
|
|
|
8405
|
-
|
|
8406
|
-
|
|
8407
|
-
* Flip the board orientation
|
|
8408
|
-
* @param {Object} [opts]
|
|
8409
|
-
* @param {boolean} [opts.animate=true]
|
|
8410
|
-
*/
|
|
8411
|
-
flipBoard(opts = {}) {
|
|
8412
|
-
if (this.coordinateService && this.coordinateService.flipOrientation) {
|
|
8413
|
-
this.coordinateService.flipOrientation();
|
|
8414
|
-
}
|
|
8415
|
-
if (this._buildBoard) this._buildBoard();
|
|
8416
|
-
if (this._buildSquares) this._buildSquares();
|
|
8417
|
-
if (this._addListeners) this._addListeners();
|
|
8418
|
-
if (this._updateBoardPieces) this._updateBoardPieces(opts.animate !== false);
|
|
8419
|
-
console.log('FEN dopo flip:', this.fen(), 'Orientamento:', this.coordinateService.getOrientation());
|
|
8420
|
-
}
|
|
8421
|
-
/**
|
|
8422
|
-
* Set the board orientation
|
|
8423
|
-
* @param {'w'|'b'} color
|
|
8424
|
-
* @param {Object} [opts]
|
|
8425
|
-
* @param {boolean} [opts.animate=true]
|
|
8426
|
-
*/
|
|
8427
|
-
setOrientation(color, opts = {}) {
|
|
8428
|
-
if (this.validationService.isValidOrientation(color)) {
|
|
8429
|
-
this.coordinateService.setOrientation(color);
|
|
8430
|
-
if (this._buildBoard) this._buildBoard();
|
|
8431
|
-
if (this._buildSquares) this._buildSquares();
|
|
8432
|
-
if (this._addListeners) this._addListeners();
|
|
8433
|
-
if (this._updateBoardPieces) this._updateBoardPieces(opts.animate !== false);
|
|
8434
|
-
}
|
|
8435
|
-
return this.coordinateService.getOrientation();
|
|
8436
|
-
}
|
|
8437
|
-
/**
|
|
8438
|
-
* Get the current orientation
|
|
8439
|
-
* @returns {'w'|'b'}
|
|
8440
|
-
*/
|
|
8441
|
-
getOrientation() { return this.orientation(); }
|
|
8442
|
-
/**
|
|
8443
|
-
* Resize the board
|
|
8444
|
-
* @param {number|string} size
|
|
8445
|
-
*/
|
|
8446
|
-
resizeBoard(size) {
|
|
8447
|
-
if (size === 'auto') {
|
|
8448
|
-
this.config.size = 'auto';
|
|
8449
|
-
document.documentElement.style.setProperty('--dimBoard', 'auto');
|
|
8450
|
-
this._updateBoardPieces(false);
|
|
8451
|
-
return true;
|
|
8452
|
-
}
|
|
8453
|
-
if (typeof size !== 'number' || size < 50 || size > 3000) {
|
|
8454
|
-
throw new Error(`[resizeBoard] Invalid size: ${size}`);
|
|
8455
|
-
}
|
|
8456
|
-
this.config.size = size;
|
|
8457
|
-
document.documentElement.style.setProperty('--dimBoard', `${size}px`);
|
|
8458
|
-
this._updateBoardPieces(false);
|
|
8459
|
-
return true;
|
|
8164
|
+
this.positionService.setGame(position, options);
|
|
8165
|
+
this._updateBoardPieces(animation, true); // Position load
|
|
8460
8166
|
}
|
|
8461
8167
|
|
|
8462
|
-
// --- HIGHLIGHTING & UI ---
|
|
8463
8168
|
/**
|
|
8464
|
-
*
|
|
8465
|
-
* @param {string|Square} square
|
|
8466
|
-
* @param {Object} [opts]
|
|
8467
|
-
*/
|
|
8468
|
-
highlight(square, opts = {}) {
|
|
8469
|
-
// API: accetta id, converte subito in oggetto
|
|
8470
|
-
const squareObj = typeof square === 'string' ? this.boardService.getSquare(square) : square;
|
|
8471
|
-
if (!squareObj || typeof squareObj !== 'object' || !('id' in squareObj)) throw new Error('[highlight] Parametro square non valido');
|
|
8472
|
-
if (this.boardService && this.boardService.highlightSquare) {
|
|
8473
|
-
this.boardService.highlightSquare(squareObj, opts);
|
|
8474
|
-
} else if (this.eventService && this.eventService.highlightSquare) {
|
|
8475
|
-
this.eventService.highlightSquare(squareObj, opts);
|
|
8476
|
-
}
|
|
8477
|
-
}
|
|
8478
|
-
/**
|
|
8479
|
-
* Remove highlight from a square
|
|
8480
|
-
* @param {string|Square} square
|
|
8481
|
-
* @param {Object} [opts]
|
|
8169
|
+
* Destroys the board and cleans up resources
|
|
8482
8170
|
*/
|
|
8483
|
-
|
|
8484
|
-
|
|
8485
|
-
|
|
8486
|
-
|
|
8487
|
-
|
|
8488
|
-
|
|
8489
|
-
|
|
8490
|
-
|
|
8171
|
+
destroy() {
|
|
8172
|
+
this.eventService.destroy();
|
|
8173
|
+
this.boardService.destroy();
|
|
8174
|
+
this.positionService.destroy();
|
|
8175
|
+
this.pieceService.destroy();
|
|
8176
|
+
this.moveService.destroy();
|
|
8177
|
+
this.animationService.destroy();
|
|
8178
|
+
this.validationService.destroy();
|
|
8179
|
+
|
|
8180
|
+
if (this._updateTimeout) {
|
|
8181
|
+
clearTimeout(this._updateTimeout);
|
|
8182
|
+
this._updateTimeout = null;
|
|
8491
8183
|
}
|
|
8492
8184
|
}
|
|
8493
8185
|
|
|
8494
|
-
// --- GAME INFO ---
|
|
8495
|
-
/**
|
|
8496
|
-
* Get FEN string
|
|
8497
|
-
* @returns {string}
|
|
8498
|
-
*/
|
|
8499
|
-
fen() {
|
|
8500
|
-
// Avoid recursion: call the underlying game object's fen()
|
|
8501
|
-
const game = this.positionService.getGame();
|
|
8502
|
-
if (!game || typeof game.fen !== 'function') return '';
|
|
8503
|
-
return game.fen();
|
|
8504
|
-
}
|
|
8505
|
-
/**
|
|
8506
|
-
* Get current turn
|
|
8507
|
-
* @returns {'w'|'b'}
|
|
8508
|
-
*/
|
|
8509
|
-
turn() { return this.positionService.getGame().turn(); }
|
|
8510
|
-
/**
|
|
8511
|
-
* Is the game over?
|
|
8512
|
-
* @returns {boolean}
|
|
8513
|
-
*/
|
|
8514
|
-
isGameOver() {
|
|
8515
|
-
// Forza sync prima di interrogare il motore
|
|
8516
|
-
this._updateBoardPieces(false, false);
|
|
8517
|
-
const game = this.positionService.getGame();
|
|
8518
|
-
if (!game) return false;
|
|
8519
|
-
if (game.isGameOver) return game.isGameOver();
|
|
8520
|
-
// Fallback: checkmate or draw
|
|
8521
|
-
if (game.isCheckmate && game.isCheckmate()) return true;
|
|
8522
|
-
if (game.isDraw && game.isDraw()) return true;
|
|
8523
|
-
return false;
|
|
8524
|
-
}
|
|
8525
|
-
/**
|
|
8526
|
-
* Is it checkmate?
|
|
8527
|
-
* @returns {boolean}
|
|
8528
|
-
*/
|
|
8529
|
-
isCheckmate() {
|
|
8530
|
-
const game = this.positionService.getGame();
|
|
8531
|
-
if (!game) return false;
|
|
8532
|
-
return game.isCheckmate ? game.isCheckmate() : false;
|
|
8533
|
-
}
|
|
8534
|
-
/**
|
|
8535
|
-
* Is it draw?
|
|
8536
|
-
* @returns {boolean}
|
|
8537
|
-
*/
|
|
8538
|
-
isDraw() {
|
|
8539
|
-
const game = this.positionService.getGame();
|
|
8540
|
-
if (!game) return false;
|
|
8541
|
-
return game.isDraw ? game.isDraw() : false;
|
|
8542
|
-
}
|
|
8543
8186
|
/**
|
|
8544
|
-
*
|
|
8545
|
-
* @
|
|
8187
|
+
* Resizes the board
|
|
8188
|
+
* @param {number|string} size - New size
|
|
8546
8189
|
*/
|
|
8547
|
-
|
|
8548
|
-
|
|
8549
|
-
|
|
8550
|
-
return game.history ? game.history() : [];
|
|
8190
|
+
resize(size) {
|
|
8191
|
+
this.boardService.resize(size);
|
|
8192
|
+
this._updateBoardPieces();
|
|
8551
8193
|
}
|
|
8552
8194
|
|
|
8553
|
-
// --- LIFECYCLE ---
|
|
8554
|
-
/**
|
|
8555
|
-
* Destroy the board and cleanup
|
|
8556
|
-
*/
|
|
8557
|
-
destroy() { /* TODO: robust destroy logic */ }
|
|
8558
8195
|
/**
|
|
8559
|
-
*
|
|
8196
|
+
* Flips the board orientation
|
|
8560
8197
|
*/
|
|
8561
|
-
|
|
8198
|
+
flip() {
|
|
8199
|
+
this.coordinateService.flipOrientation();
|
|
8562
8200
|
|
|
8563
|
-
|
|
8564
|
-
|
|
8565
|
-
|
|
8566
|
-
|
|
8567
|
-
|
|
8568
|
-
|
|
8569
|
-
/**
|
|
8570
|
-
* Set new config
|
|
8571
|
-
* @param {Object} newConfig
|
|
8572
|
-
*/
|
|
8573
|
-
setConfig(newConfig) { this.setConfig(newConfig); }
|
|
8201
|
+
// Save current position before destroying
|
|
8202
|
+
let currentPosition = null;
|
|
8203
|
+
try {
|
|
8204
|
+
// Check if there are any pieces on the board
|
|
8205
|
+
const position = this.positionService.getPosition();
|
|
8206
|
+
const hasPieces = Object.keys(position).length > 0;
|
|
8574
8207
|
|
|
8575
|
-
|
|
8576
|
-
|
|
8208
|
+
if (hasPieces) {
|
|
8209
|
+
currentPosition = this.positionService.getGame().fen();
|
|
8210
|
+
}
|
|
8211
|
+
} catch (error) {
|
|
8212
|
+
console.log('No valid position to save during flip');
|
|
8213
|
+
}
|
|
8577
8214
|
|
|
8578
|
-
|
|
8579
|
-
|
|
8580
|
-
|
|
8581
|
-
|
|
8582
|
-
|
|
8583
|
-
|
|
8215
|
+
this.destroy();
|
|
8216
|
+
this._initializeServices(); // Recreate all services
|
|
8217
|
+
this._initParams();
|
|
8218
|
+
|
|
8219
|
+
// Restore position after rebuilding if we had one
|
|
8220
|
+
if (currentPosition) {
|
|
8221
|
+
this._setGame(currentPosition);
|
|
8222
|
+
}
|
|
8223
|
+
this._buildBoard();
|
|
8224
|
+
this._buildSquares();
|
|
8225
|
+
this._addListeners();
|
|
8226
|
+
this._updateBoardPieces(true, true);
|
|
8584
8227
|
}
|
|
8585
8228
|
|
|
8586
8229
|
/**
|
|
@@ -8603,19 +8246,51 @@ let Chessboard$1 = class Chessboard {
|
|
|
8603
8246
|
this.load(position, {}, animate); // load() already handles isPositionLoad=true
|
|
8604
8247
|
}
|
|
8605
8248
|
|
|
8249
|
+
/**
|
|
8250
|
+
* Makes a move on the board
|
|
8251
|
+
* @param {string|Object} move - Move to make
|
|
8252
|
+
* @param {boolean} [animate=true] - Whether to animate
|
|
8253
|
+
* @returns {boolean} True if move was successful
|
|
8254
|
+
*/
|
|
8255
|
+
move(move, animate = true) {
|
|
8256
|
+
if (typeof move === 'string') {
|
|
8257
|
+
// Parse move string (e.g., 'e2e4')
|
|
8258
|
+
const moveObj = this.moveService.parseMove(move);
|
|
8259
|
+
if (!moveObj) return false;
|
|
8260
|
+
|
|
8261
|
+
const fromSquare = this.boardService.getSquare(moveObj.from);
|
|
8262
|
+
const toSquare = this.boardService.getSquare(moveObj.to);
|
|
8263
|
+
|
|
8264
|
+
if (!fromSquare || !toSquare) return false;
|
|
8265
|
+
|
|
8266
|
+
return this._onMove(fromSquare, toSquare, moveObj.promotion, animate);
|
|
8267
|
+
} else if (move && move.from && move.to) {
|
|
8268
|
+
// Handle move object
|
|
8269
|
+
const fromSquare = this.boardService.getSquare(move.from);
|
|
8270
|
+
const toSquare = this.boardService.getSquare(move.to);
|
|
8271
|
+
|
|
8272
|
+
if (!fromSquare || !toSquare) return false;
|
|
8273
|
+
|
|
8274
|
+
return this._onMove(fromSquare, toSquare, move.promotion, animate);
|
|
8275
|
+
}
|
|
8276
|
+
|
|
8277
|
+
return false;
|
|
8278
|
+
}
|
|
8279
|
+
|
|
8606
8280
|
/**
|
|
8607
8281
|
* Undoes the last move
|
|
8608
8282
|
* @param {boolean} [animate=true] - Whether to animate
|
|
8609
8283
|
* @returns {boolean} True if undo was successful
|
|
8610
8284
|
*/
|
|
8611
8285
|
undo(animate = true) {
|
|
8612
|
-
|
|
8613
|
-
|
|
8614
|
-
|
|
8615
|
-
|
|
8616
|
-
|
|
8286
|
+
if (this.positionService.getGame().undo) {
|
|
8287
|
+
const undoResult = this.positionService.getGame().undo();
|
|
8288
|
+
if (undoResult) {
|
|
8289
|
+
this._updateBoardPieces(animate, true); // Position change
|
|
8290
|
+
return true;
|
|
8291
|
+
}
|
|
8617
8292
|
}
|
|
8618
|
-
return
|
|
8293
|
+
return false;
|
|
8619
8294
|
}
|
|
8620
8295
|
|
|
8621
8296
|
/**
|
|
@@ -8624,13 +8299,12 @@ let Chessboard$1 = class Chessboard {
|
|
|
8624
8299
|
* @returns {boolean} True if redo was successful
|
|
8625
8300
|
*/
|
|
8626
8301
|
redo(animate = true) {
|
|
8627
|
-
if (this.
|
|
8628
|
-
const
|
|
8629
|
-
|
|
8630
|
-
|
|
8631
|
-
|
|
8632
|
-
|
|
8633
|
-
return result;
|
|
8302
|
+
if (this.positionService.getGame().redo) {
|
|
8303
|
+
const redoResult = this.positionService.getGame().redo();
|
|
8304
|
+
if (redoResult) {
|
|
8305
|
+
this._updateBoardPieces(animate, true); // Position change
|
|
8306
|
+
return true;
|
|
8307
|
+
}
|
|
8634
8308
|
}
|
|
8635
8309
|
return false;
|
|
8636
8310
|
}
|
|
@@ -8792,6 +8466,112 @@ let Chessboard$1 = class Chessboard {
|
|
|
8792
8466
|
}
|
|
8793
8467
|
}
|
|
8794
8468
|
|
|
8469
|
+
/**
|
|
8470
|
+
* Clears the board
|
|
8471
|
+
* @param {boolean} [animate=true] - Whether to animate
|
|
8472
|
+
*/
|
|
8473
|
+
clear(animate = true) {
|
|
8474
|
+
// Check if services are available
|
|
8475
|
+
if (!this.positionService || !this.positionService.getGame()) {
|
|
8476
|
+
console.log('Cannot clear - position service not available');
|
|
8477
|
+
return;
|
|
8478
|
+
}
|
|
8479
|
+
|
|
8480
|
+
// Clear visual state first
|
|
8481
|
+
this._clearVisualState();
|
|
8482
|
+
|
|
8483
|
+
// Clear game state
|
|
8484
|
+
this.positionService.getGame().clear();
|
|
8485
|
+
|
|
8486
|
+
// Update board visually
|
|
8487
|
+
this._updateBoardPieces(animate, true); // Position change
|
|
8488
|
+
}
|
|
8489
|
+
|
|
8490
|
+
/**
|
|
8491
|
+
* Resets the board to starting position
|
|
8492
|
+
* @param {boolean} [animate=true] - Whether to animate
|
|
8493
|
+
*/
|
|
8494
|
+
reset(animate = true) {
|
|
8495
|
+
// Check if services are available
|
|
8496
|
+
if (!this.positionService || !this.positionService.getGame()) {
|
|
8497
|
+
console.log('Cannot reset - position service not available');
|
|
8498
|
+
return;
|
|
8499
|
+
}
|
|
8500
|
+
|
|
8501
|
+
this.positionService.getGame().reset();
|
|
8502
|
+
this._updateBoardPieces(animate, true); // Position change
|
|
8503
|
+
}
|
|
8504
|
+
|
|
8505
|
+
/**
|
|
8506
|
+
* Puts a piece on a square
|
|
8507
|
+
* @param {string} square - Square to put piece on
|
|
8508
|
+
* @param {string} piece - Piece to put
|
|
8509
|
+
* @param {boolean} [animate=true] - Whether to animate
|
|
8510
|
+
* @returns {boolean} True if successful
|
|
8511
|
+
*/
|
|
8512
|
+
put(square, piece, animate = true) {
|
|
8513
|
+
console.log(`put() called with square: ${square}, piece: ${piece}`);
|
|
8514
|
+
|
|
8515
|
+
if (!this.validationService.isValidSquare(square) || !this.validationService.isValidPiece(piece)) {
|
|
8516
|
+
console.log('Validation failed');
|
|
8517
|
+
return false;
|
|
8518
|
+
}
|
|
8519
|
+
|
|
8520
|
+
// Check if services are available
|
|
8521
|
+
if (!this.positionService || !this.positionService.getGame()) {
|
|
8522
|
+
console.log('Cannot put piece - position service not available');
|
|
8523
|
+
return false;
|
|
8524
|
+
}
|
|
8525
|
+
|
|
8526
|
+
const pieceObj = this.pieceService.convertPiece(piece);
|
|
8527
|
+
console.log(`Converted piece:`, pieceObj);
|
|
8528
|
+
console.log(`Piece type: ${pieceObj.type}, color: ${pieceObj.color}`);
|
|
8529
|
+
|
|
8530
|
+
const squareObj = this.boardService.getSquare(square);
|
|
8531
|
+
|
|
8532
|
+
if (!squareObj) {
|
|
8533
|
+
console.log('Square not found');
|
|
8534
|
+
return false;
|
|
8535
|
+
}
|
|
8536
|
+
|
|
8537
|
+
// Update game state - note: chess.js expects (piece, square) order
|
|
8538
|
+
const chessJsPiece = { type: pieceObj.type.toLowerCase(), color: pieceObj.color.toLowerCase() };
|
|
8539
|
+
console.log(`Chess.js piece:`, chessJsPiece);
|
|
8540
|
+
|
|
8541
|
+
const result = this.positionService.getGame().put(chessJsPiece, square);
|
|
8542
|
+
console.log(`Chess.js put result:`, result);
|
|
8543
|
+
|
|
8544
|
+
if (result) {
|
|
8545
|
+
// Update visual representation
|
|
8546
|
+
this._updateBoardPieces(animate, true); // Position change
|
|
8547
|
+
}
|
|
8548
|
+
|
|
8549
|
+
return result;
|
|
8550
|
+
}
|
|
8551
|
+
|
|
8552
|
+
/**
|
|
8553
|
+
* Removes a piece from a square
|
|
8554
|
+
* @param {string} square - Square to remove piece from
|
|
8555
|
+
* @param {boolean} [animate=true] - Whether to animate
|
|
8556
|
+
* @returns {boolean} True if successful
|
|
8557
|
+
*/
|
|
8558
|
+
remove(square, animate = true) {
|
|
8559
|
+
if (!this.validationService.isValidSquare(square)) {
|
|
8560
|
+
return false;
|
|
8561
|
+
}
|
|
8562
|
+
|
|
8563
|
+
const squareObj = this.boardService.getSquare(square);
|
|
8564
|
+
if (!squareObj) return false;
|
|
8565
|
+
|
|
8566
|
+
// Update game state
|
|
8567
|
+
this.positionService.getGame().remove(square);
|
|
8568
|
+
|
|
8569
|
+
// Update visual representation
|
|
8570
|
+
this._updateBoardPieces(animate, true); // Position change
|
|
8571
|
+
|
|
8572
|
+
return true;
|
|
8573
|
+
}
|
|
8574
|
+
|
|
8795
8575
|
/**
|
|
8796
8576
|
* Gets configuration options
|
|
8797
8577
|
* @returns {Object} Configuration object
|
|
@@ -8817,6 +8597,23 @@ let Chessboard$1 = class Chessboard {
|
|
|
8817
8597
|
}
|
|
8818
8598
|
}
|
|
8819
8599
|
|
|
8600
|
+
/**
|
|
8601
|
+
* Gets or sets the animation style
|
|
8602
|
+
* @param {string} [style] - New animation style ('sequential' or 'simultaneous')
|
|
8603
|
+
* @returns {string} Current animation style
|
|
8604
|
+
*/
|
|
8605
|
+
animationStyle(style) {
|
|
8606
|
+
if (style === undefined) {
|
|
8607
|
+
return this.config.animationStyle;
|
|
8608
|
+
}
|
|
8609
|
+
|
|
8610
|
+
if (this.validationService.isValidAnimationStyle(style)) {
|
|
8611
|
+
this.config.animationStyle = style;
|
|
8612
|
+
}
|
|
8613
|
+
|
|
8614
|
+
return this.config.animationStyle;
|
|
8615
|
+
}
|
|
8616
|
+
|
|
8820
8617
|
/**
|
|
8821
8618
|
* Gets or sets the simultaneous animation delay
|
|
8822
8619
|
* @param {number} [delay] - New delay in milliseconds
|
|
@@ -8836,97 +8633,7 @@ let Chessboard$1 = class Chessboard {
|
|
|
8836
8633
|
|
|
8837
8634
|
// Additional API methods would be added here following the same pattern
|
|
8838
8635
|
// This is a good starting point for the refactored architecture
|
|
8839
|
-
|
|
8840
|
-
// Additional API methods and aliases for backward compatibility
|
|
8841
|
-
insert(square, piece) { return this.putPiece(piece, square); }
|
|
8842
|
-
build() { return this._initialize(); }
|
|
8843
|
-
ascii() { return this.positionService.getGame().ascii(); }
|
|
8844
|
-
board() { return this.positionService.getGame().board(); }
|
|
8845
|
-
getCastlingRights(color) { return this.positionService.getGame().getCastlingRights(color); }
|
|
8846
|
-
getComment() { return this.positionService.getGame().getComment(); }
|
|
8847
|
-
getComments() { return this.positionService.getGame().getComments(); }
|
|
8848
|
-
lastMove() { return this.positionService.getGame().lastMove(); }
|
|
8849
|
-
moveNumber() { return this.positionService.getGame().moveNumber(); }
|
|
8850
|
-
moves(options = {}) { return this.positionService.getGame().moves(options); }
|
|
8851
|
-
squareColor(squareId) { return this.boardService.getSquare(squareId).isWhite() ? 'light' : 'dark'; }
|
|
8852
|
-
isDrawByFiftyMoves() { return this.positionService.getGame().isDrawByFiftyMoves(); }
|
|
8853
|
-
isInsufficientMaterial() { return this.positionService.getGame().isInsufficientMaterial(); }
|
|
8854
|
-
removeComment() { return this.positionService.getGame().removeComment(); }
|
|
8855
|
-
removeComments() { return this.positionService.getGame().removeComments(); }
|
|
8856
|
-
removeHeader(field) { return this.positionService.getGame().removeHeader(field); }
|
|
8857
|
-
setCastlingRights(color, rights) { return this.positionService.getGame().setCastlingRights(color, rights); }
|
|
8858
|
-
setComment(comment) { return this.positionService.getGame().setComment(comment); }
|
|
8859
|
-
setHeader(key, value) { return this.positionService.getGame().setHeader(key, value); }
|
|
8860
|
-
validateFen(fen) { return this.positionService.getGame().validateFen(fen); }
|
|
8861
|
-
|
|
8862
|
-
// Implementazioni reali per highlight/dehighlight
|
|
8863
|
-
highlightSquare(square) {
|
|
8864
|
-
return this.boardService.highlight(square);
|
|
8865
|
-
}
|
|
8866
|
-
dehighlightSquare(square) {
|
|
8867
|
-
return this.boardService.dehighlight(square);
|
|
8868
|
-
}
|
|
8869
|
-
forceSync() { this._updateBoardPieces(true, true); this._updateBoardPieces(true, false); }
|
|
8870
|
-
|
|
8871
|
-
// Metodi mancanti che causano fallimenti nei test
|
|
8872
|
-
/**
|
|
8873
|
-
* Move a piece from one square to another
|
|
8874
|
-
* @param {string|Object} move - Move in format 'e2e4' or {from: 'e2', to: 'e4'}
|
|
8875
|
-
* @param {Object} [opts] - Options
|
|
8876
|
-
* @param {boolean} [opts.animate=true] - Whether to animate
|
|
8877
|
-
* @returns {boolean} True if move was successful
|
|
8878
|
-
*/
|
|
8879
|
-
movePiece(move, opts = {}) {
|
|
8880
|
-
const animate = opts.animate !== undefined ? opts.animate : true;
|
|
8881
|
-
|
|
8882
|
-
// --- API: accetta id/stringhe, ma converte subito in oggetti ---
|
|
8883
|
-
let fromSquareObj, toSquareObj, promotion;
|
|
8884
|
-
if (typeof move === 'string') {
|
|
8885
|
-
if (move.length === 4) {
|
|
8886
|
-
fromSquareObj = this.boardService.getSquare(move.substring(0, 2));
|
|
8887
|
-
toSquareObj = this.boardService.getSquare(move.substring(2, 4));
|
|
8888
|
-
} else if (move.length === 5) {
|
|
8889
|
-
fromSquareObj = this.boardService.getSquare(move.substring(0, 2));
|
|
8890
|
-
toSquareObj = this.boardService.getSquare(move.substring(2, 4));
|
|
8891
|
-
promotion = move.substring(4, 5);
|
|
8892
|
-
} else {
|
|
8893
|
-
throw new Error(`Invalid move format: ${move}`);
|
|
8894
|
-
}
|
|
8895
|
-
} else if (typeof move === 'object' && move.from && move.to) {
|
|
8896
|
-
// Se sono id, converto in oggetti; se sono già oggetti, li uso direttamente
|
|
8897
|
-
fromSquareObj = typeof move.from === 'string' ? this.boardService.getSquare(move.from) : move.from;
|
|
8898
|
-
toSquareObj = typeof move.to === 'string' ? this.boardService.getSquare(move.to) : move.to;
|
|
8899
|
-
promotion = move.promotion;
|
|
8900
|
-
} else {
|
|
8901
|
-
throw new Error(`Invalid move: ${move}`);
|
|
8902
|
-
}
|
|
8903
|
-
|
|
8904
|
-
if (!fromSquareObj || !toSquareObj) {
|
|
8905
|
-
throw new Error(`Invalid squares: ${move.from || move.substring(0, 2)} or ${move.to || move.substring(2, 4)}`);
|
|
8906
|
-
}
|
|
8907
|
-
|
|
8908
|
-
// --- Internamente: lavora solo con oggetti ---
|
|
8909
|
-
const result = this._onMove(fromSquareObj, toSquareObj, promotion, animate);
|
|
8910
|
-
// Dopo ogni mossa, forza la sincronizzazione della board
|
|
8911
|
-
this._updateBoardPieces(true, false);
|
|
8912
|
-
return result;
|
|
8913
|
-
}
|
|
8914
|
-
|
|
8915
|
-
// Aliases for backward compatibility
|
|
8916
|
-
move(move, animate = true) {
|
|
8917
|
-
// On any new move, clear the redo stack
|
|
8918
|
-
this._undoneMoves = [];
|
|
8919
|
-
return this.movePiece(move, { animate });
|
|
8920
|
-
}
|
|
8921
|
-
get(square) { return this.getPiece(square); }
|
|
8922
|
-
piece(square) { return this.getPiece(square); }
|
|
8923
|
-
put(piece, square, opts = {}) { return this.putPiece(piece, square, opts); }
|
|
8924
|
-
remove(square, opts = {}) { return this.removePiece(square, opts); }
|
|
8925
|
-
load(position, opts = {}) { return this.setPosition(position, opts); }
|
|
8926
|
-
resize(size) { return this.resizeBoard(size); }
|
|
8927
|
-
start(opts = {}) { return this.reset(opts); }
|
|
8928
|
-
clearBoard(opts = {}) { return this.clear(opts); }
|
|
8929
|
-
};
|
|
8636
|
+
}
|
|
8930
8637
|
|
|
8931
8638
|
/**
|
|
8932
8639
|
* Structured logging system for Chessboard.js
|
|
@@ -9384,6 +9091,7 @@ class ChessboardFactory {
|
|
|
9384
9091
|
hints: true,
|
|
9385
9092
|
clickable: true,
|
|
9386
9093
|
moveHighlight: true,
|
|
9094
|
+
animationStyle: 'simultaneous'
|
|
9387
9095
|
});
|
|
9388
9096
|
|
|
9389
9097
|
// Tournament template
|
|
@@ -9394,6 +9102,7 @@ class ChessboardFactory {
|
|
|
9394
9102
|
clickable: true,
|
|
9395
9103
|
moveHighlight: true,
|
|
9396
9104
|
onlyLegalMoves: true,
|
|
9105
|
+
animationStyle: 'sequential'
|
|
9397
9106
|
});
|
|
9398
9107
|
|
|
9399
9108
|
// Analysis template
|
|
@@ -9404,6 +9113,7 @@ class ChessboardFactory {
|
|
|
9404
9113
|
clickable: true,
|
|
9405
9114
|
moveHighlight: true,
|
|
9406
9115
|
mode: 'analysis',
|
|
9116
|
+
animationStyle: 'simultaneous'
|
|
9407
9117
|
});
|
|
9408
9118
|
|
|
9409
9119
|
// Puzzle template
|
|
@@ -9414,6 +9124,7 @@ class ChessboardFactory {
|
|
|
9414
9124
|
clickable: true,
|
|
9415
9125
|
moveHighlight: true,
|
|
9416
9126
|
onlyLegalMoves: true,
|
|
9127
|
+
animationStyle: 'sequential'
|
|
9417
9128
|
});
|
|
9418
9129
|
|
|
9419
9130
|
// Demo template
|
|
@@ -9423,6 +9134,7 @@ class ChessboardFactory {
|
|
|
9423
9134
|
hints: false,
|
|
9424
9135
|
clickable: false,
|
|
9425
9136
|
moveHighlight: true,
|
|
9137
|
+
animationStyle: 'simultaneous'
|
|
9426
9138
|
});
|
|
9427
9139
|
}
|
|
9428
9140
|
|
|
@@ -9468,7 +9180,7 @@ class ChessboardFactory {
|
|
|
9468
9180
|
this.validationService.validateConfig(finalConfig);
|
|
9469
9181
|
|
|
9470
9182
|
// Create chessboard instance
|
|
9471
|
-
const chessboard = new Chessboard
|
|
9183
|
+
const chessboard = new Chessboard(finalConfig);
|
|
9472
9184
|
|
|
9473
9185
|
// Store instance for management
|
|
9474
9186
|
this.instances.set(containerId, {
|
|
@@ -9728,44 +9440,13 @@ function createChessboardFromTemplate(containerId, templateName, overrides = {})
|
|
|
9728
9440
|
*/
|
|
9729
9441
|
|
|
9730
9442
|
|
|
9731
|
-
/**
|
|
9732
|
-
* Main Chessboard factory function for backward compatibility
|
|
9733
|
-
* Supports both legacy and modern calling conventions
|
|
9734
|
-
* @param {string|Object} containerElm - Container element ID or configuration object
|
|
9735
|
-
* @param {Object} [config={}] - Configuration options (when first param is string)
|
|
9736
|
-
* @returns {ChessboardClass} Chessboard instance
|
|
9737
|
-
*/
|
|
9738
|
-
function Chessboard(containerElm, config = {}) {
|
|
9739
|
-
const factoryLogger = logger.child('ChessboardFactory');
|
|
9740
|
-
|
|
9741
|
-
try {
|
|
9742
|
-
// If first parameter is an object, treat it as config
|
|
9743
|
-
if (typeof containerElm === 'object' && containerElm !== null) {
|
|
9744
|
-
factoryLogger.debug('Creating chessboard with config object');
|
|
9745
|
-
return new Chessboard$1(containerElm);
|
|
9746
|
-
}
|
|
9747
|
-
|
|
9748
|
-
// Otherwise, treat first parameter as element ID
|
|
9749
|
-
if (typeof containerElm === 'string') {
|
|
9750
|
-
factoryLogger.debug('Creating chessboard with element ID', { elementId: containerElm });
|
|
9751
|
-
const fullConfig = { ...config, id: containerElm };
|
|
9752
|
-
return new Chessboard$1(fullConfig);
|
|
9753
|
-
}
|
|
9754
|
-
|
|
9755
|
-
throw new Error('Invalid parameters: first parameter must be string or object');
|
|
9756
|
-
} catch (error) {
|
|
9757
|
-
factoryLogger.error('Failed to create chessboard instance', { error });
|
|
9758
|
-
throw error;
|
|
9759
|
-
}
|
|
9760
|
-
}
|
|
9761
|
-
|
|
9762
9443
|
/**
|
|
9763
9444
|
* Wrapper class that handles both calling conventions
|
|
9764
9445
|
* Provides enhanced error handling and logging
|
|
9765
9446
|
* @class
|
|
9766
9447
|
* @extends ChessboardClass
|
|
9767
9448
|
*/
|
|
9768
|
-
class ChessboardWrapper extends Chessboard
|
|
9449
|
+
class ChessboardWrapper extends Chessboard {
|
|
9769
9450
|
/**
|
|
9770
9451
|
* Creates a new ChessboardWrapper instance
|
|
9771
9452
|
* @param {string|Object} containerElm - Container element ID or configuration object
|
|
@@ -9794,53 +9475,32 @@ class ChessboardWrapper extends Chessboard$1 {
|
|
|
9794
9475
|
}
|
|
9795
9476
|
}
|
|
9796
9477
|
|
|
9797
|
-
|
|
9798
|
-
|
|
9799
|
-
|
|
9800
|
-
|
|
9478
|
+
// Attach classes and utilities to the factory function for direct access
|
|
9479
|
+
Chessboard.Class = ChessboardWrapper;
|
|
9480
|
+
Chessboard.Chessboard = ChessboardWrapper;
|
|
9481
|
+
Chessboard.Config = ChessboardConfig;
|
|
9482
|
+
Chessboard.Factory = ChessboardFactory;
|
|
9801
9483
|
|
|
9802
|
-
//
|
|
9803
|
-
/**
|
|
9804
|
-
* Create a new Chessboard instance
|
|
9805
|
-
* @param {string|Object} containerElm
|
|
9806
|
-
* @param {Object} [config]
|
|
9807
|
-
* @returns {Chessboard}
|
|
9808
|
-
*/
|
|
9484
|
+
// Attach factory methods
|
|
9809
9485
|
Chessboard.create = createChessboard;
|
|
9810
|
-
|
|
9811
|
-
* Create a Chessboard from a template
|
|
9812
|
-
* @param {string|Object} containerElm
|
|
9813
|
-
* @param {string} templateName
|
|
9814
|
-
* @param {Object} [config]
|
|
9815
|
-
* @returns {Chessboard}
|
|
9816
|
-
*/
|
|
9817
|
-
Chessboard.fromTemplate = createChessboardFromTemplate;
|
|
9486
|
+
Chessboard.createFromTemplate = createChessboardFromTemplate;
|
|
9818
9487
|
Chessboard.factory = chessboardFactory;
|
|
9819
9488
|
|
|
9820
|
-
//
|
|
9489
|
+
// Static methods for instance management
|
|
9821
9490
|
Chessboard.getInstance = (containerId) => chessboardFactory.getInstance(containerId);
|
|
9822
9491
|
Chessboard.destroyInstance = (containerId) => chessboardFactory.destroy(containerId);
|
|
9823
9492
|
Chessboard.destroyAll = () => chessboardFactory.destroyAll();
|
|
9824
9493
|
Chessboard.listInstances = () => chessboardFactory.listInstances();
|
|
9825
9494
|
|
|
9826
|
-
//
|
|
9495
|
+
// Template management
|
|
9827
9496
|
Chessboard.registerTemplate = (name, config) => chessboardFactory.registerTemplate(name, config);
|
|
9828
9497
|
Chessboard.removeTemplate = (name) => chessboardFactory.removeTemplate(name);
|
|
9829
9498
|
Chessboard.getTemplate = (name) => chessboardFactory.getTemplate(name);
|
|
9830
9499
|
Chessboard.listTemplates = () => chessboardFactory.listTemplates();
|
|
9831
9500
|
|
|
9832
|
-
//
|
|
9501
|
+
// Statistics and debugging
|
|
9833
9502
|
Chessboard.getStats = () => chessboardFactory.getStats();
|
|
9834
9503
|
|
|
9835
|
-
// --- DEPRECATED/LEGACY ALIASES ---
|
|
9836
|
-
/**
|
|
9837
|
-
* @deprecated Use Chessboard.create instead
|
|
9838
|
-
*/
|
|
9839
|
-
Chessboard.Class = ChessboardWrapper;
|
|
9840
|
-
Chessboard.Chessboard = ChessboardWrapper;
|
|
9841
|
-
Chessboard.Config = ChessboardConfig;
|
|
9842
|
-
Chessboard.Factory = ChessboardFactory;
|
|
9843
|
-
|
|
9844
9504
|
/**
|
|
9845
9505
|
* Coordinate utilities for Chessboard.js
|
|
9846
9506
|
*/
|
|
@@ -10230,7 +9890,11 @@ function validateConfig(config) {
|
|
|
10230
9890
|
if (config.moveAnimation && !isValidEasing(config.moveAnimation)) {
|
|
10231
9891
|
errors.push('Invalid moveAnimation. Must be a valid easing function');
|
|
10232
9892
|
}
|
|
10233
|
-
|
|
9893
|
+
|
|
9894
|
+
if (config.animationStyle && !['sequential', 'simultaneous'].includes(config.animationStyle)) {
|
|
9895
|
+
errors.push('Invalid animationStyle. Must be "sequential" or "simultaneous"');
|
|
9896
|
+
}
|
|
9897
|
+
|
|
10234
9898
|
return {
|
|
10235
9899
|
success: errors.length === 0,
|
|
10236
9900
|
errors
|