cm-chessboard 5.1.6 → 5.2.0

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/README.md CHANGED
@@ -19,7 +19,7 @@ aspects of chess games.
19
19
  ## Extensions 🆕
20
20
 
21
21
  - [Accessibility Extension](https://shaack.com/projekte/cm-chessboard/examples/extensions/chessboard-accessibility-extension.html)
22
- - [Arrows Extension](https://shaack.com/projekte/cm-chessboard/examples/extensions/chessboard-arrows-extension.html)
22
+ - [Arrows Extension](https://shaack.com/projekte/cm-chessboard/examples/extensions/chessboard-arrows-extension.html) (by [@barakmich](https://github.com/barakmich))
23
23
 
24
24
  ## Demo and repository
25
25
 
@@ -54,6 +54,7 @@ Preconditions for using cm-chessboard in a web page:
54
54
  Example, showing a FEN:
55
55
 
56
56
  ```html
57
+
57
58
  <script type="module">
58
59
  import {Chessboard} from "./src/cm-chessboard/Chessboard.js"
59
60
 
@@ -130,7 +131,7 @@ Sets the position as `fen`. Special values are "start", sets the chess start pos
130
131
 
131
132
  Returns the board position as `fen`.
132
133
 
133
- ### addMarker(type, square)
134
+ ### addMarker(type, square)
134
135
 
135
136
  > signature changed with V5.1 from (square, type) to (type, square)
136
137
 
@@ -155,7 +156,8 @@ below.
155
156
 
156
157
  Returns the board's markers as an array.
157
158
 
158
- Only set type, to get all markers of a type on the board. Set type to `undefined`, to get markers of all types on a square.
159
+ Only set type, to get all markers of a type on the board. Set type to `undefined`, to get markers of all types on a
160
+ square.
159
161
  Set `both` to `undefined` to get all markers on the board.
160
162
 
161
163
  ### removeMarkers(type = undefined, square = undefined)
@@ -418,10 +420,26 @@ const chessboard = new Chessboard(document.getElementById("board"), {
418
420
 
419
421
  #### Arrows extension
420
422
 
421
- To draw arrows on the board.
423
+ Draw arrows on the board.
422
424
 
423
- See
424
- example [Arrows extension](https://shaack.com/projekte/cm-chessboard/examples/extensions/chessboard-arrows-extension.html)
425
+ Example: [Arrows extension](https://shaack.com/projekte/cm-chessboard/examples/extensions/chessboard-arrows-extension.html)
426
+
427
+ ##### Methods
428
+
429
+ ###### addArrow(type, fromSquare, toSquare)
430
+
431
+ Add an arrow.
432
+
433
+ ###### removeArrows(type, from, to)
434
+
435
+ To remove all arrows, call `chessboard.removeArrows()` without parameters. To remove all arrows of a specific
436
+ type (type "danger"), call `chessboard.removeArrows(ARROW_TYPE.danger)`. To remove all arrows starting at "
437
+ e2"
438
+ you can call `chessboard.removeArrows(undefined, "e2")` and so on...
439
+
440
+ ###### getArrows(type, from, to)
441
+
442
+ To get all arrows, call `chessboard.getArrows()` without parameters, as with `removeArrows(type, from, to)`.
425
443
 
426
444
  ## Usage with React
427
445
 
@@ -13,6 +13,7 @@
13
13
  <h2>Example: Arrows extension</h2>
14
14
  <div class="board" id="board"></div>
15
15
  <br style="clear: both"/>
16
+ <h2>Example code</h2>
16
17
  <pre>
17
18
  import {ARROW_TYPE, Arrows} from "../../src/cm-chessboard/extensions/arrows/Arrows.js"
18
19
  import {Chessboard} from "../../src/cm-chessboard/Chessboard.js"
@@ -36,6 +37,18 @@ chessboard.addArrow(ARROW_TYPE.default, "b8", "c6");
36
37
  chessboard.addArrow(ARROW_TYPE.pointy, "d2", "d3");
37
38
  chessboard.addArrow(ARROW_TYPE.danger, "g5", "e6");
38
39
  </pre>
40
+ <h2>Methods</h2>
41
+ <h3><code>addArrow(type, from, to)</code></h3>
42
+ <h3><code>removeArrows(type, from, to)</code></h3>
43
+ <p>
44
+ To remove all arrows, call <code>chessboard.removeArrows()</code> without parameters. To remove all arrows of a specific
45
+ type (type "danger"), call <code>chessboard.removeArrows(ARROW_TYPE.danger)</code>. To remove all arrows starting at "e2"
46
+ you can call <code>chessboard.removeArrows(undefined, "e2")</code> and so on...
47
+ </p>
48
+ <h3><code>getArrows(type, from, to)</code></h3>
49
+ <p>
50
+ To get all arrows, call <code>chessboard.getArrows()</code> without parameters, as with <code>removeArrows(type, from, to)</code>.
51
+ </p>
39
52
 
40
53
  <script type="module">
41
54
  import {ARROW_TYPE, Arrows} from "../../src/cm-chessboard/extensions/arrows/Arrows.js"
@@ -55,10 +68,10 @@ chessboard.addArrow(ARROW_TYPE.danger, "g5", "e6");
55
68
 
56
69
  }]
57
70
  })
58
- chessboard.addArrow(ARROW_TYPE.default, "f3", "d5");
59
- chessboard.addArrow(ARROW_TYPE.default, "b8", "c6");
60
- chessboard.addArrow(ARROW_TYPE.pointy, "d2", "d3");
61
- chessboard.addArrow(ARROW_TYPE.danger, "g5", "e6");
71
+ chessboard.addArrow(ARROW_TYPE.default, "f3", "d5")
72
+ chessboard.addArrow(ARROW_TYPE.default, "b8", "c6")
73
+ chessboard.addArrow(ARROW_TYPE.pointy, "d2", "d3")
74
+ chessboard.addArrow(ARROW_TYPE.danger, "g5", "e6")
62
75
  </script>
63
76
  </body>
64
- </html>
77
+ </html>
@@ -24,11 +24,9 @@ const chess = new Chess()
24
24
  function inputHandler(event) {
25
25
  console.log("event", event)
26
26
  event.chessboard.removeMarkers(MARKER_TYPE.dot)
27
- event.chessboard.removeMarkers(MARKER_TYPE.square)
28
27
  if (event.type === INPUT_EVENT_TYPE.moveStart) {
29
28
  const moves = chess.moves({square: event.square, verbose: true});
30
- event.chessboard.addMarker(MARKER_TYPE.square, event.square)
31
- for (const move of moves) { // draw dots on possible moves
29
+ for (const move of moves) { // draw dots on possible squares
32
30
  event.chessboard.addMarker(MARKER_TYPE.dot, move.to)
33
31
  }
34
32
  return moves.length > 0
@@ -37,16 +35,20 @@ function inputHandler(event) {
37
35
  const result = chess.move(move)
38
36
  if (result) {
39
37
  event.chessboard.disableMoveInput()
40
- const possibleMoves = chess.moves({verbose: true})
41
- if (possibleMoves.length > 0) {
42
- const randomIndex = Math.floor(Math.random() * possibleMoves.length)
43
- const randomMove = possibleMoves[randomIndex]
44
- setTimeout(() => { // smoother with 500ms delay
45
- chess.move({from: randomMove.from, to: randomMove.to})
46
- event.chessboard.enableMoveInput(inputHandler, COLOR.white)
47
- event.chessboard.setPosition(chess.fen(), true)
48
- }, 500)
49
- }
38
+ this.chessboard.state.moveInputProcess.then(() => { // wait for the move input process has finished
39
+ this.chessboard.setPosition(chess.fen(), true).then(() => { // wait for animation has finished
40
+ const possibleMoves = chess.moves({verbose: true})
41
+ if (possibleMoves.length > 0) {
42
+ const randomIndex = Math.floor(Math.random() * possibleMoves.length)
43
+ const randomMove = possibleMoves[randomIndex]
44
+ setTimeout(() => { // smoother with 500ms delay
45
+ chess.move({from: randomMove.from, to: randomMove.to})
46
+ event.chessboard.enableMoveInput(inputHandler, COLOR.white)
47
+ event.chessboard.setPosition(chess.fen(), true)
48
+ }, 500)
49
+ }
50
+ }) // update position, maybe castled
51
+ })
50
52
  } else {
51
53
  console.warn("invalid move", move)
52
54
  }
@@ -83,16 +85,20 @@ board.enableMoveInput(inputHandler, COLOR.white)
83
85
  const result = chess.move(move)
84
86
  if (result) {
85
87
  event.chessboard.disableMoveInput()
86
- const possibleMoves = chess.moves({verbose: true})
87
- if (possibleMoves.length > 0) {
88
- const randomIndex = Math.floor(Math.random() * possibleMoves.length)
89
- const randomMove = possibleMoves[randomIndex]
90
- setTimeout(() => { // smoother with 500ms delay
91
- chess.move({from: randomMove.from, to: randomMove.to})
92
- event.chessboard.enableMoveInput(inputHandler, COLOR.white)
93
- event.chessboard.setPosition(chess.fen(), true)
94
- }, 500)
95
- }
88
+ this.chessboard.state.moveInputProcess.then(() => { // wait for the move input process has finished
89
+ this.chessboard.setPosition(chess.fen(), true).then(() => { // wait for animation has finished
90
+ const possibleMoves = chess.moves({verbose: true})
91
+ if (possibleMoves.length > 0) {
92
+ const randomIndex = Math.floor(Math.random() * possibleMoves.length)
93
+ const randomMove = possibleMoves[randomIndex]
94
+ setTimeout(() => { // smoother with 500ms delay
95
+ chess.move({from: randomMove.from, to: randomMove.to})
96
+ event.chessboard.enableMoveInput(inputHandler, COLOR.white)
97
+ event.chessboard.setPosition(chess.fen(), true)
98
+ }, 500)
99
+ }
100
+ }) // update position, maybe castled
101
+ })
96
102
  } else {
97
103
  console.warn("invalid move", move)
98
104
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cm-chessboard",
3
- "version": "5.1.6",
3
+ "version": "5.2.0",
4
4
  "description": "A JavaScript chessboard which is lightweight, ES6 module based, responsive, SVG rendered and without dependencies.",
5
5
  "keywords": [
6
6
  "chess",
@@ -5,7 +5,7 @@
5
5
  */
6
6
 
7
7
  import {ChessboardState} from "./model/ChessboardState.js"
8
- import {Position} from "./model/Position.js"
8
+ import {FEN, Position} from "./model/Position.js"
9
9
  import {PositionAnimationsQueue} from "./view/PositionAnimationsQueue.js"
10
10
  import {EXTENSION_POINT} from "./model/Extension.js"
11
11
  import {ChessboardView} from "./view/ChessboardView.js"
@@ -49,7 +49,7 @@ export class Chessboard {
49
49
  this.id = (Math.random() + 1).toString(36).substring(2, 8)
50
50
  this.extensions = []
51
51
  let defaultProps = {
52
- position: "empty", // set as fen, "start" or "empty"
52
+ position: FEN.empty, // set as fen, can use FEN.start or FEN.empty // TODO remove those strings in favour of FEN.start and FEN.empty
53
53
  orientation: COLOR.white, // white on bottom
54
54
  responsive: true, // resize the board automatically to the size of the context element
55
55
  animationDuration: 300, // pieces animation duration in milliseconds. Disable all animation with `0`.
@@ -119,8 +119,11 @@ export class Chessboard {
119
119
 
120
120
  async setPosition(fen, animated = false) {
121
121
  const positionFrom = this.state.position.clone()
122
- this.state.position.setFen(fen)
123
- this.state.invokeExtensionPoints(EXTENSION_POINT.positionChanged)
122
+ const positionTo = new Position(fen)
123
+ if(positionFrom.getFen() !== positionTo.getFen()) {
124
+ this.state.position.setFen(fen)
125
+ this.state.invokeExtensionPoints(EXTENSION_POINT.positionChanged)
126
+ }
124
127
  return this.positionAnimationsQueue.enqueuePositionChange(positionFrom, this.state.position.clone(), animated)
125
128
  }
126
129
 
@@ -5,6 +5,17 @@
5
5
  */
6
6
  import {Position} from "./Position.js"
7
7
 
8
+ export function createTask() {
9
+ let resolve, reject
10
+ const promise = new Promise(function (_resolve, _reject) {
11
+ resolve = _resolve
12
+ reject = _reject
13
+ })
14
+ promise.resolve = resolve
15
+ promise.reject = reject
16
+ return promise
17
+ }
18
+
8
19
  export class ChessboardState {
9
20
 
10
21
  constructor() {
@@ -16,6 +27,7 @@ export class ChessboardState {
16
27
  this.inputEnabled = false
17
28
  this.squareSelectEnabled = false
18
29
  this.extensionPoints = {}
30
+ this.moveInputProcess = createTask().resolve()
19
31
  }
20
32
 
21
33
  setPosition(fen, animated = false) {
@@ -3,8 +3,12 @@
3
3
  * Repository: https://github.com/shaack/cm-chessboard
4
4
  * License: MIT, see file 'LICENSE'
5
5
  */
6
- export const FEN_START_POSITION = "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1"
7
- export const FEN_EMPTY_POSITION = "8/8/8/8/8/8/8/8"
6
+ export const FEN_START_POSITION = "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1" // TODO deprecated, use FEN
7
+ export const FEN_EMPTY_POSITION = "8/8/8/8/8/8/8/8" // TODO deprecated, use FEN
8
+ export const FEN = {
9
+ start: FEN_START_POSITION,
10
+ empty: FEN_EMPTY_POSITION
11
+ }
8
12
 
9
13
  export class Position {
10
14
 
@@ -16,8 +20,10 @@ export class Position {
16
20
  setFen(fen = FEN_EMPTY_POSITION) {
17
21
  let fenNormalized
18
22
  if (fen === "start") {
23
+ console.warn("setting the position with the strings 'start' or 'empty' is deprecated, use FEN.start or FEN.empty")
19
24
  fenNormalized = FEN_START_POSITION
20
25
  } else if (fen === "empty" || fen === undefined) {
26
+ console.warn("setting the position with the strings 'start' or 'empty' is deprecated, use FEN.start or FEN.empty")
21
27
  fenNormalized = FEN_EMPTY_POSITION
22
28
  } else {
23
29
  fenNormalized = fen
@@ -3,11 +3,11 @@
3
3
  * Repository: https://github.com/shaack/cm-chessboard
4
4
  * License: MIT, see file 'LICENSE'
5
5
  */
6
- import {FEN_EMPTY_POSITION, Position} from "../model/Position.js"
6
+ import {FEN, Position} from "../model/Position.js"
7
7
  import {Svg} from "./ChessboardView.js"
8
8
 
9
9
  /*
10
- * Thanks to markosyan for the idea to the PromiseQueue
10
+ * Thanks to markosyan for the idea of the PromiseQueue
11
11
  * https://medium.com/@karenmarkosyan/how-to-manage-promises-into-dynamic-queue-with-vanilla-javascript-9d0d1f8d4df5
12
12
  */
13
13
 
@@ -250,7 +250,7 @@ export class PositionAnimationsQueue extends PromiseQueue {
250
250
 
251
251
  async enqueueTurnBoard(position, color, animated) {
252
252
  return super.enqueue(() => new Promise((resolve) => {
253
- const emptyPosition = new Position(FEN_EMPTY_POSITION)
253
+ const emptyPosition = new Position(FEN.empty)
254
254
  let duration = animated ? this.chessboard.props.animationDuration : 0
255
255
  if(this.queue.length > 0) {
256
256
  duration = duration / (1 + Math.pow(this.queue.length / 5, 2))
@@ -5,6 +5,7 @@
5
5
  */
6
6
 
7
7
  import {Svg} from "./ChessboardView.js"
8
+ import {createTask} from "../model/ChessboardState.js"
8
9
 
9
10
  const STATE = {
10
11
  waitForInputStart: 0,
@@ -32,13 +33,20 @@ export class VisualMoveInput {
32
33
  this.view = view
33
34
  this.chessboard = view.chessboard
34
35
  this.moveStartCallback = (square) => {
35
- return moveStartCallback(square)
36
+ const result = moveStartCallback(square)
37
+ if(result) {
38
+ this.chessboard.state.moveInputProcess = createTask()
39
+ }
40
+ return result
36
41
  }
37
42
  this.moveDoneCallback = (fromSquare, toSquare) => {
38
- return moveDoneCallback(fromSquare, toSquare)
43
+ const result = moveDoneCallback(fromSquare, toSquare)
44
+ this.chessboard.state.moveInputProcess.resolve(result)
45
+ return result
39
46
  }
40
47
  this.moveCanceledCallback = (reason, fromSquare, toSquare) => {
41
48
  moveCanceledCallback(reason, fromSquare, toSquare)
49
+ this.chessboard.state.moveInputProcess.resolve()
42
50
  }
43
51
  this.setMoveInputState(STATE.waitForInputStart)
44
52
  }