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