cm-chessboard 5.4.8 → 5.5.1

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
@@ -20,7 +20,8 @@ aspects of chess games.
20
20
 
21
21
  - [Accessibility Extension](https://shaack.com/projekte/cm-chessboard/examples/extensions/chessboard-accessibility-extension.html)
22
22
  - [Arrows Extension](https://shaack.com/projekte/cm-chessboard/examples/extensions/chessboard-arrows-extension.html) (by [@barakmich](https://github.com/barakmich))
23
- - [PromotionDialog Extension](https://shaack.com/projekte/cm-chessboard/examples/extensions/chessboard-promotion-dialog-extension.html) 🆕
23
+ - [PromotionDialog Extension](https://shaack.com/projekte/cm-chessboard/examples/extensions/chessboard-promotion-dialog-extension.html)
24
+ - [RenderVideo](https://shaack.com/projekte/cm-chessboard/examples/extensions/chessboard-render-video-extension.html) 🆕
24
25
 
25
26
  ## Demo and repository
26
27
 
@@ -350,7 +351,7 @@ export const EXTENSION_POINT = {
350
351
  positionChanged: "positionChanged", // the positions of the pieces was changed
351
352
  boardChanged: "boardChanged", // the board (orientation) was changed
352
353
  moveInputToggled: "moveInputToggled", // move input was enabled or disabled
353
- moveInput: "moveInput", // move started, to validate or canceled // TODO validation not possible for now, see https://github.com/shaack/cm-chessboard/issues/82
354
+ moveInput: "moveInput", // to validate and/or cancel the move on start or end
354
355
  redrawBoard: "redrawBoard", // called after redrawing the board
355
356
  destroy: "destroy" // called, before the board is destroyed
356
357
  }
@@ -0,0 +1,50 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <title>cm-chessboard</title>
6
+ <meta name="viewport" content="width=device-width, user-scalable=yes, initial-scale=1.0"/>
7
+ <link rel="stylesheet" href="../styles/examples.css"/>
8
+ <link rel="stylesheet" href="../../assets/styles/cm-chessboard.css"/>
9
+ </head>
10
+ <body>
11
+ <h1><a href="../..">cm-chessboard</a></h1>
12
+ <h2>Example: RenderVideo extension</h2>
13
+ <p>Works in Chrome.</p>
14
+ <div class="board board-small" id="board"></div>
15
+ <video id="videoOut" controls="controls"></video>
16
+ <br style="clear: both"/>
17
+
18
+ <script type="module">
19
+ import {RenderVideo} from "../../src/cm-chessboard/extensions/render-video/RenderVideo.js"
20
+ import {Chessboard} from "../../src/cm-chessboard/Chessboard.js"
21
+ import {FEN} from "../../src/cm-chessboard/model/Position.js"
22
+
23
+ const boardElement = document.getElementById("board")
24
+ const chessboard = new Chessboard(boardElement, {
25
+ position: FEN.start,
26
+ sprite: {url: "../../assets/images/chessboard-sprite.svg"},
27
+ extensions:
28
+ [{
29
+ class: RenderVideo,
30
+ props: {}
31
+ }]
32
+ })
33
+ chessboard.recorderStart()
34
+ setTimeout(() => {
35
+ chessboard.movePiece("e2", "e4", true).then(() => {
36
+ chessboard.movePiece("e7", "e5", true).then(() => {
37
+ setTimeout(() => {
38
+ const url = chessboard.recorderStop()
39
+ const video = document.getElementById("videoOut")
40
+ video.src = url
41
+ }, 100)
42
+
43
+ })
44
+ })
45
+
46
+ }, 500)
47
+
48
+ </script>
49
+ </body>
50
+ </html>
@@ -43,6 +43,8 @@ div.board {
43
43
  width: calc(100vw - 40px);
44
44
  margin-right: 20px;
45
45
  margin-bottom: 20px; }
46
+ div.board.board-small {
47
+ max-width: 320px; }
46
48
 
47
49
  .clearfix::after {
48
50
  content: "";
@@ -5,5 +5,5 @@
5
5
  "examples.scss"
6
6
  ],
7
7
  "names": [],
8
- "mappings": "AASA,AAAA,IAAI,CAAC;EACH,KAAK,EAPG,IAAI;EAQZ,gBAAgB,EATL,IAAI;EAUf,OAAO,EAAE,IAAI;EACb,MAAM,EAAE,CAAC;EACT,WAAW,EAAE,4BAA4B;EACzC,WAAW,EAAE,GAAG;EAChB,SAAS,EATC,IAAI,GAcf;EAZD,AASE,IATE,CASF,CAAC,CAAC;IACA,SAAS,EAZD,IAAI,GAab;;AAGH,AAAA,CAAC,CAAC;EACA,KAAK,EAxBA,OAAO,GAiCb;EAVD,AAGE,CAHD,CAGG,OAAO,CAAC;IACR,KAAK,EAAE,OAAO,GACf;EALH,AAOE,CAPD,CAOG,KAAK,CAAC;IACN,KAAK,EA9BI,OAAO,GA+BjB;;AAGH,AAAA,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC;EACP,UAAU,EAAE,CAAC;EACb,SAAS,EAAE,MAAgB;EAC3B,KAAK,EAlCE,OAAO,GAmCf;;AAED,AAAA,EAAE,CAAC;EACD,aAAa,EAAE,IAAI,GACpB;;AAED,AAAA,EAAE,CAAC;EACD,aAAa,EAAE,IAAI;EACnB,SAAS,EAAE,MAAgB;EAC3B,KAAK,EA5CE,OAAO,GA6Cf;;AAED,AAAA,GAAG,CAAC;EACF,WAAW,EAAE,wBAAwB;EACrC,SAAS,EAAE,GAAG;EACd,gBAAgB,EAjDA,IAAI;EAkDpB,KAAK,EAjDA,IAAI;EAkDT,OAAO,EAAE,GAAG;EACZ,QAAQ,EAAE,IAAI,GACf;;AAED,AAAA,GAAG,AAAA,MAAM,CAAC;EACR,KAAK,EAAE,IAAI;EACX,SAAS,EAAE,KAAK;EAChB,KAAK,EAAE,kBAAkB;EACzB,YAAY,EAAE,IAAI;EAClB,aAAa,EAAE,IAAI,GACpB;;AAED,AAAA,SAAS,EAAE,KAAK,CAAC;EACf,OAAO,EAAE,EAAE;EACX,KAAK,EAAE,IAAI;EACX,OAAO,EAAE,KAAK,GACf;;AAED,AAAA,MAAM,CAAC;EACL,OAAO,EAAE,QAAQ;EACjB,SAAS,EAAE,GAAG;EACd,YAAY,EAAE,IAAI;EAClB,aAAa,EAAE,IAAI;EACnB,gBAAgB,EAAE,IAAI;EACtB,KAAK,EAAE,KAAK;EACZ,MAAM,EAAE,IAAI;EACZ,aAAa,EAAE,GAAG;EAClB,MAAM,EAAE,OAAO,GAKhB;EAdD,AAWE,MAXI,CAWF,KAAK,CAAC;IACN,gBAAgB,EAAE,IAAI,GACvB;;AAGH,AAAA,KAAK,CAAA,AAAA,IAAC,CAAD,IAAC,AAAA,EAAW;EACf,SAAS,EAAE,GAAG;EACd,OAAO,EAAE,GAAG;EACZ,aAAa,EAAE,GAAG;EAClB,MAAM,EAAE,IAAI,GACb;;AAED,AAAA,EAAE,CAAC;EACD,OAAO,EAAE,OAAO,GAEjB;;AAED,AAAA,gBAAgB,CAAC;EACf,SAAS,EAAE,KAAK,GACjB"
8
+ "mappings": "AASA,AAAA,IAAI,CAAC;EACH,KAAK,EAPG,IAAI;EAQZ,gBAAgB,EATL,IAAI;EAUf,OAAO,EAAE,IAAI;EACb,MAAM,EAAE,CAAC;EACT,WAAW,EAAE,4BAA4B;EACzC,WAAW,EAAE,GAAG;EAChB,SAAS,EATC,IAAI,GAcf;EAZD,AASE,IATE,CASF,CAAC,CAAC;IACA,SAAS,EAZD,IAAI,GAab;;AAGH,AAAA,CAAC,CAAC;EACA,KAAK,EAxBA,OAAO,GAiCb;EAVD,AAGE,CAHD,CAGG,OAAO,CAAC;IACR,KAAK,EAAE,OAAO,GACf;EALH,AAOE,CAPD,CAOG,KAAK,CAAC;IACN,KAAK,EA9BI,OAAO,GA+BjB;;AAGH,AAAA,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC;EACP,UAAU,EAAE,CAAC;EACb,SAAS,EAAE,MAAgB;EAC3B,KAAK,EAlCE,OAAO,GAmCf;;AAED,AAAA,EAAE,CAAC;EACD,aAAa,EAAE,IAAI,GACpB;;AAED,AAAA,EAAE,CAAC;EACD,aAAa,EAAE,IAAI;EACnB,SAAS,EAAE,MAAgB;EAC3B,KAAK,EA5CE,OAAO,GA6Cf;;AAED,AAAA,GAAG,CAAC;EACF,WAAW,EAAE,wBAAwB;EACrC,SAAS,EAAE,GAAG;EACd,gBAAgB,EAjDA,IAAI;EAkDpB,KAAK,EAjDA,IAAI;EAkDT,OAAO,EAAE,GAAG;EACZ,QAAQ,EAAE,IAAI,GACf;;AAED,AAAA,GAAG,AAAA,MAAM,CAAC;EACR,KAAK,EAAE,IAAI;EACX,SAAS,EAAE,KAAK;EAChB,KAAK,EAAE,kBAAkB;EACzB,YAAY,EAAE,IAAI;EAClB,aAAa,EAAE,IAAI,GAIpB;EATD,AAME,GANC,AAAA,MAAM,AAMN,YAAY,CAAC;IACZ,SAAS,EAAE,KAAK,GACjB;;AAGH,AAAA,SAAS,EAAE,KAAK,CAAC;EACf,OAAO,EAAE,EAAE;EACX,KAAK,EAAE,IAAI;EACX,OAAO,EAAE,KAAK,GACf;;AAED,AAAA,MAAM,CAAC;EACL,OAAO,EAAE,QAAQ;EACjB,SAAS,EAAE,GAAG;EACd,YAAY,EAAE,IAAI;EAClB,aAAa,EAAE,IAAI;EACnB,gBAAgB,EAAE,IAAI;EACtB,KAAK,EAAE,KAAK;EACZ,MAAM,EAAE,IAAI;EACZ,aAAa,EAAE,GAAG;EAClB,MAAM,EAAE,OAAO,GAKhB;EAdD,AAWE,MAXI,CAWF,KAAK,CAAC;IACN,gBAAgB,EAAE,IAAI,GACvB;;AAGH,AAAA,KAAK,CAAA,AAAA,IAAC,CAAD,IAAC,AAAA,EAAW;EACf,SAAS,EAAE,GAAG;EACd,OAAO,EAAE,GAAG;EACZ,aAAa,EAAE,GAAG;EAClB,MAAM,EAAE,IAAI,GACb;;AAED,AAAA,EAAE,CAAC;EACD,OAAO,EAAE,OAAO,GAEjB;;AAED,AAAA,gBAAgB,CAAC;EACf,SAAS,EAAE,KAAK,GACjB"
9
9
  }
@@ -64,6 +64,9 @@ div.board {
64
64
  width: calc(100vw - 40px);
65
65
  margin-right: 20px;
66
66
  margin-bottom: 20px;
67
+ &.board-small {
68
+ max-width: 320px;
69
+ }
67
70
  }
68
71
 
69
72
  .clearfix::after {
package/index.html CHANGED
@@ -30,7 +30,8 @@ It works, it is cool and it is easy to use. 👍</p>
30
30
  <ul>
31
31
  <li><a href="examples/extensions/chessboard-accessibility-extension.html">Accessibility extension</a></li>
32
32
  <li><a href="examples/extensions/chessboard-arrows-extension.html">Arrows extension</a></li>
33
- <li><a href="examples/extensions/chessboard-promotion-dialog-extension.html">PromotionDialog extension</a> 🆕</li>
33
+ <li><a href="examples/extensions/chessboard-promotion-dialog-extension.html">PromotionDialog extension</a></li>
34
+ <li><a href="examples/extensions/chessboard-render-video-extension.html">RenderVideo extension</a> 🆕</li>
34
35
  </ul>
35
36
  </div>
36
37
  <h2>Chessboard</h2>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cm-chessboard",
3
- "version": "5.4.8",
3
+ "version": "5.5.1",
4
4
  "description": "A JavaScript chessboard which is lightweight, ES6 module based, responsive, SVG rendered and without dependencies.",
5
5
  "keywords": [
6
6
  "chess",
@@ -30,5 +30,6 @@
30
30
  "homepage": "https://github.com/shaack/cm-chessboard#readme",
31
31
  "devDependencies": {
32
32
  "teevi": "^2.2.2"
33
- }
33
+ },
34
+ "dependencies": {}
34
35
  }
@@ -15,12 +15,9 @@ export const COLOR = {
15
15
  black: "b"
16
16
  }
17
17
  export const INPUT_EVENT_TYPE = {
18
- moveStart: "moveInputStarted", // TODO deprecated 2022-08-24, use `moveInputStarted`
19
18
  moveInputStarted: "moveInputStarted",
20
- moveDone: "validateMoveInput", // TODO deprecated 2022-08-24, use `validateMoveInput` https://github.com/shaack/cm-chessboard/issues/83
21
19
  validateMoveInput: "validateMoveInput",
22
- moveCanceled: "moveInputCanceled", // TODO deprecated 2022-08-24, use `moveInputCanceled`
23
- moveInputCanceled: "moveInputCanceled",
20
+ moveInputCanceled: "moveInputCanceled"
24
21
  }
25
22
  export const SQUARE_SELECT_TYPE = {
26
23
  primary: "primary",
@@ -156,19 +153,11 @@ export class Chessboard {
156
153
  }
157
154
 
158
155
  addMarker(type, square) {
159
- if (typeof type === "string" || typeof square === "object") { // todo remove 2022-12-01
160
- console.error("changed the signature of `addMarker` to `(type, square)` with v5.1.x")
161
- return
162
- }
163
156
  this.state.addMarker(square, type)
164
157
  this.view.drawMarkers()
165
158
  }
166
159
 
167
160
  getMarkers(type = undefined, square = undefined) {
168
- if (typeof type === "string" || typeof square === "object") { // todo remove 2022-12-01
169
- console.error("changed the signature of `getMarkers` to `(type, square)` with v5.1.x")
170
- return
171
- }
172
161
  const markersFound = []
173
162
  this.state.markers.forEach((marker) => {
174
163
  const markerSquare = marker.square
@@ -182,10 +171,6 @@ export class Chessboard {
182
171
  }
183
172
 
184
173
  removeMarkers(type = undefined, square = undefined) {
185
- if (typeof type === "string" || typeof square === "object") { // todo remove 2022-12-01
186
- console.error("changed the signature of `removeMarkers` to `(type, square)` with v5.1.x")
187
- return
188
- }
189
174
  this.state.removeMarkers(square, type)
190
175
  this.view.drawMarkers()
191
176
  }
@@ -0,0 +1,94 @@
1
+ /**
2
+ * Author and copyright: Stefan Haack (https://shaack.com)
3
+ * Repository: https://github.com/shaack/cm-chessboard
4
+ * License: MIT, see file 'LICENSE'
5
+ */
6
+
7
+ import {Extension, EXTENSION_POINT} from "../../model/Extension.js"
8
+
9
+ export class RenderVideo extends Extension {
10
+
11
+ constructor(chessboard, props) {
12
+ super(chessboard, props)
13
+ this.props = {
14
+ mediaType: "video/webm;codecs=H264"
15
+ }
16
+ Object.assign(this.props, props)
17
+ this.images = []
18
+ this.makeSpriteInline()
19
+ this.registerExtensionPoint(EXTENSION_POINT.animation, () => {
20
+ // console.log("EXTENSION_POINT.animation", data)
21
+ let clonedSvgElement = this.chessboard.view.svg.cloneNode(true)
22
+ // this.makeStyleInline(clonedSvgElement)
23
+ let serialized = new XMLSerializer().serializeToString(clonedSvgElement)
24
+ // console.log(serialized)
25
+ const blob = new Blob([serialized], {type: "image/svg+xml"})
26
+ const blobURL = URL.createObjectURL(blob)
27
+ const image = new Image()
28
+ this.images.push(image)
29
+ image.onload = () => {
30
+ // console.log("onload", event)
31
+ let context = this.canvas.getContext('2d')
32
+ // console.log(image)
33
+ context.drawImage(image, 0, 0, this.canvas.width, this.canvas.height)
34
+ }
35
+ image.src = blobURL
36
+ })
37
+ this.registerMethod("recorderStart", () => {
38
+ let all = document.querySelectorAll("svg *")
39
+ for (let i = 0; i < all.length; i++) {
40
+ this.transferComputedStyle(all[i])
41
+ }
42
+ const dimensions = this.chessboard.view.svg.getBBox()
43
+ this.canvas = document.createElement("canvas")
44
+ this.canvas.style.display = "none"
45
+ this.canvas.width = dimensions.width
46
+ this.canvas.height = dimensions.height
47
+ document.body.append(this.canvas)
48
+ this.stream = this.canvas.captureStream()
49
+ this.recorder = new MediaRecorder(this.stream, {mimeType: this.props.mediaType})
50
+ this.recordedData = []
51
+ this.recorder.ondataavailable = (event) => {
52
+ // console.log(event)
53
+ if (event.data && event.data.size) {
54
+ this.recordedData.push(event.data)
55
+ }
56
+ }
57
+ this.recorder.start(0.1)
58
+ console.log("recorder", this.recorder.state)
59
+ })
60
+ /**
61
+ * returns the url of the recorded media
62
+ */
63
+ this.registerMethod("recorderStop", () => {
64
+ this.recorder.stop()
65
+ console.log("recorder", this.recorder.state)
66
+ return URL.createObjectURL(new Blob(this.recordedData, {type: this.props.mediaType}))
67
+ })
68
+ }
69
+
70
+ transferComputedStyle(element) {
71
+ const computedStyle = getComputedStyle(element, null)
72
+ for (let i = 0; i < computedStyle.length; i++) {
73
+ const style = computedStyle[i] + ""
74
+ if (style === "fill") {
75
+ element.style[style] = computedStyle[style]
76
+ }
77
+ }
78
+ }
79
+
80
+ makeSpriteInline() {
81
+ const wrapper = document.createElement("div")
82
+ wrapper.style.display = "none"
83
+ document.body.appendChild(wrapper)
84
+ const svg = this.chessboard.view.svg
85
+ const xhr = new XMLHttpRequest()
86
+ xhr.open("GET", this.chessboard.props.sprite.url, true)
87
+ xhr.onload = function () {
88
+ const doc = new DOMParser().parseFromString(xhr.response, "text/xml")
89
+ svg.prepend(doc.getElementById("Sprite-PD"))
90
+ }
91
+ xhr.send()
92
+ }
93
+
94
+ }
@@ -9,8 +9,8 @@ export const EXTENSION_POINT = {
9
9
  boardChanged: "boardChanged", // the board (orientation) was changed
10
10
  moveInputToggled: "moveInputToggled", // move input was enabled or disabled
11
11
  moveInput: "moveInput", // move started, to validate or canceled
12
- // moveInputStateChanged: "moveInput", // TODO deprecated, use `moveInput`
13
12
  redrawBoard: "redrawBoard", // called after redrawing the board
13
+ animation: "animation", // called on every animation frame
14
14
  destroy: "destroy" // called, before the board is destroyed
15
15
  }
16
16
 
@@ -3,11 +3,9 @@
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" // TODO deprecated, use FEN
7
- export const FEN_EMPTY_POSITION = "8/8/8/8/8/8/8/8" // TODO deprecated, use FEN
8
6
  export const FEN = {
9
- start: FEN_START_POSITION,
10
- empty: FEN_EMPTY_POSITION
7
+ start: "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1",
8
+ empty: "8/8/8/8/8/8/8/8"
11
9
  }
12
10
 
13
11
  export class Position {
@@ -5,12 +5,19 @@
5
5
  */
6
6
  import {FEN, Position} from "../model/Position.js"
7
7
  import {Svg} from "./ChessboardView.js"
8
+ import {EXTENSION_POINT} from "../model/Extension.js"
8
9
 
9
10
  /*
10
11
  * Thanks to markosyan for the idea of the PromiseQueue
11
12
  * https://medium.com/@karenmarkosyan/how-to-manage-promises-into-dynamic-queue-with-vanilla-javascript-9d0d1f8d4df5
12
13
  */
13
14
 
15
+ export const ANIMATION_EVENT = {
16
+ start: "start",
17
+ frame: "frame",
18
+ end: "end"
19
+ }
20
+
14
21
  export class PromiseQueue {
15
22
 
16
23
  constructor() {
@@ -163,6 +170,9 @@ export class PositionsAnimation {
163
170
  // console.log("animationStep", time)
164
171
  if (!this.startTime) {
165
172
  this.startTime = time
173
+ this.view.chessboard.state.invokeExtensionPoints(EXTENSION_POINT.animation, {
174
+ event: ANIMATION_EVENT.start
175
+ })
166
176
  }
167
177
  const timeDiff = time - this.startTime
168
178
  if (timeDiff <= this.duration) {
@@ -175,6 +185,9 @@ export class PositionsAnimation {
175
185
  Svg.removeElement(animatedItem.element)
176
186
  }
177
187
  })
188
+ this.view.chessboard.state.invokeExtensionPoints(EXTENSION_POINT.animation, {
189
+ event: ANIMATION_EVENT.end
190
+ })
178
191
  this.callback()
179
192
  return
180
193
  }
@@ -206,6 +219,10 @@ export class PositionsAnimation {
206
219
  console.warn("animatedItem has no element", animatedItem)
207
220
  }
208
221
  })
222
+ this.view.chessboard.state.invokeExtensionPoints(EXTENSION_POINT.animation, {
223
+ event: ANIMATION_EVENT.frame,
224
+ progress: progress
225
+ })
209
226
  }
210
227
 
211
228
  static squareDistance(index1, index2) {
@@ -197,7 +197,7 @@ export class VisualMoveInput {
197
197
  }
198
198
 
199
199
  createDraggablePiece(pieceName) {
200
- // TODO use the existing piece from the board and don't create an new one
200
+ // maybe I should use the existing piece from the board and don't create a new one
201
201
  if (this.draggablePiece) {
202
202
  throw Error("draggablePiece exists")
203
203
  }