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 +24 -6
- package/examples/extensions/chessboard-arrows-extension.html +18 -5
- package/examples/validate-moves.html +29 -23
- package/package.json +1 -1
- package/src/cm-chessboard/Chessboard.js +7 -4
- package/src/cm-chessboard/model/ChessboardState.js +12 -0
- package/src/cm-chessboard/model/Position.js +8 -2
- package/src/cm-chessboard/view/PositionAnimationsQueue.js +3 -3
- package/src/cm-chessboard/view/VisualMoveInput.js +10 -2
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
|
|
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
|
-
|
|
423
|
+
Draw arrows on the board.
|
|
422
424
|
|
|
423
|
-
|
|
424
|
-
|
|
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
|
-
|
|
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
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
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
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
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
|
@@ -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:
|
|
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
|
-
|
|
123
|
-
|
|
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 {
|
|
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
|
|
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(
|
|
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
|
-
|
|
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
|
-
|
|
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
|
}
|