cm-chessboard 5.1.9 → 5.2.2

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
@@ -14,13 +14,12 @@ aspects of chess games.
14
14
  - [Can handle moves input via click or drag](https://shaack.com/projekte/cm-chessboard/examples/validate-moves.html)
15
15
  - [Styleable via css and supports multiple piece sets](https://shaack.com/projekte/cm-chessboard/examples/different-styles.html)
16
16
  - Uses SVG for rendering
17
- - [Allows adding **
18
- extensions** to extend the functionality](https://shaack.com/projekte/cm-chessboard/examples/extensions/chessboard-arrows-extension.html)
17
+ - [Allows adding **extensions** to extend the functionality](https://shaack.com/projekte/cm-chessboard/examples/extensions/chessboard-arrows-extension.html)
19
18
 
20
19
  ## Extensions 🆕
21
20
 
22
21
  - [Accessibility Extension](https://shaack.com/projekte/cm-chessboard/examples/extensions/chessboard-accessibility-extension.html)
23
- - [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))
24
23
 
25
24
  ## Demo and repository
26
25
 
@@ -73,23 +72,23 @@ Below is the default configuration
73
72
 
74
73
  ```javascript
75
74
  let defaultProps = {
76
- position: "empty", // set as fen, "start" or "empty"
75
+ position: FEN.empty, // set as fen, can use FEN.start or FEN.empty
77
76
  orientation: COLOR.white, // white on bottom
78
77
  responsive: true, // resize the board automatically to the size of the context element
79
78
  animationDuration: 300, // pieces animation duration in milliseconds. Disable all animation with `0`.
80
79
  language: navigator.language.substring(0, 2).toLowerCase(), // supports "de" and "en" for now, used for pieces naming
81
80
  style: {
82
- cssClass: "default", // set the css theme of the board, try "green", "blue" or "chess-club"
83
- showCoordinates: true, // show ranks and files
84
- borderType: BORDER_TYPE.none, // "thin" thin border, "frame" wide border with coordinates in it, "none" no border
85
- aspectRatio: 1, // height/width of the board
86
- moveFromMarker: MARKER_TYPE.frame, // the marker used to mark the start square
87
- moveToMarker: MARKER_TYPE.frame, // the marker used to mark the square where the figure is moving to
81
+ cssClass: "default", // set the css theme of the board, try "green", "blue" or "chess-club"
82
+ showCoordinates: true, // show ranks and files
83
+ borderType: BORDER_TYPE.none, // "thin" thin border, "frame" wide border with coordinates in it, "none" no border
84
+ aspectRatio: 1, // height/width of the board
85
+ moveFromMarker: MARKER_TYPE.frame, // the marker used to mark the start square
86
+ moveToMarker: MARKER_TYPE.frame, // the marker used to mark the square where the figure is moving to
88
87
  },
89
88
  sprite: {
90
- url: "./assets/images/chessboard-sprite.svg", // pieces and markers are stored in a sprite file
91
- size: 40, // the sprite tiles size, defaults to 40x40px
92
- cache: true // cache the sprite
89
+ url: "./assets/images/chessboard-sprite.svg", // pieces and markers are stored in a sprite file
90
+ size: 40, // the sprite tiles size, defaults to 40x40px
91
+ cache: true // cache the sprite
93
92
  },
94
93
  extensions: [ /* {class: ExtensionClass, props: { ... }} */] // add extensions here
95
94
  }
@@ -123,8 +122,7 @@ Move a piece from `squareFrom` to `squareTo`. Returns a **Promise**, which is re
123
122
 
124
123
  ### setPosition(fen, animated = false)
125
124
 
126
- Sets the position as `fen`. Special values are "start", sets the chess start position and
127
- "empty", sets an empty board. Returns a **Promise**, which is resolved, after the animation finished.
125
+ Sets the position as `fen`. Returns a **Promise**, which is resolved, after the animation finished.
128
126
 
129
127
  [Example for **setPosition**](https://shaack.com/projekte/cm-chessboard/examples/pieces-animation.html)
130
128
 
@@ -203,26 +201,24 @@ board.enableMoveInput((event) => {
203
201
 
204
202
  The event has the following **`event.type`**:
205
203
 
206
- - **`INPUT_EVENT_TYPE.moveStart`**: User started the move input, `event.square` contains the coordinates
207
- - **`INPUT_EVENT_TYPE.moveDone`**: User finished the move input, `event.squareFrom` and `event.squareTo` contain the
208
- coordinates
209
- - **`INPUT_EVENT_TYPE.moveCanceled`**: User canceled the move with clicking again on the start square or clicking
210
- outside of the board
204
+ - **`INPUT_EVENT_TYPE.moveInputStarted`**: User started the move input, `event.square` contains the coordinates. Return true or false to validate the start square.
205
+ - **`INPUT_EVENT_TYPE.validateMoveInput`**: User finished the move input, `event.squareFrom` and `event.squareTo` contain the coordinates. Return true or false to validate the move input.
206
+ - **`INPUT_EVENT_TYPE.moveInputCanceled`**: User canceled the move with clicking again on the start square or clicking outside the board.
211
207
 
212
208
  ```javascript
213
209
  chessboard.enableMoveInput((event) => {
214
- switch (event.type) {
215
- case INPUT_EVENT_TYPE.moveStart:
216
- console.log(`moveStart: ${event.square}`)
217
- // return `true`, if input is accepted/valid, `false` aborts the interaction, the piece will not move
218
- return true
219
- case INPUT_EVENT_TYPE.moveDone:
220
- console.log(`moveDone: ${event.squareFrom}-${event.squareTo}`)
221
- // return true, if input is accepted/valid, `false` takes the move back
222
- return true
223
- case INPUT_EVENT_TYPE.moveCanceled:
224
- console.log(`moveCanceled`)
225
- }
210
+ switch (event.type) {
211
+ case INPUT_EVENT_TYPE.moveInputStarted:
212
+ console.log(`moveInputStarted: ${event.square}`)
213
+ // return `true`, if input is accepted/valid, `false` aborts the interaction, the piece will not move
214
+ return true
215
+ case INPUT_EVENT_TYPE.validateMoveInput:
216
+ console.log(`validateMoveInput: ${event.squareFrom}-${event.squareTo}`)
217
+ // return true, if input is accepted/valid, `false` takes the move back
218
+ return true
219
+ case INPUT_EVENT_TYPE.moveInputCanceled:
220
+ console.log(`moveInputCanceled`)
221
+ }
226
222
  }, COLOR.white)
227
223
  ```
228
224
 
@@ -351,7 +347,7 @@ export const EXTENSION_POINT = {
351
347
  positionChanged: "positionChanged", // the positions of the pieces was changed
352
348
  boardChanged: "boardChanged", // the board (orientation) was changed
353
349
  moveInputToggled: "moveInputToggled", // move input was enabled or disabled
354
- moveInput: "moveInput", // move started, cancelled or done
350
+ moveInput: "moveInput", // move started, canceled or validation // TODO validation in extensions is not awailable for now
355
351
  destroy: "destroy" // called, before the board is destroyed
356
352
  }
357
353
  ```
@@ -360,7 +356,7 @@ Enable extensions via the chessboard props.
360
356
 
361
357
  ```js
362
358
  const chessboard = new Chessboard(document.getElementById("board"), {
363
- position: "start",
359
+ position: FEN.start,
364
360
  extensions: // list of used extensions
365
361
  [{
366
362
  class: MyCoolChessboardExtension, // the class of the extension
@@ -398,7 +394,7 @@ example [Accessibility extension](https://shaack.com/projekte/cm-chessboard/exam
398
394
 
399
395
  ```js
400
396
  const chessboard = new Chessboard(document.getElementById("board"), {
401
- position: "start",
397
+ position: FEN.start,
402
398
  sprite: {url: "../assets/images/chessboard-sprite.svg"},
403
399
  // animationDuration: 0, // optional, set to 0 to disable animations
404
400
  style: {
@@ -31,12 +31,13 @@
31
31
  <div id="boards"></div>
32
32
  <script type="module">
33
33
  import {Chessboard} from "../src/cm-chessboard/Chessboard.js"
34
+ import {FEN} from "../src/cm-chessboard/model/Position.js"
34
35
  const boardsDiv = document.getElementById("boards")
35
36
  const boardDiv = document.createElement("div")
36
37
  boardDiv.setAttribute("class", "board1")
37
38
  boardsDiv.appendChild(boardDiv)
38
39
  const largeBoard = new Chessboard(boardDiv, {
39
- position: "start",
40
+ position: FEN.start,
40
41
  sprite: {url: "../assets/images/chessboard-sprite-staunty.svg"},
41
42
  })
42
43
  const chess = new Chess()
@@ -21,9 +21,10 @@
21
21
  <div class="board" id="board9"></div>
22
22
  <script type="module">
23
23
  import {Chessboard, BORDER_TYPE} from "../src/cm-chessboard/Chessboard.js"
24
+ import {FEN} from "../src/cm-chessboard/model/Position.js"
24
25
 
25
26
  new Chessboard(document.getElementById("board1"), {
26
- position: "start",
27
+ position: FEN.start,
27
28
  style: {
28
29
  cssClass: "green",
29
30
  borderType: BORDER_TYPE.frame
@@ -31,7 +32,7 @@
31
32
  sprite: {url: "../assets/images/chessboard-sprite-staunty.svg"},
32
33
  })
33
34
  new Chessboard(document.getElementById("board2"), {
34
- position: "start",
35
+ position: FEN.start,
35
36
  style: {
36
37
  cssClass: "chessboard-js",
37
38
  borderType: BORDER_TYPE.thin
@@ -39,7 +40,7 @@
39
40
  sprite: {url: "../assets/images/chessboard-sprite.svg", cache: false}
40
41
  })
41
42
  new Chessboard(document.getElementById("board3"), {
42
- position: "start",
43
+ position: FEN.start,
43
44
  style: {
44
45
  cssClass: "chess-club",
45
46
  borderType: BORDER_TYPE.frame
@@ -47,7 +48,7 @@
47
48
  sprite: {url: "../assets/images/chessboard-sprite-staunty.svg"}
48
49
  })
49
50
  new Chessboard(document.getElementById("board4"), {
50
- position: "start",
51
+ position: FEN.start,
51
52
  style: {
52
53
  cssClass: "blue",
53
54
  borderType: BORDER_TYPE.thin,
@@ -56,14 +57,14 @@
56
57
  sprite: {url: "../assets/images/chessboard-sprite.svg", cache: false}
57
58
  })
58
59
  new Chessboard(document.getElementById("board5"), {
59
- position: "start",
60
+ position: FEN.start,
60
61
  style: {
61
62
  borderType: BORDER_TYPE.none
62
63
  },
63
64
  sprite: {url: "../assets/images/chessboard-sprite-staunty.svg"},
64
65
  })
65
66
  new Chessboard(document.getElementById("board6"), {
66
- position: "start",
67
+ position: FEN.start,
67
68
  style: {
68
69
  cssClass: "blue",
69
70
  borderType: BORDER_TYPE.frame
@@ -71,21 +72,21 @@
71
72
  sprite: {url: "../assets/images/chessboard-sprite-staunty.svg"},
72
73
  })
73
74
  new Chessboard(document.getElementById("board7"), {
74
- position: "start",
75
+ position: FEN.start,
75
76
  style: {
76
77
  cssClass: "green"
77
78
  },
78
79
  sprite: {url: "../assets/images/chessboard-sprite.svg", cache: false},
79
80
  })
80
81
  new Chessboard(document.getElementById("board8"), {
81
- position: "start",
82
+ position: FEN.start,
82
83
  style: {
83
84
  cssClass: "black-and-white"
84
85
  },
85
86
  sprite: {url: "../assets/images/chessboard-sprite.svg", cache: false},
86
87
  })
87
88
  new Chessboard(document.getElementById("board9"), {
88
- position: "start",
89
+ position: FEN.start,
89
90
  style: {
90
91
  cssClass: "chessboard-js",
91
92
  borderType: BORDER_TYPE.frame
@@ -14,21 +14,21 @@
14
14
  <div class="board" id="board"></div>
15
15
  <pre>
16
16
  const board = new Chessboard(document.getElementById("board"), {
17
- position: "start",
17
+ position: FEN.start,
18
18
  sprite: {url: "../assets/images/chessboard-sprite-staunty.svg"}
19
19
  })
20
20
 
21
21
  board.enableMoveInput(inputHandler)
22
22
  function inputHandler(event) {
23
23
  switch (event.type) {
24
- case INPUT_EVENT_TYPE.moveStart:
25
- log(`moveStart: ${event.square}`)
24
+ case INPUT_EVENT_TYPE.moveInputStarted:
25
+ log(`moveInputStarted: ${event.square}`)
26
26
  return true
27
- case INPUT_EVENT_TYPE.moveDone:
28
- log(`moveDone: ${event.squareFrom}-${event.squareTo}`)
27
+ case INPUT_EVENT_TYPE.validateMoveInput:
28
+ log(`validateMoveInput: ${event.squareFrom}-${event.squareTo}`)
29
29
  return true
30
- case INPUT_EVENT_TYPE.moveCanceled:
31
- log(`moveCanceled`)
30
+ case INPUT_EVENT_TYPE.moveInputCanceled:
31
+ log(`moveInputCanceled`)
32
32
  }
33
33
  }
34
34
  </pre>
@@ -38,9 +38,10 @@ function inputHandler(event) {
38
38
  <div id="output" style="width: 100%; overflow: hidden"></div>
39
39
  <script type="module">
40
40
  import {INPUT_EVENT_TYPE, Chessboard} from "../src/cm-chessboard/Chessboard.js"
41
+ import {FEN} from "../src/cm-chessboard/model/Position.js"
41
42
 
42
43
  window.board = new Chessboard(document.getElementById("board"), {
43
- position: "start",
44
+ position: FEN.start,
44
45
  sprite: {url: "../assets/images/chessboard-sprite-staunty.svg"}
45
46
  })
46
47
 
@@ -48,14 +49,14 @@ function inputHandler(event) {
48
49
  function inputHandler(event) {
49
50
  console.log(event)
50
51
  switch (event.type) {
51
- case INPUT_EVENT_TYPE.moveStart:
52
- log(`moveStart: ${event.square}`)
52
+ case INPUT_EVENT_TYPE.moveInputStarted:
53
+ log(`moveInputStarted: ${event.square}`)
53
54
  return true
54
- case INPUT_EVENT_TYPE.moveDone:
55
- log(`moveDone: ${event.squareFrom}-${event.squareTo}`)
55
+ case INPUT_EVENT_TYPE.validateMoveInput:
56
+ log(`validateMoveInput: ${event.squareFrom}-${event.squareTo}`)
56
57
  return true
57
- case INPUT_EVENT_TYPE.moveCanceled:
58
- log(`moveCanceled`)
58
+ case INPUT_EVENT_TYPE.moveInputCanceled:
59
+ log(`moveInputCanceled`)
59
60
  }
60
61
  }
61
62
 
@@ -32,9 +32,10 @@
32
32
  </pre>
33
33
  <script type="module">
34
34
  import {Chessboard, MARKER_TYPE, SQUARE_SELECT_TYPE} from "../src/cm-chessboard/Chessboard.js"
35
+ import {FEN} from "../src/cm-chessboard/model/Position.js"
35
36
 
36
37
  const board1 = new Chessboard(document.getElementById("board1"), {
37
- position: "start",
38
+ position: FEN.start,
38
39
  sprite: {url: "../assets/images/chessboard-sprite.svg", cache: false}
39
40
  })
40
41
  board1.enableSquareSelect((event) => {
@@ -45,10 +45,11 @@ await board.movePiece("d5", "f4")
45
45
  </pre>
46
46
  <script type="module">
47
47
  import {Chessboard, PIECE} from "../src/cm-chessboard/Chessboard.js"
48
+ import {FEN} from "../src/cm-chessboard/model/Position.js"
48
49
 
49
50
  const board = new Chessboard(document.getElementById("board"),
50
51
  {
51
- position: "start",
52
+ position: FEN.start,
52
53
  sprite: {url: "../assets/images/chessboard-sprite-staunty.svg"},
53
54
  animationDuration: 500
54
55
  })
@@ -13,15 +13,16 @@
13
13
  <div id="board"></div>
14
14
  <pre>
15
15
  new Chessboard(document.getElementById("board"), {
16
- position: "start",
16
+ position: FEN.start,
17
17
  style: {aspectRatio: 0.9}
18
18
  })
19
19
  </pre>
20
20
  <script type="module">
21
21
  import {Chessboard} from "../src/cm-chessboard/Chessboard.js"
22
+ import {FEN} from "../src/cm-chessboard/model/Position.js"
22
23
 
23
24
  new Chessboard(document.getElementById("board"), {
24
- position: "start",
25
+ position: FEN.start,
25
26
  sprite: {url: "../assets/images/chessboard-sprite-staunty.svg"},
26
27
  style: {
27
28
  aspectRatio: 0.9
@@ -29,4 +30,4 @@ new Chessboard(document.getElementById("board"), {
29
30
  })
30
31
  </script>
31
32
  </body>
32
- </html>
33
+ </html>
@@ -15,7 +15,7 @@
15
15
  <br style="clear: both"/>
16
16
  <pre>
17
17
  new Chessboard(document.getElementById("board1"), {
18
- position: "start"
18
+ position: FEN.start
19
19
  })
20
20
  new Chessboard(document.getElementById("board2"), {
21
21
  position: "rn2k1r1/ppp1pp1p/3p2p1/5bn1/P7/2N2B2/1PPPPP2/2BNK1RR w Gkq - 4 11",
@@ -24,9 +24,10 @@ new Chessboard(document.getElementById("board2"), {
24
24
  </pre>
25
25
  <script type="module">
26
26
  import {COLOR, Chessboard} from "../src/cm-chessboard/Chessboard.js"
27
+ import {FEN} from "../src/cm-chessboard/model/Position.js"
27
28
 
28
29
  new Chessboard(document.getElementById("board1"), {
29
- position: "start",
30
+ position: FEN.start,
30
31
  sprite: {url: "../assets/images/chessboard-sprite-staunty.svg"},
31
32
  })
32
33
  new Chessboard(document.getElementById("board2"), {
@@ -36,4 +37,4 @@ new Chessboard(document.getElementById("board2"), {
36
37
  })
37
38
  </script>
38
39
  </body>
39
- </html>
40
+ </html>
@@ -24,29 +24,31 @@ 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
35
- } else if (event.type === INPUT_EVENT_TYPE.moveDone) {
33
+ } else if (event.type === INPUT_EVENT_TYPE.validateMoveInput) {
36
34
  const move = {from: event.squareFrom, to: event.squareTo}
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(() => { // update position, maybe castled and 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
+ })
51
+ })
50
52
  } else {
51
53
  console.warn("invalid move", move)
52
54
  }
@@ -72,27 +74,31 @@ board.enableMoveInput(inputHandler, COLOR.white)
72
74
  function inputHandler(event) {
73
75
  console.log("event", event)
74
76
  event.chessboard.removeMarkers(MARKER_TYPE.dot)
75
- if (event.type === INPUT_EVENT_TYPE.moveStart) {
77
+ if (event.type === INPUT_EVENT_TYPE.moveInputStarted) {
76
78
  const moves = chess.moves({square: event.square, verbose: true});
77
79
  for (const move of moves) { // draw dots on possible squares
78
80
  event.chessboard.addMarker(MARKER_TYPE.dot, move.to)
79
81
  }
80
82
  return moves.length > 0
81
- } else if (event.type === INPUT_EVENT_TYPE.moveDone) {
83
+ } else if (event.type === INPUT_EVENT_TYPE.validateMoveInput) {
82
84
  const move = {from: event.squareFrom, to: event.squareTo}
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(() => { // update position, maybe castled and 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
+ })
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.9",
3
+ "version": "5.2.2",
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"
@@ -15,9 +15,12 @@ export const COLOR = {
15
15
  black: "b"
16
16
  }
17
17
  export const INPUT_EVENT_TYPE = {
18
- moveStart: "moveStart",
19
- moveDone: "moveDone",
20
- moveCanceled: "moveCanceled"
18
+ moveStart: "moveInputStarted", // TODO deprecated 2022-08-24, use `moveInputStarted`
19
+ moveInputStarted: "moveInputStarted",
20
+ moveDone: "validateMoveInput", // TODO deprecated 2022-08-24, use `validateMoveInput` https://github.com/shaack/cm-chessboard/issues/83
21
+ validateMoveInput: "validateMoveInput",
22
+ moveCanceled: "moveInputCanceled", // TODO deprecated 2022-08-24, use `moveInputCanceled`
23
+ moveInputCanceled: "moveInputCanceled",
21
24
  }
22
25
  export const SQUARE_SELECT_TYPE = {
23
26
  primary: "primary",
@@ -49,7 +52,7 @@ export class Chessboard {
49
52
  this.id = (Math.random() + 1).toString(36).substring(2, 8)
50
53
  this.extensions = []
51
54
  let defaultProps = {
52
- position: "empty", // set as fen, "start" or "empty"
55
+ position: FEN.empty, // set as fen, can use FEN.start or FEN.empty
53
56
  orientation: COLOR.white, // white on bottom
54
57
  responsive: true, // resize the board automatically to the size of the context element
55
58
  animationDuration: 300, // pieces animation duration in milliseconds. Disable all animation with `0`.
@@ -119,8 +122,11 @@ export class Chessboard {
119
122
 
120
123
  async setPosition(fen, animated = false) {
121
124
  const positionFrom = this.state.position.clone()
122
- this.state.position.setFen(fen)
123
- this.state.invokeExtensionPoints(EXTENSION_POINT.positionChanged)
125
+ const positionTo = new Position(fen)
126
+ if(positionFrom.getFen() !== positionTo.getFen()) {
127
+ this.state.position.setFen(fen)
128
+ this.state.invokeExtensionPoints(EXTENSION_POINT.positionChanged)
129
+ }
124
130
  return this.positionAnimationsQueue.enqueuePositionChange(positionFrom, this.state.position.clone(), animated)
125
131
  }
126
132
 
@@ -65,7 +65,7 @@ export class Accessibility extends Extension {
65
65
  evt.preventDefault()
66
66
  if (this.chessboard.view.moveInputCallback({
67
67
  chessboard: this.chessboard,
68
- type: INPUT_EVENT_TYPE.moveDone,
68
+ type: INPUT_EVENT_TYPE.validateMoveInput,
69
69
  squareFrom: this.inputFrom.value,
70
70
  squareTo: this.inputTo.value
71
71
  })) {
@@ -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) {
@@ -8,7 +8,7 @@ export const EXTENSION_POINT = {
8
8
  positionChanged: "positionChanged", // the positions of the pieces was changed
9
9
  boardChanged: "boardChanged", // the board (orientation) was changed
10
10
  moveInputToggled: "moveInputToggled", // move input was enabled or disabled
11
- moveInput: "moveInput", // move started, cancelled or done
11
+ moveInput: "moveInput", // move started, to validate or canceled // TODO validation not possible for now, see https://github.com/shaack/cm-chessboard/issues/82
12
12
  moveInputStateChanged: "moveInput", // TODO deprecated, use `moveInput`
13
13
  destroy: "destroy", // called, before the board is destroyed
14
14
  redrawBoard: "redrawBoard" // called while redrawing the board
@@ -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
 
@@ -13,12 +17,14 @@ export class Position {
13
17
  this.setFen(fen)
14
18
  }
15
19
 
16
- setFen(fen = FEN_EMPTY_POSITION) {
20
+ setFen(fen = FEN.empty) {
17
21
  let fenNormalized
18
22
  if (fen === "start") {
19
- fenNormalized = FEN_START_POSITION
23
+ console.warn("setting the position with the strings 'start' or 'empty' is deprecated, use FEN.start or FEN.empty")
24
+ fenNormalized = FEN.start
20
25
  } else if (fen === "empty" || fen === undefined) {
21
- fenNormalized = FEN_EMPTY_POSITION
26
+ console.warn("setting the position with the strings 'start' or 'empty' is deprecated, use FEN.start or FEN.empty")
27
+ fenNormalized = FEN.empty
22
28
  } else {
23
29
  fenNormalized = fen
24
30
  }
@@ -53,9 +53,9 @@ export class ChessboardView {
53
53
  constructor(chessboard) {
54
54
  this.chessboard = chessboard
55
55
  this.moveInput = new VisualMoveInput(this,
56
- this.moveStartCallback.bind(this),
57
- this.moveDoneCallback.bind(this),
58
- this.moveCanceledCallback.bind(this)
56
+ this.moveInputStartedCallback.bind(this),
57
+ this.validateMoveInputCallback.bind(this),
58
+ this.moveInputCanceledCallback.bind(this)
59
59
  )
60
60
  if (chessboard.props.sprite.cache) {
61
61
  this.cacheSpriteToDiv("chessboardSpriteCache", this.chessboard.props.sprite.url)
@@ -391,13 +391,13 @@ export class ChessboardView {
391
391
 
392
392
  // callbacks //
393
393
 
394
- moveStartCallback(square) {
394
+ moveInputStartedCallback(square) {
395
395
  const data = {
396
396
  chessboard: this.chessboard,
397
- type: INPUT_EVENT_TYPE.moveStart,
397
+ type: INPUT_EVENT_TYPE.moveInputStarted,
398
398
  square: square
399
399
  }
400
- this.chessboard.state.invokeExtensionPoints(EXTENSION_POINT.moveInput, data)
400
+ this.chessboard.state.invokeExtensionPoints(EXTENSION_POINT.moveInput, data) // TODO use the return value of this EP
401
401
  if (this.moveInputCallback) {
402
402
  return this.moveInputCallback(data)
403
403
  } else {
@@ -405,14 +405,14 @@ export class ChessboardView {
405
405
  }
406
406
  }
407
407
 
408
- moveDoneCallback(squareFrom, squareTo) {
408
+ validateMoveInputCallback(squareFrom, squareTo) {
409
409
  const data = {
410
410
  chessboard: this.chessboard,
411
- type: INPUT_EVENT_TYPE.moveDone,
411
+ type: INPUT_EVENT_TYPE.validateMoveInput,
412
412
  squareFrom: squareFrom,
413
413
  squareTo: squareTo
414
414
  }
415
- this.chessboard.state.invokeExtensionPoints(EXTENSION_POINT.moveInput, data)
415
+ this.chessboard.state.invokeExtensionPoints(EXTENSION_POINT.moveInput, data) // TODO use the return value of this EP
416
416
  if (this.moveInputCallback) {
417
417
  return this.moveInputCallback(data)
418
418
  } else {
@@ -420,10 +420,10 @@ export class ChessboardView {
420
420
  }
421
421
  }
422
422
 
423
- moveCanceledCallback(reason, squareFrom, squareTo) {
423
+ moveInputCanceledCallback(reason, squareFrom, squareTo) {
424
424
  const data = {
425
425
  chessboard: this.chessboard,
426
- type: INPUT_EVENT_TYPE.moveCanceled,
426
+ type: INPUT_EVENT_TYPE.moveInputCanceled,
427
427
  reason: reason,
428
428
  squareFrom: squareFrom,
429
429
  squareTo: squareTo
@@ -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,
@@ -28,17 +29,24 @@ const DRAG_THRESHOLD = 4
28
29
 
29
30
  export class VisualMoveInput {
30
31
 
31
- constructor(view, moveStartCallback, moveDoneCallback, moveCanceledCallback) {
32
+ constructor(view, moveInputStartedCallback, validateMoveInputCallback, moveInputCanceledCallback) {
32
33
  this.view = view
33
34
  this.chessboard = view.chessboard
34
- this.moveStartCallback = (square) => {
35
- return moveStartCallback(square)
35
+ this.moveInputStartedCallback = (square) => {
36
+ const result = moveInputStartedCallback(square)
37
+ if(result) {
38
+ this.chessboard.state.moveInputProcess = createTask()
39
+ }
40
+ return result
36
41
  }
37
- this.moveDoneCallback = (fromSquare, toSquare) => {
38
- return moveDoneCallback(fromSquare, toSquare)
42
+ this.validateMoveInputCallback = (fromSquare, toSquare) => {
43
+ const result = validateMoveInputCallback(fromSquare, toSquare)
44
+ this.chessboard.state.moveInputProcess.resolve(result)
45
+ return result
39
46
  }
40
- this.moveCanceledCallback = (reason, fromSquare, toSquare) => {
41
- moveCanceledCallback(reason, fromSquare, toSquare)
47
+ this.moveInputCanceledCallback = (reason, fromSquare, toSquare) => {
48
+ moveInputCanceledCallback(reason, fromSquare, toSquare)
49
+ this.chessboard.state.moveInputProcess.resolve()
42
50
  }
43
51
  this.setMoveInputState(STATE.waitForInputStart)
44
52
  }
@@ -143,7 +151,7 @@ export class VisualMoveInput {
143
151
  throw new Error("moveInputState")
144
152
  }
145
153
  this.toSquare = params.square
146
- if (this.toSquare && this.moveDoneCallback(this.fromSquare, this.toSquare)) {
154
+ if (this.toSquare && this.validateMoveInputCallback(this.fromSquare, this.toSquare)) {
147
155
  if (prevState === STATE.clickTo) {
148
156
  this.chessboard.movePiece(this.fromSquare, this.toSquare, true).then(() => {
149
157
  this.setMoveInputState(STATE.reset)
@@ -238,7 +246,7 @@ export class VisualMoveInput {
238
246
  } else if (e.type === "touchstart") {
239
247
  point = {x: e.touches[0].clientX, y: e.touches[0].clientY}
240
248
  }
241
- if (this.moveInputState === STATE.waitForInputStart && pieceName && this.moveStartCallback(square)) {
249
+ if (this.moveInputState === STATE.waitForInputStart && pieceName && this.moveInputStartedCallback(square)) {
242
250
  this.setMoveInputState(STATE.pieceClickedThreshold, {
243
251
  square: square,
244
252
  piece: pieceName,
@@ -259,8 +267,8 @@ export class VisualMoveInput {
259
267
  const startPieceName = this.chessboard.getPiece(this.fromSquare)
260
268
  const startPieceColor = startPieceName ? startPieceName.substring(0, 1) : undefined
261
269
  if (color && startPieceColor === pieceColor) {
262
- this.moveCanceledCallback(MOVE_CANCELED_REASON.clickedAnotherPiece, this.fromSquare, square)
263
- if (this.moveStartCallback(square)) {
270
+ this.moveInputCanceledCallback(MOVE_CANCELED_REASON.clickedAnotherPiece, this.fromSquare, square)
271
+ if (this.moveInputStartedCallback(square)) {
264
272
  this.setMoveInputState(STATE.pieceClickedThreshold, {
265
273
  square: square,
266
274
  piece: pieceName,
@@ -344,7 +352,7 @@ export class VisualMoveInput {
344
352
  if (this.moveInputState === STATE.clickDragTo) {
345
353
  this.chessboard.state.position.setPiece(this.fromSquare, this.movedPiece)
346
354
  this.view.setPieceVisibility(this.fromSquare)
347
- this.moveCanceledCallback(MOVE_CANCELED_REASON.draggedBack, square, square)
355
+ this.moveInputCanceledCallback(MOVE_CANCELED_REASON.draggedBack, square, square)
348
356
  this.setMoveInputState(STATE.reset)
349
357
  } else {
350
358
  this.setMoveInputState(STATE.clickTo, {square: square})
@@ -356,13 +364,13 @@ export class VisualMoveInput {
356
364
  this.setMoveInputState(STATE.clickTo, {square: square})
357
365
  } else if (this.moveInputState === STATE.secondClickThreshold) {
358
366
  this.setMoveInputState(STATE.reset)
359
- this.moveCanceledCallback(MOVE_CANCELED_REASON.secondClick, square, square)
367
+ this.moveInputCanceledCallback(MOVE_CANCELED_REASON.secondClick, square, square)
360
368
  }
361
369
  } else {
362
370
  this.view.redrawPieces()
363
371
  const moveStartSquare = this.fromSquare
364
372
  this.setMoveInputState(STATE.reset)
365
- this.moveCanceledCallback(MOVE_CANCELED_REASON.movedOutOfBoard, moveStartSquare, undefined)
373
+ this.moveInputCanceledCallback(MOVE_CANCELED_REASON.movedOutOfBoard, moveStartSquare, undefined)
366
374
  }
367
375
  } else {
368
376
  this.view.redrawPieces()
package/test/TestBoard.js CHANGED
@@ -6,6 +6,7 @@
6
6
 
7
7
  import {describe, it, assert} from "../node_modules/teevi/src/teevi.js"
8
8
  import {Chessboard} from "../src/cm-chessboard/Chessboard.js"
9
+ import {FEN} from "../src/cm-chessboard/model/Position.js"
9
10
 
10
11
  describe("TestBoard", () => {
11
12
 
@@ -13,7 +14,7 @@ describe("TestBoard", () => {
13
14
  it("should create and immediately destroy a board without failure", () => {
14
15
  const chessboard = new Chessboard(document.getElementById("TestBoard"), {
15
16
  sprite: {url: "../assets/images/chessboard-sprite.svg"},
16
- position: "start"
17
+ position: FEN.start
17
18
  })
18
19
  chessboard.destroy()
19
20
  })
@@ -21,7 +22,7 @@ describe("TestBoard", () => {
21
22
  it("should create and destroy a board", () => {
22
23
  const chessboard = new Chessboard(document.getElementById("TestBoard"), {
23
24
  sprite: {url: "../assets/images/chessboard-sprite.svg"},
24
- position: "start"
25
+ position: FEN.start
25
26
  })
26
27
  assert.equal(chessboard.view.context.childNodes.length, 1)
27
28
  chessboard.destroy()
@@ -6,13 +6,14 @@
6
6
 
7
7
  import {describe, it, assert} from "../node_modules/teevi/src/teevi.js"
8
8
  import {PIECE, Chessboard} from "../src/cm-chessboard/Chessboard.js"
9
+ import {FEN} from "../src/cm-chessboard/model/Position.js"
9
10
 
10
11
  describe("TestChessboard", () => {
11
12
 
12
13
  it("should create and destroy a chessboard", () => {
13
14
  const chessboard = new Chessboard(document.getElementById("TestPosition"), {
14
15
  sprite: {url: "../assets/images/chessboard-sprite.svg"},
15
- position: "start"
16
+ position: FEN.start
16
17
  })
17
18
  assert.equal(chessboard.getPosition(), "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR")
18
19
  chessboard.destroy()
@@ -30,7 +31,7 @@ describe("TestChessboard", () => {
30
31
  it("should get pieces on squares", () => {
31
32
  const chessboard = new Chessboard(document.getElementById("TestPosition"), {
32
33
  sprite: {url: "../assets/images/chessboard-sprite.svg"},
33
- position: "start"
34
+ position: FEN.start
34
35
  })
35
36
  assert.equal(chessboard.getPiece("d1"), "wq")
36
37
  assert.equal(chessboard.getPiece("d8"), "bq")
@@ -40,7 +41,6 @@ describe("TestChessboard", () => {
40
41
 
41
42
  it("should set pieces on squares", () => {
42
43
  const chessboard = new Chessboard(document.getElementById("TestPosition"), {
43
- position: "empty",
44
44
  sprite: {url: "../assets/images/chessboard-sprite.svg"},
45
45
  })
46
46
  chessboard.setPiece("a1", PIECE.bk)
@@ -11,8 +11,7 @@ describe("TestMarkers", () => {
11
11
 
12
12
  it("should set and get markers", () => {
13
13
  const chessboard = new Chessboard(document.getElementById("TestMarkers"), {
14
- sprite: {url: "../assets/images/chessboard-sprite.svg"},
15
- position: "empty"
14
+ sprite: {url: "../assets/images/chessboard-sprite.svg"}
16
15
  })
17
16
  chessboard.addMarker(MARKER_TYPE.square, "e5")
18
17
  chessboard.addMarker(MARKER_TYPE.frame, "b6")