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