@alepot55/chessboardjs 2.1.6 → 2.1.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.
@@ -2497,16 +2497,17 @@ var Chessboard = (function () {
2497
2497
  'invalid_hintColor': 'Invalid hintColor - ',
2498
2498
  }
2499
2499
 
2500
+ // -------------------
2501
+ // Initialization
2502
+ // -------------------
2500
2503
  constructor(config) {
2501
2504
  this.config = new ChessboardConfig(config);
2502
2505
  this.init();
2503
2506
  }
2504
2507
 
2505
- // Build
2506
-
2507
2508
  init() {
2508
2509
  this.initParams();
2509
- this.buildGame(this.config.position);
2510
+ this.setGame(this.config.position);
2510
2511
  this.buildBoard();
2511
2512
  this.buildSquares();
2512
2513
  this.addListeners();
@@ -2518,27 +2519,13 @@ var Chessboard = (function () {
2518
2519
  this.squares = {};
2519
2520
  this.promoting = false;
2520
2521
  this.clicked = null;
2521
- this.movesHistory = [];
2522
2522
  this.mosseIndietro = [];
2523
2523
  this.clicked = null;
2524
2524
  }
2525
2525
 
2526
- buildGame(position) {
2527
- if (typeof position === 'object') {
2528
- this.game = new Chess('start');
2529
- Object.entries(position).forEach(([square, [type, color]]) => {
2530
- this.game.put({ type, color }, square);
2531
- });
2532
- } else if (Object.values(this.standard_positions).includes(position)) {
2533
- if (position === 'start') this.game = new Chess();
2534
- else this.game = new Chess(this.standard_positions[position]);
2535
- } else if (validateFen(position)) {
2536
- this.game = new Chess(position);
2537
- } else {
2538
- throw new Error(this.error_messages['invalid_position'] + position);
2539
- }
2540
- }
2541
-
2526
+ // -------------------
2527
+ // Board Setup
2528
+ // -------------------
2542
2529
  buildBoard() {
2543
2530
  this.board = document.getElementById(this.config.id_div);
2544
2531
  if (!this.board) {
@@ -2548,12 +2535,6 @@ var Chessboard = (function () {
2548
2535
  this.board.className = "board";
2549
2536
  }
2550
2537
 
2551
- realCoord(row, col) {
2552
- if (this.isWhiteOriented()) row = 7 - row;
2553
- else col = 7 - col;
2554
- return [row + 1, col + 1];
2555
- }
2556
-
2557
2538
  buildSquares() {
2558
2539
 
2559
2540
  for (let row = 0; row < 8; row++) {
@@ -2573,8 +2554,79 @@ var Chessboard = (function () {
2573
2554
  this.board.innerHTML = '';
2574
2555
  }
2575
2556
 
2576
- // Pieces
2557
+ removeSquares() {
2558
+ for (const square of Object.values(this.squares)) {
2559
+ this.board.removeChild(square.element);
2560
+ square.destroy();
2561
+
2562
+ }
2563
+ this.squares = {};
2564
+ }
2565
+
2566
+ resize(value) {
2567
+ if (value === 'auto') {
2568
+ let size;
2569
+ if (this.board.offsetWidth === 0) {
2570
+ size = this.board.offsetHeight;
2571
+ } else if (this.board.offsetHeight === 0) {
2572
+ size = this.board.offsetWidth;
2573
+ } else {
2574
+ size = Math.min(this.board.offsetWidth, this.board.offsetHeight);
2575
+ }
2576
+ this.resize(size);
2577
+ } else if (typeof value !== 'number') {
2578
+ throw new Error(this.error_messages['invalid_value'] + value);
2579
+ } else {
2580
+ document.documentElement.style.setProperty('--dimBoard', value + 'px');
2581
+ this.updateBoardPieces();
2582
+ }
2583
+ }
2584
+
2585
+ // -------------------
2586
+ // Game/Position Functions
2587
+ // -------------------
2588
+ convertFen(position) {
2589
+ if (typeof position === 'string') {
2590
+ if (this.validateFen(position)) return position;
2591
+ else if (this.standard_positions[position]) return this.standard_positions[position];
2592
+ else throw new Error('Invalid position -' + position);
2593
+ } else if (typeof position === 'object') {
2594
+ let parts = [];
2595
+ for (let row = 0; row < 8; row++) {
2596
+ let rowParts = [];
2597
+ let empty = 0;
2598
+ for (let col = 0; col < 8; col++) {
2599
+ let square = this.getSquareID(row, col);
2600
+ let piece = position[square];
2601
+ if (piece) {
2602
+ if (empty > 0) {
2603
+ rowParts.push(empty);
2604
+ empty = 0;
2605
+ }
2606
+ // Convert piece notation: white pieces become uppercase, black remain lowercase.
2607
+ let fenPiece = piece[1] === 'w' ? piece[0].toUpperCase() : piece[0].toLowerCase();
2608
+ rowParts.push(fenPiece);
2609
+ } else {
2610
+ empty++;
2611
+ }
2612
+ }
2613
+ if (empty > 0) rowParts.push(empty);
2614
+ parts.push(rowParts.join(''));
2615
+ }
2616
+ return parts.join('/');
2617
+ } else {
2618
+ throw new Error('Invalid position -' + position);
2619
+ }
2620
+ }
2621
+
2622
+ setGame(position) {
2623
+ const fen = this.convertFen(position);
2624
+ this.game = new Chess(fen);
2625
+ }
2577
2626
 
2627
+ // -------------------
2628
+ // Piece Functions
2629
+ // -------------------
2578
2630
  getPiecePath(piece) {
2579
2631
  if (typeof this.config.piecesPath === 'string')
2580
2632
  return this.config.piecesPath + '/' + piece + '.svg';
@@ -2586,41 +2638,27 @@ var Chessboard = (function () {
2586
2638
  throw new Error(this.error_messages['invalid_piecesPath']);
2587
2639
  }
2588
2640
 
2589
- colorPiece(square) {
2590
- let piece = this.piece(square);
2591
- return piece ? piece[1] : null;
2592
- }
2593
-
2594
- movePiece(piece, to, duration, callback) {
2595
- piece.translate(to, duration, this.transitionTimingFunction, this.config.moveAnimation, callback);
2641
+ convertPiece(piece) {
2642
+ if (piece instanceof Piece) return piece;
2643
+ if (typeof piece === 'string') {
2644
+ let [type, color] = piece.split('');
2645
+ return new Piece(color, type, this.getPiecePath(piece));
2646
+ }
2647
+ throw new Error(this.error_messages['invalid_piece'] + piece);
2596
2648
  }
2597
2649
 
2598
- translatePiece(move, removeTo, animate, callback = null) {
2599
-
2600
- if (removeTo) this.removePieceFromSquare(move.to, false);
2601
-
2602
- let change_square = () => {
2603
- move.from.removePiece();
2604
- move.to.putPiece(move.piece);
2605
- move.piece.setDrag(this.dragFunction(move.to, move.piece));
2606
- if (callback) callback();
2607
- };
2608
-
2609
- let duration = animate ? this.config.moveTime : 0;
2610
-
2611
- this.movePiece(move.piece, move.to, duration, change_square);
2650
+ addPieceOnSquare(square, piece, fade = true) {
2612
2651
 
2613
- }
2652
+ square.putPiece(piece);
2653
+ piece.setDrag(this.dragFunction(square, piece));
2614
2654
 
2615
- snapbackPiece(square, animate) {
2616
- let move = new Move(square, square);
2617
- this.translatePiece(move, false, animate);
2618
- }
2655
+ if (fade) piece.fadeIn(
2656
+ this.config.fadeTime,
2657
+ this.config.fadeAnimation,
2658
+ this.transitionTimingFunction
2659
+ );
2619
2660
 
2620
- convertSquare(square) {
2621
- if (square instanceof Square) return square;
2622
- if (typeof square === 'string' && this.squares[square]) return this.squares[square];
2623
- throw new Error('Invalid square value');
2661
+ piece.visible();
2624
2662
  }
2625
2663
 
2626
2664
  removePieceFromSquare(square, fade = true) {
@@ -2642,110 +2680,35 @@ var Chessboard = (function () {
2642
2680
  return piece;
2643
2681
  }
2644
2682
 
2645
- dragFunction(square, piece) {
2646
-
2647
- return (event) => {
2648
-
2649
- event.preventDefault();
2650
-
2651
- if (!this.config.draggable || !piece) return;
2652
- if (!this.config.onDragStart(square, piece)) return;
2653
-
2654
- let prec;
2655
- let from = square;
2656
- let to = square;
2657
-
2658
- const img = piece.element;
2659
-
2660
- if (!this.canMove(from)) return;
2661
- if (!this.config.clickable) this.clicked = null;
2662
- if (this.onClick(from)) return;
2663
-
2664
- img.style.position = 'absolute';
2665
- img.style.zIndex = 100;
2666
-
2667
- const moveAt = (pageX, pageY) => {
2668
- const halfWidth = img.offsetWidth / 2;
2669
- const halfHeight = img.offsetHeight / 2;
2670
- img.style.left = `${pageX - halfWidth}px`;
2671
- img.style.top = `${pageY - halfHeight}px`;
2672
- return true;
2673
- };
2674
-
2675
- const onMouseMove = (event) => {
2676
- if (!moveAt(event.pageX, event.pageY)) ;
2677
-
2678
- const boardRect = this.board.getBoundingClientRect();
2679
- const { offsetWidth: boardWidth, offsetHeight: boardHeight } = this.board;
2680
- const x = event.clientX - boardRect.left;
2681
- const y = event.clientY - boardRect.top;
2682
-
2683
- let newTo = null;
2684
- if (x >= 0 && x <= boardWidth && y >= 0 && y <= boardHeight) {
2685
- const col = Math.floor(x / (boardWidth / 8));
2686
- const row = Math.floor(y / (boardHeight / 8));
2687
- newTo = this.squares[this.getSquareID(row, col)];
2688
- }
2689
-
2690
- to = newTo;
2691
- this.config.onDragMove(from, to, piece);
2683
+ movePiece(piece, to, duration, callback) {
2684
+ piece.translate(to, duration, this.transitionTimingFunction, this.config.moveAnimation, callback);
2685
+ }
2692
2686
 
2693
- if (to !== prec) {
2694
- to?.highlight();
2695
- prec?.dehighlight();
2696
- prec = to;
2697
- }
2698
- };
2687
+ translatePiece(move, removeTo, animate, callback = null) {
2699
2688
 
2700
- const onMouseUp = () => {
2701
- prec?.dehighlight();
2702
- document.removeEventListener('mousemove', onMouseMove);
2703
- window.removeEventListener('mouseup', onMouseUp);
2704
- img.style.zIndex = 20;
2689
+ if (removeTo) this.removePieceFromSquare(move.to, false);
2705
2690
 
2706
- const dropResult = this.config.onDrop(from, to, piece);
2707
- const isTrashDrop = !to && (this.config.dropOffBoard === 'trash' || dropResult === 'trash');
2691
+ let change_square = () => {
2692
+ move.from.removePiece();
2693
+ move.to.putPiece(move.piece);
2694
+ move.piece.setDrag(this.dragFunction(move.to, move.piece));
2695
+ if (callback) callback();
2696
+ };
2708
2697
 
2709
- if (isTrashDrop) {
2710
- this.allSquares("unmoved");
2711
- this.allSquares('removeHint');
2712
- from.deselect();
2713
- this.remove(from);
2714
- } else if (!to || !this.onClick(to, true)) {
2715
- this.snapbackPiece(from, !this.promoting);
2716
- this.config.onSnapbackEnd(from, piece);
2717
- }
2718
- };
2698
+ let duration = animate ? this.config.moveTime : 0;
2719
2699
 
2720
- window.addEventListener('mouseup', onMouseUp, { once: true });
2721
- document.addEventListener('mousemove', onMouseMove);
2722
- img.addEventListener('mouseup', onMouseUp, { once: true });
2723
- }
2724
- }
2700
+ this.movePiece(move.piece, move.to, duration, change_square);
2725
2701
 
2726
- convertPiece(piece) {
2727
- if (piece instanceof Piece) return piece;
2728
- if (typeof piece === 'string') {
2729
- let [type, color] = piece.split('');
2730
- return new Piece(color, type, this.getPiecePath(piece));
2731
- }
2732
- throw new Error(this.error_messages['invalid_piece'] + piece);
2733
2702
  }
2734
2703
 
2735
- addPieceOnSquare(square, piece, fade = true) {
2736
-
2737
- square.putPiece(piece);
2738
- piece.setDrag(this.dragFunction(square, piece));
2739
-
2740
- if (fade) piece.fadeIn(
2741
- this.config.fadeTime,
2742
- this.config.fadeAnimation,
2743
- this.transitionTimingFunction
2744
- );
2745
-
2746
- piece.visible();
2704
+ snapbackPiece(square, animate) {
2705
+ let move = new Move(square, square);
2706
+ this.translatePiece(move, false, animate);
2747
2707
  }
2748
2708
 
2709
+ // -------------------
2710
+ // Board Update Functions
2711
+ // -------------------
2749
2712
  updateBoardPieces(animation = false) {
2750
2713
  let { updatedFlags, escapeFlags, movableFlags, pendingTranslations } = this.prepareBoardUpdateData();
2751
2714
 
@@ -2765,9 +2728,9 @@ var Chessboard = (function () {
2765
2728
  for (let squareId in this.squares) {
2766
2729
  let cellPiece = this.squares[squareId].piece;
2767
2730
  let cellPieceId = cellPiece ? cellPiece.getId() : null;
2768
- updatedFlags[squareId] = this.piece(squareId) === cellPieceId;
2731
+ updatedFlags[squareId] = this.getGamePieceId(squareId) === cellPieceId;
2769
2732
  escapeFlags[squareId] = false;
2770
- movableFlags[squareId] = cellPiece ? this.piece(squareId) !== cellPieceId : false;
2733
+ movableFlags[squareId] = cellPiece ? this.getGamePieceId(squareId) !== cellPieceId : false;
2771
2734
  }
2772
2735
 
2773
2736
  return { updatedFlags, escapeFlags, movableFlags, pendingTranslations };
@@ -2775,7 +2738,7 @@ var Chessboard = (function () {
2775
2738
 
2776
2739
  identifyPieceTranslations(updatedFlags, escapeFlags, movableFlags, pendingTranslations) {
2777
2740
  Object.values(this.squares).forEach(targetSquare => {
2778
- const newPieceId = this.piece(targetSquare.id);
2741
+ const newPieceId = this.getGamePieceId(targetSquare.id);
2779
2742
  const newPiece = newPieceId && this.convertPiece(newPieceId);
2780
2743
  const currentPiece = targetSquare.piece;
2781
2744
  const currentPieceId = currentPiece ? currentPiece.getId() : null;
@@ -2820,7 +2783,7 @@ var Chessboard = (function () {
2820
2783
 
2821
2784
  pendingTranslations.push([currentSource, sourceSquare, targetSquare]);
2822
2785
 
2823
- if (!this.piece(sourceSquare.id)) updatedFlags[sourceSquare.id] = true;
2786
+ if (!this.getGamePieceId(sourceSquare.id)) updatedFlags[sourceSquare.id] = true;
2824
2787
 
2825
2788
  escapeFlags[sourceSquare.id] = true;
2826
2789
  movableFlags[sourceSquare.id] = false;
@@ -2838,7 +2801,7 @@ var Chessboard = (function () {
2838
2801
  // Gestisce gli aggiornamenti residui per ogni cella che non è ancora stata correttamente aggiornata
2839
2802
  processRemainingPieceUpdates(updatedFlags, animation) {
2840
2803
  for (const square of Object.values(this.squares)) {
2841
- let newPieceId = this.piece(square.id);
2804
+ let newPieceId = this.getGamePieceId(square.id);
2842
2805
  let newPiece = newPieceId ? this.convertPiece(newPieceId) : null;
2843
2806
  let currentPiece = square.piece;
2844
2807
  let currentPieceId = currentPiece ? currentPiece.getId() : null;
@@ -2853,9 +2816,11 @@ var Chessboard = (function () {
2853
2816
  updateSinglePiece(square, newPiece, updatedFlags, animation) {
2854
2817
  if (!updatedFlags[square.id]) {
2855
2818
  let lastMove = this.lastMove();
2819
+ console.log(lastMove);
2856
2820
 
2857
2821
  if (lastMove?.promotion) {
2858
2822
  if (lastMove['to'] === square.id) {
2823
+ console.log('Promotion detected');
2859
2824
 
2860
2825
  let move = new Move(this.squares[lastMove['from']], square);
2861
2826
  this.translatePiece(move, true, animation
@@ -2871,47 +2836,127 @@ var Chessboard = (function () {
2871
2836
  }
2872
2837
  }
2873
2838
 
2874
- isPiece(piece, square) { return this.piece(square) === piece }
2875
-
2876
- // Listeners
2839
+ // -------------------
2840
+ // Event Handlers and Drag
2841
+ // -------------------
2842
+ dragFunction(square, piece) {
2877
2843
 
2878
- addListeners() {
2879
- for (const square of Object.values(this.squares)) {
2844
+ return (event) => {
2880
2845
 
2881
- let piece = square.piece;
2846
+ event.preventDefault();
2882
2847
 
2883
- square.element.addEventListener("mouseover", (e) => {
2884
- if (!this.clicked) this.hintMoves(square);
2885
- });
2886
- square.element.addEventListener("mouseout", (e) => {
2887
- if (!this.clicked) this.dehintMoves(square);
2888
- });
2848
+ if (!this.config.draggable || !piece) return;
2849
+ if (!this.config.onDragStart(square, piece)) return;
2889
2850
 
2890
- const handleClick = (e) => {
2891
- e.stopPropagation();
2892
- if (this.config.clickable && (!piece || this.config.onlyLegalMoves)) this.onClick(square);
2893
- };
2851
+ let prec;
2852
+ let from = square;
2853
+ let to = square;
2894
2854
 
2895
- square.element.addEventListener("click", handleClick);
2896
- square.element.addEventListener("touch", handleClick);
2897
- }
2898
- }
2855
+ const img = piece.element;
2899
2856
 
2900
- onClick(square, animation = this.config.moveAnimation) {
2857
+ if (!this.canMove(from)) return;
2858
+ if (!this.config.clickable) this.clicked = null;
2859
+ if (this.onClick(from)) return;
2901
2860
 
2902
- if (square.id === this.clicked?.id) return false;
2861
+ img.style.position = 'absolute';
2862
+ img.style.zIndex = 100;
2903
2863
 
2904
- let from = this.clicked;
2905
- this.clicked = null;
2864
+ const moveAt = (pageX, pageY) => {
2865
+ const halfWidth = img.offsetWidth / 2;
2866
+ const halfHeight = img.offsetHeight / 2;
2867
+ img.style.left = `${pageX - halfWidth}px`;
2868
+ img.style.top = `${pageY - halfHeight}px`;
2869
+ return true;
2870
+ };
2906
2871
 
2907
- let promotion = null;
2872
+ const onMouseMove = (event) => {
2873
+ if (!moveAt(event.pageX, event.pageY)) ;
2908
2874
 
2909
- if (this.promoting) {
2910
- if (this.promoting === 'none') from = null;
2911
- else promotion = this.promoting;
2875
+ const boardRect = this.board.getBoundingClientRect();
2876
+ const { offsetWidth: boardWidth, offsetHeight: boardHeight } = this.board;
2877
+ const x = event.clientX - boardRect.left;
2878
+ const y = event.clientY - boardRect.top;
2912
2879
 
2913
- this.promoting = false;
2914
- this.allSquares("removePromotion");
2880
+ let newTo = null;
2881
+ if (x >= 0 && x <= boardWidth && y >= 0 && y <= boardHeight) {
2882
+ const col = Math.floor(x / (boardWidth / 8));
2883
+ const row = Math.floor(y / (boardHeight / 8));
2884
+ newTo = this.squares[this.getSquareID(row, col)];
2885
+ }
2886
+
2887
+ to = newTo;
2888
+ this.config.onDragMove(from, to, piece);
2889
+
2890
+ if (to !== prec) {
2891
+ to?.highlight();
2892
+ prec?.dehighlight();
2893
+ prec = to;
2894
+ }
2895
+ };
2896
+
2897
+ const onMouseUp = () => {
2898
+ prec?.dehighlight();
2899
+ document.removeEventListener('mousemove', onMouseMove);
2900
+ window.removeEventListener('mouseup', onMouseUp);
2901
+ img.style.zIndex = 20;
2902
+
2903
+ const dropResult = this.config.onDrop(from, to, piece);
2904
+ const isTrashDrop = !to && (this.config.dropOffBoard === 'trash' || dropResult === 'trash');
2905
+
2906
+ if (isTrashDrop) {
2907
+ this.allSquares("unmoved");
2908
+ this.allSquares('removeHint');
2909
+ from.deselect();
2910
+ this.remove(from);
2911
+ } else if (!to || !this.onClick(to, true)) {
2912
+ this.snapbackPiece(from, !this.promoting);
2913
+ this.config.onSnapbackEnd(from, piece);
2914
+ }
2915
+ };
2916
+
2917
+ window.addEventListener('mouseup', onMouseUp, { once: true });
2918
+ document.addEventListener('mousemove', onMouseMove);
2919
+ img.addEventListener('mouseup', onMouseUp, { once: true });
2920
+ }
2921
+ }
2922
+
2923
+ addListeners() {
2924
+ for (const square of Object.values(this.squares)) {
2925
+
2926
+ let piece = square.piece;
2927
+
2928
+ square.element.addEventListener("mouseover", (e) => {
2929
+ if (!this.clicked) this.hintMoves(square);
2930
+ });
2931
+ square.element.addEventListener("mouseout", (e) => {
2932
+ if (!this.clicked) this.dehintMoves(square);
2933
+ });
2934
+
2935
+ const handleClick = (e) => {
2936
+ e.stopPropagation();
2937
+ if (this.config.clickable && (!piece || this.config.onlyLegalMoves)) this.onClick(square);
2938
+ };
2939
+
2940
+ square.element.addEventListener("click", handleClick);
2941
+ square.element.addEventListener("touch", handleClick);
2942
+ }
2943
+ }
2944
+
2945
+ onClick(square, animation = this.config.moveAnimation) {
2946
+
2947
+ if (square.id === this.clicked?.id) return false;
2948
+
2949
+ let from = this.clicked;
2950
+ this.clicked = null;
2951
+
2952
+ let promotion = null;
2953
+
2954
+ if (this.promoting) {
2955
+ if (this.promoting === 'none') from = null;
2956
+ else promotion = this.promoting;
2957
+
2958
+ this.promoting = false;
2959
+ this.allSquares("removePromotion");
2915
2960
  this.allSquares("removeCover");
2916
2961
  }
2917
2962
 
@@ -2945,31 +2990,9 @@ var Chessboard = (function () {
2945
2990
  return false;
2946
2991
  }
2947
2992
 
2948
- // Hint
2949
-
2950
- hint(square) {
2951
- if (!this.config.hints || !this.squares[square]) return;
2952
- this.squares[square].putHint(this.colorPiece(square) && this.colorPiece(square) !== this.turn());
2953
- }
2954
-
2955
- hintMoves(square) {
2956
- if (!this.canMove(square)) return;
2957
- let mosse = this.game.moves({ square: square.id, verbose: true });
2958
- for (let mossa of mosse) {
2959
- if (mossa['to'].length === 2) this.hint(mossa['to']);
2960
- }
2961
- }
2962
-
2963
- dehintMoves(square) {
2964
- let mosse = this.game.moves({ square: square.id, verbose: true });
2965
- for (let mossa of mosse) {
2966
- let to = this.squares[mossa['to']];
2967
- to.removeHint();
2968
- }
2969
- }
2970
-
2971
- // Moves
2972
-
2993
+ // -------------------
2994
+ // Move Functions
2995
+ // -------------------
2973
2996
  canMove(square) {
2974
2997
  if (!square.piece) return false;
2975
2998
  if (this.config.movableColors === 'none') return false;
@@ -2990,13 +3013,6 @@ var Chessboard = (function () {
2990
3013
  throw new Error("Invalid move format");
2991
3014
  }
2992
3015
 
2993
- allSquares(method) {
2994
- for (const square of Object.values(this.squares)) {
2995
- square[method]();
2996
- this.squares[square.id] = square;
2997
- }
2998
- }
2999
-
3000
3016
  legalMove(move) {
3001
3017
  let legal_moves = this.legalMoves(move.from.id);
3002
3018
 
@@ -3014,50 +3030,72 @@ var Chessboard = (function () {
3014
3030
  return this.game.moves({ verbose: verb });
3015
3031
  }
3016
3032
 
3017
- // Position
3033
+ move(move, animation) {
3034
+ move = this.convertMove(move);
3035
+ move.check();
3018
3036
 
3019
- chageFenTurn(fen, color) {
3020
- let parts = fen.split(' ');
3021
- parts[1] = color;
3022
- return parts.join(' ');
3023
- }
3037
+ let from = move.from;
3038
+ let to = move.to;
3024
3039
 
3025
- changeFenColor(fen) {
3026
- let parts = fen.split(' ');
3027
- parts[1] = parts[1] === 'w' ? 'b' : 'w';
3028
- return parts.join(' ');
3029
- }
3040
+ if (!this.config.onlyLegalMoves) {
3041
+ let piece = this.getGamePieceId(from.id);
3042
+ this.game.remove(from.id);
3043
+ this.game.remove(to.id);
3044
+ this.game.put({ type: move.hasPromotion() ? move.promotion : piece[0], color: piece[1] }, to.id);
3045
+ this.updateBoardPieces(animation);
3046
+ } else {
3047
+ this.allSquares("unmoved");
3048
+
3049
+ move = this.game.move({
3050
+ from: from.id,
3051
+ to: to.id,
3052
+ promotion: move.hasPromotion() ? move.promotion : undefined
3053
+ });
3054
+
3055
+ if (move === null) {
3056
+ throw new Error("Invalid move: move could not be executed");
3057
+ }
3030
3058
 
3031
- playerTurn() {
3032
- return this.getOrientation() == this.game.turn()
3059
+ this.updateBoardPieces(animation);
3060
+
3061
+ from.moved();
3062
+ to.moved();
3063
+ this.allSquares("removeHint");
3064
+
3065
+ this.config.onMoveEnd(move);
3066
+ }
3033
3067
  }
3034
3068
 
3035
- isWhiteOriented() { return this.config.orientation === 'w' }
3069
+ // -------------------
3070
+ // Miscellaneous Functions
3071
+ // -------------------
3072
+ hint(squareId) {
3073
+ let square = this.squares[squareId];
3074
+ if (!this.config.hints || !square) return;
3075
+ square.putHint(square.piece && square.piece.color !== this.turn());
3076
+ }
3036
3077
 
3037
- // Squares
3078
+ hintMoves(square) {
3079
+ if (!this.canMove(square)) return;
3080
+ let mosse = this.game.moves({ square: square.id, verbose: true });
3081
+ for (let mossa of mosse) {
3082
+ if (mossa['to'].length === 2) this.hint(mossa['to']);
3083
+ }
3084
+ }
3038
3085
 
3039
- getSquareID(row, col) {
3040
- row = parseInt(row);
3041
- col = parseInt(col);
3042
- if (this.isWhiteOriented()) {
3043
- row = 8 - row;
3044
- col = col + 1;
3045
- } else {
3046
- row = row + 1;
3047
- col = 8 - col;
3086
+ dehintMoves(square) {
3087
+ let mosse = this.game.moves({ square: square.id, verbose: true });
3088
+ for (let mossa of mosse) {
3089
+ let to = this.squares[mossa['to']];
3090
+ to.removeHint();
3048
3091
  }
3049
- let letters = 'abcdefgh';
3050
- let letter = letters[col - 1];
3051
- return letter + row;
3052
3092
  }
3053
3093
 
3054
- removeSquares() {
3094
+ allSquares(method) {
3055
3095
  for (const square of Object.values(this.squares)) {
3056
- this.board.removeChild(square.element);
3057
- square.destroy();
3058
-
3096
+ square[method]();
3097
+ this.squares[square.id] = square;
3059
3098
  }
3060
- this.squares = {};
3061
3099
  }
3062
3100
 
3063
3101
  promote(move) {
@@ -3115,189 +3153,248 @@ var Chessboard = (function () {
3115
3153
  }
3116
3154
  }
3117
3155
 
3118
- // user
3119
-
3120
- turn() {
3121
- return this.game.turn();
3156
+ clearSquares() {
3157
+ this.allSquares('removeHint');
3158
+ this.allSquares("deselect");
3159
+ this.allSquares("unmoved");
3122
3160
  }
3123
3161
 
3124
- getOrientation() {
3125
- return this.config.orientation;
3162
+ getGamePieceId(squareId) {
3163
+ let piece = this.game.get(squareId);
3164
+ return piece ? piece['type'] + piece['color'] : null;
3126
3165
  }
3127
3166
 
3128
- fen() {
3129
- return this.game.fen();
3130
- }
3167
+ isPiece(piece, square) { return this.getGamePieceId(square) === piece }
3131
3168
 
3132
- lastMove() {
3133
- return this.movesHistory[this.movesHistory.length - 1];
3169
+ realCoord(row, col) {
3170
+ if (this.isWhiteOriented()) row = 7 - row;
3171
+ else col = 7 - col;
3172
+ return [row + 1, col + 1];
3134
3173
  }
3135
3174
 
3136
- get history() {
3137
- return this.movesHistory;
3175
+ getSquareID(row, col) {
3176
+ row = parseInt(row);
3177
+ col = parseInt(col);
3178
+ if (this.isWhiteOriented()) {
3179
+ row = 8 - row;
3180
+ col = col + 1;
3181
+ } else {
3182
+ row = row + 1;
3183
+ col = 8 - col;
3184
+ }
3185
+ let letters = 'abcdefgh';
3186
+ let letter = letters[col - 1];
3187
+ return letter + row;
3138
3188
  }
3139
3189
 
3140
- history() {
3141
- return this.movesHistory;
3190
+ convertSquare(square) {
3191
+ if (square instanceof Square) return square;
3192
+ if (typeof square === 'string' && this.squares[square]) return this.squares[square];
3193
+ throw new Error(this.error_messages['invalid_square'] + square);
3142
3194
  }
3143
3195
 
3144
- get(square) {
3145
- square = this.convertSquare(square);
3146
- square.check();
3147
- let piece = square.piece;
3148
- return piece ? piece.id : null;
3196
+ // -------------------
3197
+ // User API and Chess.js Integration
3198
+ // -------------------
3199
+ getOrientation() {
3200
+ return this.config.orientation;
3149
3201
  }
3150
3202
 
3151
- position(position, color = null) {
3152
- this.allSquares('removeHint');
3153
- this.allSquares("deselect");
3154
- this.allSquares("unmoved");
3155
- if (color && color !== this.config.orientation) {
3156
- position = this.changeFenColor(position);
3203
+ setOrientation(color, animation = true) {
3204
+ if (!['w', 'b'].includes(color)) {
3157
3205
  this.config.orientation = color;
3158
- this.destroy();
3159
- this.init();
3206
+ this.flip(animation);
3160
3207
  } else {
3161
- this.buildGame(this.config.position);
3162
- this.updateBoardPieces();
3208
+ throw new Error(this.error_messages['invalid_orientation'] + color);
3163
3209
  }
3164
3210
  }
3165
3211
 
3166
- flip() {
3167
- let position = this.game.fen();
3168
- this.position(position, this.config.orientation === 'w' ? 'b' : 'w');
3212
+ lastMove() {
3213
+ const moves = this.history({ verbose: true });
3214
+ return moves[moves.length - 1];
3215
+ }
3216
+
3217
+ flip(animation = true) {
3218
+ this.clearSquares();
3219
+ this.allSquares('opposite');
3220
+ this.updateBoardPieces(animation);
3169
3221
  }
3170
3222
 
3171
3223
  build() {
3172
- if (this.board) this.destroy();
3224
+ if (this.board) throw new Error('Board already built');
3173
3225
  this.init();
3174
3226
  }
3175
3227
 
3176
- move(move, animation) {
3177
- move = this.convertMove(move);
3178
- move.check();
3228
+ ascii() {
3229
+ return this.game.ascii();
3230
+ }
3179
3231
 
3180
- let from = move.from;
3181
- let to = move.to;
3232
+ board() {
3233
+ return this.game.board();
3234
+ }
3182
3235
 
3183
- if (!this.config.onlyLegalMoves) {
3184
- let piece = this.piece(from.id);
3185
- this.game.remove(from.id);
3186
- this.game.remove(to.id);
3187
- this.game.put({ type: move.hasPromotion() ? move.promotion : piece[0], color: piece[1] }, to.id);
3188
- this.updateBoardPieces(animation);
3189
- } else {
3190
- this.allSquares("unmoved");
3236
+ clear(options = {}, animation = true) {
3237
+ this.game.clear(options);
3238
+ this.updateBoardPieces(animation);
3239
+ }
3191
3240
 
3192
- move = this.game.move({
3193
- from: from.id,
3194
- to: to.id,
3195
- promotion: move.hasPromotion() ? move.promotion : undefined
3196
- });
3241
+ fen() {
3242
+ return this.game.fen();
3243
+ }
3197
3244
 
3198
- if (move === null) {
3199
- throw new Error("Invalid move: move could not be executed");
3200
- }
3245
+ get(squareId) {
3246
+ const square = this.convertSquare(squareId);
3247
+ square.check();
3248
+ return square.piece;
3249
+ }
3201
3250
 
3202
- this.movesHistory.push(move);
3251
+ getCastlingRights(color) {
3252
+ return this.game.getCastlingRights(color);
3253
+ }
3203
3254
 
3204
- this.updateBoardPieces(animation);
3255
+ getComment() {
3256
+ return this.game.getComment();
3257
+ }
3205
3258
 
3206
- from.moved();
3207
- to.moved();
3208
- this.allSquares("removeHint");
3259
+ getComments() {
3260
+ return this.game.getComments();
3261
+ }
3209
3262
 
3210
- this.config.onMoveEnd(move);
3211
- }
3263
+ history(options = {}) {
3264
+ return this.game.history(options);
3212
3265
  }
3213
3266
 
3214
- clear(animation = true) {
3215
- this.game.clear();
3267
+ isCheckmate() {
3268
+ return this.game.isCheckmate();
3269
+ }
3270
+
3271
+ isDraw() {
3272
+ return this.game.isDraw();
3273
+ }
3274
+
3275
+ isDrawByFiftyMoves() {
3276
+ return this.game.isDrawByFiftyMoves();
3277
+ }
3278
+
3279
+ isInsufficientMaterial() {
3280
+ return this.game.isInsufficientMaterial();
3281
+ }
3282
+
3283
+ isGameOver() {
3284
+ return this.game.isGameOver();
3285
+ }
3286
+
3287
+ isStalemate() {
3288
+ return this.game.isStalemate();
3289
+ }
3290
+
3291
+ isThreefoldRepetition() {
3292
+ return this.game.isThreefoldRepetition();
3293
+ }
3294
+
3295
+ load(fen, options = {}, animation = true) {
3296
+ this.clearSquares();
3297
+ this.game.load(fen, options);
3216
3298
  this.updateBoardPieces(animation);
3217
3299
  }
3218
3300
 
3219
- insert(square, piece) {
3220
- square = this.convertSquare(square);
3221
- piece = this.convertPiece(piece);
3222
- square.check();
3223
- piece.check();
3224
- if (square.piece) this.remove(square);
3225
- this.game.put({ type: piece.type, color: piece.color }, square.id);
3301
+ loadPgn(pgn, options = {}, animation = true) {
3302
+ this.clearSquares();
3303
+ this.game.loadPgn(pgn, options);
3226
3304
  this.updateBoardPieces();
3227
3305
  }
3228
3306
 
3229
- isGameOver() {
3230
- if (this.game.isGameOver()) {
3231
- if (this.game.inCheck()) return this.game.turn() === 'w' ? 'b' : 'w';
3232
- return 'd';
3233
- }
3234
- return null;
3307
+ moveNumber() {
3308
+ return this.game.moveNumber();
3235
3309
  }
3236
3310
 
3237
- orientation(color) {
3238
- if ((color === 'w' || color === 'b') && color !== this.config.orientation) this.flip();
3311
+ moves(options = {}) {
3312
+ return this.game.moves(options);
3239
3313
  }
3240
3314
 
3241
- resize(value) {
3242
- if (value === 'auto') {
3243
- let size;
3244
- if (this.board.offsetWidth === 0) {
3245
- size = this.board.offsetHeight;
3246
- } else if (this.board.offsetHeight === 0) {
3247
- size = this.board.offsetWidth;
3248
- } else {
3249
- size = Math.min(this.board.offsetWidth, this.board.offsetHeight);
3250
- }
3251
- this.resize(size);
3252
- } else if (typeof value !== 'number') {
3253
- throw new Error(this.error_messages['invalid_value'] + value);
3254
- } else {
3255
- document.documentElement.style.setProperty('--dimBoard', value + 'px');
3256
- this.updateBoardPieces();
3257
- }
3315
+ pgn(options = {}) {
3316
+ return this.game.pgn(options);
3258
3317
  }
3259
3318
 
3260
- destroy() {
3261
- this.removeSquares();
3262
- this.removeBoard();
3263
- this.game = null;
3264
- this.clicked = null;
3265
- this.movesHistory = [];
3266
- this.mosseIndietro = [];
3267
- this.clicked = null;
3268
- this.board = null;
3319
+ put(pieceId, squareId, animation = true) {
3320
+ const success = this.game.put(pieceId, squareId);
3321
+ if (success) this.updateBoardPieces(animation);
3322
+ return success;
3269
3323
  }
3270
3324
 
3271
- remove(square, animation = true) {
3272
- square = this.convertSquare(square);
3273
- square.check();
3274
- this.game.remove(square.id);
3275
- let piece = square.piece;
3325
+ remove(squareId, animation = true) {
3326
+ const removedPiece = this.game.remove(squareId);
3276
3327
  this.updateBoardPieces(animation);
3277
- return piece;
3328
+ return removedPiece;
3278
3329
  }
3279
3330
 
3280
- piece(square) {
3281
- let piece = this.game.get(square);
3282
- return piece ? piece['type'] + piece['color'] : null;
3331
+ removeComment() {
3332
+ return this.game.removeComment();
3283
3333
  }
3284
3334
 
3285
- highlight(square) {
3286
- square = this.convertSquare(square);
3287
- square.check();
3288
- square.highlight();
3335
+ removeComments() {
3336
+ return this.game.removeComments();
3289
3337
  }
3290
3338
 
3291
- dehighlight(square) {
3292
- square = this.convertSquare(square);
3293
- square.check();
3294
- square.dehighlight();
3339
+ removeHeader(field) {
3340
+ return this.game.removeHeader(field);
3341
+ }
3342
+
3343
+ reset(animation = true) {
3344
+ this.game.reset();
3345
+ this.updateBoardPieces(animation);
3346
+ }
3347
+
3348
+ setCastlingRights(color, rights) {
3349
+ return this.game.setCastlingRights(color, rights);
3350
+ }
3351
+
3352
+ setComment(comment) {
3353
+ this.game.setComment(comment);
3354
+ }
3355
+
3356
+ setHeader(key, value) {
3357
+ return this.game.setHeader(key, value);
3358
+ }
3359
+
3360
+ squareColor(squareId) {
3361
+ return this.game.squareColor(squareId);
3362
+ }
3363
+
3364
+ turn() {
3365
+ return this.game.turn();
3366
+ }
3367
+
3368
+ undo() {
3369
+ const move = this.game.undo();
3370
+ if (move) this.updateBoardPieces();
3371
+ return move;
3372
+ }
3373
+
3374
+ validateFen(fen) {
3375
+ return validateFen(fen);
3295
3376
  }
3296
3377
 
3378
+ // -------------------
3379
+ // Other Utility Functions
3380
+ // -------------------
3381
+ chageFenTurn(fen, color) {
3382
+ let parts = fen.split(' ');
3383
+ parts[1] = color;
3384
+ return parts.join(' ');
3385
+ }
3386
+
3387
+ changeFenColor(fen) {
3388
+ let parts = fen.split(' ');
3389
+ parts[1] = parts[1] === 'w' ? 'b' : 'w';
3390
+ return parts.join(' ');
3391
+ }
3392
+
3393
+ isWhiteOriented() { return this.config.orientation === 'w' }
3394
+
3297
3395
  }
3298
3396
 
3299
3397
  return Chessboard;
3300
- })();
3301
3398
 
3302
- // Exporting class for browser window
3399
+ })();
3303
3400
  window.Chessboard.Chessboard = Chessboard;