cm-chessboard 6.0.4 → 7.0.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 +28 -28
- package/assets/{styles/cm-chessboard.css → chessboard/chessboard.css} +2 -30
- package/assets/chessboard/chessboard.css.map +10 -0
- package/assets/{styles/cm-chessboard.scss → chessboard/chessboard.scss} +2 -43
- package/assets/chessboard/pieces/standard.svg +192 -0
- package/assets/chessboard/pieces/staunty.svg +240 -0
- package/assets/extensions/arrows/arrows.svg +19 -0
- package/assets/extensions/markers/markers.css +26 -0
- package/assets/extensions/markers/markers.css.map +9 -0
- package/assets/extensions/markers/markers.scss +40 -0
- package/assets/extensions/markers/markers.svg +27 -0
- package/{src/cm-chessboard/extensions/promotion-dialog/assets → assets/extensions/promotion-dialog}/promotion-dialog.css +1 -1
- package/{src/cm-chessboard/extensions/promotion-dialog/assets → assets/extensions/promotion-dialog}/promotion-dialog.css.map +1 -1
- package/{src/cm-chessboard/extensions/promotion-dialog/assets → assets/extensions/promotion-dialog}/promotion-dialog.scss +1 -1
- package/examples/destroy-many-boards.html +5 -3
- package/examples/different-styles.html +34 -23
- package/examples/enable-input.html +14 -7
- package/examples/extensions/{chessboard-accessibility-extension.html → accessibility-extension.html} +6 -4
- package/examples/extensions/{chessboard-arrows-extension.html → arrows-extension.html} +12 -30
- package/examples/{input-callbacks.html → extensions/markers-extension.html} +17 -21
- package/examples/extensions/{chessboard-promotion-dialog-extension.html → promotion-dialog-extension.html} +8 -7
- package/examples/extensions/{chessboard-render-video-extension.html → render-video-extension.html} +3 -8
- package/examples/many-boards.html +5 -5
- package/examples/pieces-animation.html +3 -3
- package/examples/responsive-board.html +3 -5
- package/examples/simple-boards.html +8 -4
- package/examples/test-getPiece.html +3 -3
- package/examples/validate-moves.html +7 -7
- package/index.html +7 -7
- package/package.json +1 -1
- package/src/cm-chessboard/Chessboard.js +19 -25
- package/src/cm-chessboard/extensions/accessibility/Accessibility.js +1 -1
- package/src/cm-chessboard/extensions/arrows/Arrows.js +9 -18
- package/src/cm-chessboard/extensions/markers/Markers.js +28 -17
- package/src/cm-chessboard/extensions/promotion-dialog/PromotionDialog.js +4 -6
- package/src/cm-chessboard/extensions/render-video/RenderVideo.js +5 -2
- package/src/cm-chessboard/lib/I18n.js +44 -0
- package/src/cm-chessboard/lib/Svg.js +69 -0
- package/src/cm-chessboard/lib/Utils.js +41 -0
- package/src/cm-chessboard/model/Extension.js +2 -2
- package/src/cm-chessboard/view/ChessboardView.js +47 -173
- package/src/cm-chessboard/view/PositionAnimationsQueue.js +3 -3
- package/src/cm-chessboard/view/VisualMoveInput.js +13 -7
- package/test/TestBoard.js +2 -2
- package/test/TestChessboard.js +4 -4
- package/test/TestMarkers.js +1 -1
- package/test/index.html +1 -1
- package/assets/images/chessboard-sprite-staunty.svg +0 -145
- package/assets/images/chessboard-sprite.svg +0 -144
- package/assets/styles/cm-chessboard.css.map +0 -10
- package/examples/extensions/chessboard-markers-extension.html +0 -52
- package/src/cm-chessboard/extensions/arrows/assets/arrows.svg +0 -31
- /package/assets/{styles/_cm-chessboard-theme.scss → chessboard/_chessboard-theme.scss} +0 -0
- /package/{src/cm-chessboard/extensions/arrows/assets → assets/extensions/arrows}/arrows.css +0 -0
- /package/{src/cm-chessboard/extensions/arrows/assets → assets/extensions/arrows}/arrows.css.map +0 -0
- /package/{src/cm-chessboard/extensions/arrows/assets → assets/extensions/arrows}/arrows.scss +0 -0
|
@@ -5,7 +5,8 @@
|
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
import {Extension, EXTENSION_POINT} from "../../model/Extension.js"
|
|
8
|
-
import {Svg} from "../../
|
|
8
|
+
import {Svg} from "../../lib/Svg.js"
|
|
9
|
+
import {INPUT_EVENT_TYPE} from "../../Chessboard.js"
|
|
9
10
|
|
|
10
11
|
export const MARKER_TYPE = {
|
|
11
12
|
square: {class: "marker-square", slice: "markerSquare"},
|
|
@@ -15,27 +16,20 @@ export const MARKER_TYPE = {
|
|
|
15
16
|
}
|
|
16
17
|
|
|
17
18
|
export class Markers extends Extension {
|
|
18
|
-
constructor(chessboard, props) {
|
|
19
|
+
constructor(chessboard, props = {}) {
|
|
19
20
|
super(chessboard, props)
|
|
20
21
|
this.registerExtensionPoint(EXTENSION_POINT.redrawBoard, () => {
|
|
21
22
|
this.onRedrawBoard()
|
|
22
23
|
})
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
moveToMarker: MARKER_TYPE.frame, // the marker used to mark the square where the figure is moving to
|
|
27
|
-
},
|
|
28
|
-
sprite: chessboard.props.sprite
|
|
24
|
+
this.props = {
|
|
25
|
+
autoMarkers: MARKER_TYPE.frame, // set to `null` to disable autoMarkers
|
|
26
|
+
sprite: "markers.svg" // the sprite file of the markers
|
|
29
27
|
}
|
|
30
|
-
this.props = {}
|
|
31
|
-
Object.assign(this.props, defaultProps)
|
|
32
28
|
Object.assign(this.props, props)
|
|
33
|
-
this.
|
|
34
|
-
if (props
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
if (this.props.sprite.cache) {
|
|
38
|
-
this.chessboard.view.cacheSpriteToDiv("chessboardMarkerSpriteCache", this.props.sprite.url)
|
|
29
|
+
this.autoMarker = {}
|
|
30
|
+
if (chessboard.props.assetsCache) {
|
|
31
|
+
chessboard.view.cacheSpriteToDiv("cm-chessboard-markers", this.chessboard.props.assetsUrl +
|
|
32
|
+
"extensions/markers/" + this.props.sprite)
|
|
39
33
|
}
|
|
40
34
|
this.registerMethod("addMarker", this.addMarker)
|
|
41
35
|
this.registerMethod("getMarkers", this.getMarkers)
|
|
@@ -43,6 +37,22 @@ export class Markers extends Extension {
|
|
|
43
37
|
this.markerGroupDown = Svg.addElement(chessboard.view.markersLayer, "g", {class: "markers"})
|
|
44
38
|
this.markerGroupUp = Svg.addElement(chessboard.view.markersTopLayer, "g", {class: "markers"})
|
|
45
39
|
this.markers = []
|
|
40
|
+
if (this.props.autoMarkers) {
|
|
41
|
+
Object.assign(this.autoMarker, this.props.autoMarkers)
|
|
42
|
+
this.registerExtensionPoint(EXTENSION_POINT.moveInput, (event) => {
|
|
43
|
+
this.removeMarkers(this.autoMarker)
|
|
44
|
+
if (event.type === INPUT_EVENT_TYPE.moveInputStarted ||
|
|
45
|
+
event.type === INPUT_EVENT_TYPE.movingOverSquare ||
|
|
46
|
+
event.type === INPUT_EVENT_TYPE.validateMoveInput) {
|
|
47
|
+
if(event.squareFrom) {
|
|
48
|
+
this.addMarker(this.autoMarker, event.squareFrom)
|
|
49
|
+
}
|
|
50
|
+
if(event.squareTo) {
|
|
51
|
+
this.addMarker(this.autoMarker, event.squareTo)
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
})
|
|
55
|
+
}
|
|
46
56
|
}
|
|
47
57
|
|
|
48
58
|
onRedrawBoard() {
|
|
@@ -70,7 +80,8 @@ export class Markers extends Extension {
|
|
|
70
80
|
const transform = (this.chessboard.view.svg.createSVGTransform())
|
|
71
81
|
transform.setTranslate(point.x, point.y)
|
|
72
82
|
markerGroup.transform.baseVal.appendItem(transform)
|
|
73
|
-
const spriteUrl = this.chessboard.props.
|
|
83
|
+
const spriteUrl = this.chessboard.props.assetsCache ? "" : this.chessboard.props.assetsUrl +
|
|
84
|
+
"extensions/markers/" + this.props.sprite
|
|
74
85
|
const markerUse = Svg.addElement(markerGroup, "use",
|
|
75
86
|
{href: `${spriteUrl}#${marker.type.slice}`, class: "marker " + marker.type.class})
|
|
76
87
|
const transformScale = (this.chessboard.view.svg.createSVGTransform())
|
|
@@ -5,17 +5,17 @@
|
|
|
5
5
|
*/
|
|
6
6
|
import {Extension, EXTENSION_POINT} from "../../model/Extension.js"
|
|
7
7
|
import {COLOR, PIECE} from "../../Chessboard.js"
|
|
8
|
-
import {
|
|
8
|
+
import {Svg} from "../../lib/Svg.js"
|
|
9
|
+
import {Utils} from "../../lib/Utils.js"
|
|
9
10
|
|
|
10
11
|
export class PromotionDialog extends Extension {
|
|
11
12
|
|
|
12
|
-
constructor(chessboard, props) {
|
|
13
|
+
constructor(chessboard, props = {}) {
|
|
13
14
|
super(chessboard, props)
|
|
14
|
-
|
|
15
15
|
this.registerExtensionPoint(EXTENSION_POINT.redrawBoard, this.redrawDialog.bind(this))
|
|
16
16
|
this.registerMethod("showPromotionDialog", this.showPromotionDialog)
|
|
17
17
|
this.promotionDialogGroup = Svg.addElement(chessboard.view.markersTopLayer, "g", {class: "promotion-dialog-group"})
|
|
18
|
-
|
|
18
|
+
Utils.delegate(this.promotionDialogGroup, "click", ".promotion-dialog-button",
|
|
19
19
|
this.promotionDialogOnClickPiece.bind(this))
|
|
20
20
|
this.state = {
|
|
21
21
|
isShown: false,
|
|
@@ -23,7 +23,6 @@ export class PromotionDialog extends Extension {
|
|
|
23
23
|
square: undefined,
|
|
24
24
|
callback: undefined
|
|
25
25
|
}
|
|
26
|
-
|
|
27
26
|
}
|
|
28
27
|
|
|
29
28
|
drawPieceButton(piece, point) {
|
|
@@ -121,7 +120,6 @@ export class PromotionDialog extends Extension {
|
|
|
121
120
|
this.state.color = color
|
|
122
121
|
this.state.callback = callback
|
|
123
122
|
const mousedownListener = (event) => {
|
|
124
|
-
// console.log("98c265", event)
|
|
125
123
|
if (!event.target.dataset.piece && this.state.isShown) {
|
|
126
124
|
this.state.isShown = false
|
|
127
125
|
this.state.callback({square: this.state.square, piece: null})
|
|
@@ -146,10 +146,13 @@ export class RenderVideo extends Extension {
|
|
|
146
146
|
document.body.appendChild(wrapper)
|
|
147
147
|
const svg = this.chessboard.view.svg
|
|
148
148
|
const xhr = new XMLHttpRequest()
|
|
149
|
-
xhr.open("GET", this.chessboard.
|
|
149
|
+
xhr.open("GET", this.chessboard.view.getSpriteUrl(), true)
|
|
150
150
|
xhr.onload = function () {
|
|
151
151
|
const doc = new DOMParser().parseFromString(xhr.response, "text/xml")
|
|
152
|
-
|
|
152
|
+
const pieces = doc.querySelectorAll("svg>g")
|
|
153
|
+
for (const piece of pieces) {
|
|
154
|
+
svg.prepend(piece)
|
|
155
|
+
}
|
|
153
156
|
}
|
|
154
157
|
xhr.send()
|
|
155
158
|
}
|
|
@@ -0,0 +1,44 @@
|
|
|
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
|
+
export const piecesTranslations = {
|
|
8
|
+
en: {
|
|
9
|
+
colors: {
|
|
10
|
+
w: "w", b: "b"
|
|
11
|
+
},
|
|
12
|
+
colors_long: {
|
|
13
|
+
w: "White", b: "Black"
|
|
14
|
+
},
|
|
15
|
+
pieces: {
|
|
16
|
+
p: "p", n: "n", b: "b", r: "r", q: "q", k: "k"
|
|
17
|
+
},
|
|
18
|
+
pieces_long: {
|
|
19
|
+
p: "Pawn", n: "Knight", b: "Bishop", r: "Rook", q: "Queen", k: "King"
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
de: {
|
|
23
|
+
colors: {
|
|
24
|
+
w: "w", b: "s"
|
|
25
|
+
},
|
|
26
|
+
colors_long: {
|
|
27
|
+
w: "Weiß", b: "Schwarz"
|
|
28
|
+
},
|
|
29
|
+
pieces: {
|
|
30
|
+
p: "b", n: "s", b: "l", r: "t", q: "d", k: "k"
|
|
31
|
+
},
|
|
32
|
+
pieces_long: {
|
|
33
|
+
p: "Bauer", n: "Springer", b: "Läufer", r: "Turm", q: "Dame", k: "König"
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export function renderPieceTitle(lang, name, color = undefined) {
|
|
39
|
+
let title = piecesTranslations[lang].pieces_long[name]
|
|
40
|
+
if (color) {
|
|
41
|
+
title += " " + piecesTranslations[lang].colors_long[color]
|
|
42
|
+
}
|
|
43
|
+
return title
|
|
44
|
+
}
|
|
@@ -0,0 +1,69 @@
|
|
|
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
|
+
const SVG_NAMESPACE = "http://www.w3.org/2000/svg"
|
|
8
|
+
|
|
9
|
+
export class Svg {
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* create the Svg in the HTML DOM
|
|
13
|
+
* @param containerElement
|
|
14
|
+
* @returns {Element}
|
|
15
|
+
*/
|
|
16
|
+
static createSvg(containerElement = undefined) {
|
|
17
|
+
let svg = document.createElementNS(SVG_NAMESPACE, "svg")
|
|
18
|
+
if (containerElement) {
|
|
19
|
+
svg.setAttribute("width", "100%")
|
|
20
|
+
svg.setAttribute("height", "100%")
|
|
21
|
+
containerElement.appendChild(svg)
|
|
22
|
+
}
|
|
23
|
+
return svg
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Add an Element to a SVG DOM
|
|
28
|
+
* @param parent
|
|
29
|
+
* @param name
|
|
30
|
+
* @param attributes
|
|
31
|
+
* @param sibling
|
|
32
|
+
* @returns {Element}
|
|
33
|
+
*/
|
|
34
|
+
static addElement(parent, name, attributes, sibling = undefined) {
|
|
35
|
+
let element = document.createElementNS(SVG_NAMESPACE, name)
|
|
36
|
+
if (name === "use") {
|
|
37
|
+
attributes["xlink:href"] = attributes["href"] // fix for safari
|
|
38
|
+
}
|
|
39
|
+
for (let attribute in attributes) {
|
|
40
|
+
if (attributes.hasOwnProperty(attribute)) {
|
|
41
|
+
if (attribute.indexOf(":") !== -1) {
|
|
42
|
+
const value = attribute.split(":")
|
|
43
|
+
element.setAttributeNS("http://www.w3.org/1999/" + value[0], value[1], attributes[attribute])
|
|
44
|
+
} else {
|
|
45
|
+
element.setAttribute(attribute, attributes[attribute])
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
if (sibling !== undefined) {
|
|
50
|
+
parent.appendChild(element)
|
|
51
|
+
} else {
|
|
52
|
+
parent.insertBefore(element, sibling)
|
|
53
|
+
}
|
|
54
|
+
return element
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Remove an Element from a SVG DOM
|
|
59
|
+
* @param element
|
|
60
|
+
*/
|
|
61
|
+
static removeElement(element) {
|
|
62
|
+
if (element.parentNode) {
|
|
63
|
+
element.parentNode.removeChild(element)
|
|
64
|
+
} else {
|
|
65
|
+
console.warn(element, "without parentNode")
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
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
|
+
export class Utils {
|
|
8
|
+
|
|
9
|
+
static delegate(element, eventName, selector, handler) {
|
|
10
|
+
const eventListener = function (event) {
|
|
11
|
+
let target = event.target
|
|
12
|
+
while (target && target !== this) {
|
|
13
|
+
if (target.matches(selector)) {
|
|
14
|
+
handler.call(target, event)
|
|
15
|
+
}
|
|
16
|
+
target = target.parentNode
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
element.addEventListener(eventName, eventListener)
|
|
20
|
+
return {
|
|
21
|
+
remove: function () {
|
|
22
|
+
element.removeEventListener(eventName, eventListener)
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
static mergeObjects(target, source) {
|
|
28
|
+
const isObject = (obj) => obj && typeof obj === 'object'
|
|
29
|
+
if (!isObject(target) || !isObject(source)) {
|
|
30
|
+
return source
|
|
31
|
+
}
|
|
32
|
+
for (const key of Object.keys(source)) {
|
|
33
|
+
if (source[key] instanceof Object) {
|
|
34
|
+
Object.assign(source[key], Utils.mergeObjects(target[key], source[key]))
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
Object.assign(target || {}, source)
|
|
38
|
+
return target
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
}
|
|
@@ -8,9 +8,9 @@ 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,
|
|
11
|
+
moveInput: "moveInput", // move started, moving over a square, validating or canceled
|
|
12
12
|
redrawBoard: "redrawBoard", // called after redrawing the board
|
|
13
|
-
animation: "animation", // called on every animation frame
|
|
13
|
+
animation: "animation", // called on animation start, end and on every animation frame
|
|
14
14
|
destroy: "destroy" // called, before the board is destroyed
|
|
15
15
|
}
|
|
16
16
|
|
|
@@ -8,57 +8,18 @@ import {VisualMoveInput} from "./VisualMoveInput.js"
|
|
|
8
8
|
import {BORDER_TYPE, COLOR, INPUT_EVENT_TYPE} from "../Chessboard.js"
|
|
9
9
|
import {Position} from "../model/Position.js"
|
|
10
10
|
import {EXTENSION_POINT} from "../model/Extension.js"
|
|
11
|
-
|
|
12
|
-
export const piecesTranslations = {
|
|
13
|
-
en: {
|
|
14
|
-
colors: {
|
|
15
|
-
w: "w", b: "b"
|
|
16
|
-
},
|
|
17
|
-
colors_long: {
|
|
18
|
-
w: "White", b: "Black"
|
|
19
|
-
},
|
|
20
|
-
pieces: {
|
|
21
|
-
p: "p", n: "n", b: "b", r: "r", q: "q", k: "k"
|
|
22
|
-
},
|
|
23
|
-
pieces_long: {
|
|
24
|
-
p: "Pawn", n: "Knight", b: "Bishop", r: "Rook", q: "Queen", k: "King"
|
|
25
|
-
}
|
|
26
|
-
},
|
|
27
|
-
de: {
|
|
28
|
-
colors: {
|
|
29
|
-
w: "w", b: "s"
|
|
30
|
-
},
|
|
31
|
-
colors_long: {
|
|
32
|
-
w: "Weiß", b: "Schwarz"
|
|
33
|
-
},
|
|
34
|
-
pieces: {
|
|
35
|
-
p: "b", n: "s", b: "l", r: "t", q: "d", k: "k"
|
|
36
|
-
},
|
|
37
|
-
pieces_long: {
|
|
38
|
-
p: "Bauer", n: "Springer", b: "Läufer", r: "Turm", q: "Dame", k: "König"
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
export function renderPieceTitle(lang, name, color = undefined) {
|
|
44
|
-
let title = piecesTranslations[lang].pieces_long[name]
|
|
45
|
-
if (color) {
|
|
46
|
-
title += " " + piecesTranslations[lang].colors_long[color]
|
|
47
|
-
}
|
|
48
|
-
return title
|
|
49
|
-
}
|
|
11
|
+
import {Svg} from "../lib/Svg.js"
|
|
50
12
|
|
|
51
13
|
export class ChessboardView {
|
|
52
|
-
|
|
53
14
|
constructor(chessboard) {
|
|
54
15
|
this.chessboard = chessboard
|
|
55
16
|
this.moveInput = new VisualMoveInput(this,
|
|
56
17
|
this.moveInputStartedCallback.bind(this),
|
|
18
|
+
this.movingOverSquareCallback.bind(this),
|
|
57
19
|
this.validateMoveInputCallback.bind(this),
|
|
58
|
-
this.moveInputCanceledCallback.bind(this)
|
|
59
|
-
)
|
|
60
|
-
|
|
61
|
-
this.cacheSpriteToDiv("chessboardSpriteCache", this.chessboard.props.sprite.url)
|
|
20
|
+
this.moveInputCanceledCallback.bind(this))
|
|
21
|
+
if (chessboard.props.assetsCache) {
|
|
22
|
+
this.cacheSpriteToDiv("cm-chessboard-sprite", this.getSpriteUrl())
|
|
62
23
|
}
|
|
63
24
|
this.context = document.createElement("div")
|
|
64
25
|
this.chessboard.context.appendChild(this.context)
|
|
@@ -143,6 +104,7 @@ export class ChessboardView {
|
|
|
143
104
|
}
|
|
144
105
|
|
|
145
106
|
updateMetrics() {
|
|
107
|
+
const piecesTileSize = this.chessboard.props.style.pieces.tileSize
|
|
146
108
|
this.width = this.context.clientWidth
|
|
147
109
|
this.height = this.context.clientWidth * (this.chessboard.props.style.aspectRatio || 1)
|
|
148
110
|
if (this.chessboard.props.style.borderType === BORDER_TYPE.frame) {
|
|
@@ -156,16 +118,15 @@ export class ChessboardView {
|
|
|
156
118
|
this.innerHeight = this.height - 2 * this.borderSize
|
|
157
119
|
this.squareWidth = this.innerWidth / 8
|
|
158
120
|
this.squareHeight = this.innerHeight / 8
|
|
159
|
-
this.scalingX = this.squareWidth /
|
|
160
|
-
this.scalingY = this.squareHeight /
|
|
161
|
-
this.pieceXTranslate = (this.squareWidth / 2 -
|
|
121
|
+
this.scalingX = this.squareWidth / piecesTileSize
|
|
122
|
+
this.scalingY = this.squareHeight / piecesTileSize
|
|
123
|
+
this.pieceXTranslate = (this.squareWidth / 2 - piecesTileSize * this.scalingY / 2)
|
|
162
124
|
}
|
|
163
125
|
|
|
164
126
|
handleResize() {
|
|
165
127
|
this.context.style.width = this.chessboard.context.clientWidth + "px"
|
|
166
128
|
this.context.style.height = (this.chessboard.context.clientWidth * this.chessboard.props.style.aspectRatio) + "px"
|
|
167
|
-
if (this.context.clientWidth !== this.width ||
|
|
168
|
-
this.context.clientHeight !== this.height) {
|
|
129
|
+
if (this.context.clientWidth !== this.width || this.context.clientHeight !== this.height) {
|
|
169
130
|
this.updateMetrics()
|
|
170
131
|
this.redrawBoard()
|
|
171
132
|
this.redrawPieces()
|
|
@@ -193,10 +154,7 @@ export class ChessboardView {
|
|
|
193
154
|
if (this.chessboard.props.style.borderType === BORDER_TYPE.frame) {
|
|
194
155
|
const innerPos = this.borderSize
|
|
195
156
|
let borderInner = Svg.addElement(this.boardGroup, "rect", {
|
|
196
|
-
x: innerPos,
|
|
197
|
-
y: innerPos,
|
|
198
|
-
width: this.width - innerPos * 2,
|
|
199
|
-
height: this.height - innerPos * 2
|
|
157
|
+
x: innerPos, y: innerPos, width: this.width - innerPos * 2, height: this.height - innerPos * 2
|
|
200
158
|
})
|
|
201
159
|
borderInner.setAttribute("class", "border-inner")
|
|
202
160
|
}
|
|
@@ -223,7 +181,7 @@ export class ChessboardView {
|
|
|
223
181
|
}
|
|
224
182
|
const inline = this.chessboard.props.style.borderType !== BORDER_TYPE.frame
|
|
225
183
|
for (let file = 0; file < 8; file++) {
|
|
226
|
-
let x = this.borderSize + (17 + this.chessboard.props.
|
|
184
|
+
let x = this.borderSize + (17 + this.chessboard.props.style.pieces.tileSize * file) * this.scalingX
|
|
227
185
|
let y = this.height - this.scalingY * 3.5
|
|
228
186
|
let cssClass = "coordinate file"
|
|
229
187
|
if (inline) {
|
|
@@ -231,10 +189,7 @@ export class ChessboardView {
|
|
|
231
189
|
cssClass += file % 2 ? " white" : " black"
|
|
232
190
|
}
|
|
233
191
|
const textElement = Svg.addElement(this.coordinatesGroup, "text", {
|
|
234
|
-
class: cssClass,
|
|
235
|
-
x: x,
|
|
236
|
-
y: y,
|
|
237
|
-
style: `font-size: ${this.scalingY * 10}px`
|
|
192
|
+
class: cssClass, x: x, y: y, style: `font-size: ${this.scalingY * 10}px`
|
|
238
193
|
})
|
|
239
194
|
if (this.chessboard.state.orientation === COLOR.white) {
|
|
240
195
|
textElement.textContent = String.fromCharCode(97 + file)
|
|
@@ -257,10 +212,7 @@ export class ChessboardView {
|
|
|
257
212
|
}
|
|
258
213
|
}
|
|
259
214
|
const textElement = Svg.addElement(this.coordinatesGroup, "text", {
|
|
260
|
-
class: cssClass,
|
|
261
|
-
x: x,
|
|
262
|
-
y: y,
|
|
263
|
-
style: `font-size: ${this.scalingY * 10}px`
|
|
215
|
+
class: cssClass, x: x, y: y, style: `font-size: ${this.scalingY * 10}px`
|
|
264
216
|
})
|
|
265
217
|
if (this.chessboard.state.orientation === COLOR.white) {
|
|
266
218
|
textElement.textContent = "" + (8 - rank)
|
|
@@ -288,31 +240,20 @@ export class ChessboardView {
|
|
|
288
240
|
drawPiece(parentGroup, pieceName, point) {
|
|
289
241
|
const pieceGroup = Svg.addElement(parentGroup, "g", {})
|
|
290
242
|
pieceGroup.setAttribute("data-piece", pieceName)
|
|
291
|
-
pieceGroup.setAttribute("class", "piece-group")
|
|
292
243
|
const transform = (this.svg.createSVGTransform())
|
|
293
244
|
transform.setTranslate(point.x, point.y)
|
|
294
245
|
pieceGroup.transform.baseVal.appendItem(transform)
|
|
295
|
-
const spriteUrl = this.chessboard.props.
|
|
246
|
+
const spriteUrl = this.chessboard.props.assetsCache ? "" : this.getSpriteUrl()
|
|
296
247
|
const pieceUse = Svg.addElement(pieceGroup, "use", {
|
|
297
|
-
href: `${spriteUrl}#${pieceName}`,
|
|
298
|
-
class: "piece"
|
|
248
|
+
href: `${spriteUrl}#${pieceName}`, class: "piece"
|
|
299
249
|
})
|
|
300
250
|
const transformScale = (this.svg.createSVGTransform())
|
|
301
251
|
transformScale.setScale(this.scalingY, this.scalingY)
|
|
302
252
|
pieceUse.transform.baseVal.appendItem(transformScale)
|
|
303
|
-
const transformTranslate = (this.svg.createSVGTransform())
|
|
304
|
-
transformTranslate.setTranslate(this.pieceXTranslate, 0)
|
|
305
|
-
pieceUse.transform.baseVal.appendItem(transformTranslate)
|
|
306
253
|
return pieceGroup
|
|
307
254
|
}
|
|
308
255
|
|
|
309
256
|
drawPieceOnSquare(square, pieceName) {
|
|
310
|
-
const point = this.squareToPoint(square)
|
|
311
|
-
const pieceGroup = this.drawPiece(this.piecesGroup, pieceName, point)
|
|
312
|
-
pieceGroup.setAttribute("data-square", square)
|
|
313
|
-
return pieceGroup
|
|
314
|
-
|
|
315
|
-
/*
|
|
316
257
|
const pieceGroup = Svg.addElement(this.piecesGroup, "g", {})
|
|
317
258
|
pieceGroup.setAttribute("data-piece", pieceName)
|
|
318
259
|
pieceGroup.setAttribute("data-square", square)
|
|
@@ -320,24 +261,24 @@ export class ChessboardView {
|
|
|
320
261
|
const transform = (this.svg.createSVGTransform())
|
|
321
262
|
transform.setTranslate(point.x, point.y)
|
|
322
263
|
pieceGroup.transform.baseVal.appendItem(transform)
|
|
323
|
-
const spriteUrl = this.chessboard.props.
|
|
264
|
+
const spriteUrl = this.chessboard.props.assetsCache ? "" : this.getSpriteUrl()
|
|
324
265
|
const pieceUse = Svg.addElement(pieceGroup, "use", {
|
|
325
|
-
href: `${spriteUrl}#${pieceName}`,
|
|
326
|
-
class: "piece"
|
|
266
|
+
href: `${spriteUrl}#${pieceName}`, class: "piece"
|
|
327
267
|
})
|
|
328
268
|
// center on square
|
|
329
269
|
const transformTranslate = (this.svg.createSVGTransform())
|
|
330
270
|
transformTranslate.setTranslate(this.pieceXTranslate, 0)
|
|
331
271
|
pieceUse.transform.baseVal.appendItem(transformTranslate)
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
272
|
+
// scale
|
|
273
|
+
const transformScale = (this.svg.createSVGTransform())
|
|
274
|
+
transformScale.setScale(this.scalingY, this.scalingY)
|
|
275
|
+
pieceUse.transform.baseVal.appendItem(transformScale)
|
|
276
|
+
return pieceGroup
|
|
336
277
|
}
|
|
337
278
|
|
|
338
279
|
setPieceVisibility(square, visible = true) {
|
|
339
280
|
const piece = this.getPieceElement(square)
|
|
340
|
-
if(piece) {
|
|
281
|
+
if (piece) {
|
|
341
282
|
if (visible) {
|
|
342
283
|
piece.setAttribute("visibility", "visible")
|
|
343
284
|
} else {
|
|
@@ -391,17 +332,32 @@ export class ChessboardView {
|
|
|
391
332
|
const data = {
|
|
392
333
|
chessboard: this.chessboard,
|
|
393
334
|
type: INPUT_EVENT_TYPE.moveInputStarted,
|
|
394
|
-
square: square,
|
|
335
|
+
square: square, // TODO this one is deprecated 2023-03-18
|
|
336
|
+
squareFrom: square,
|
|
395
337
|
piece: this.chessboard.getPiece(square)
|
|
396
338
|
}
|
|
397
339
|
if (this.moveInputCallback) {
|
|
398
340
|
// the "oldschool" move input validator
|
|
399
|
-
data.moveInputCallbackResult =
|
|
341
|
+
data.moveInputCallbackResult = this.moveInputCallback(data)
|
|
400
342
|
}
|
|
401
343
|
// the new extension points
|
|
402
344
|
const extensionPointsResult = this.chessboard.state.invokeExtensionPoints(EXTENSION_POINT.moveInput, data)
|
|
403
|
-
// validates, when moveInputCallbackResult and
|
|
404
|
-
return !(extensionPointsResult === false || !data.moveInputCallbackResult)
|
|
345
|
+
// validates, when moveInputCallbackResult and extensionPointsResults are true
|
|
346
|
+
return !(extensionPointsResult === false || !data.moveInputCallbackResult)
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
movingOverSquareCallback(squareFrom, squareTo) {
|
|
350
|
+
const data = {
|
|
351
|
+
chessboard: this.chessboard,
|
|
352
|
+
type: INPUT_EVENT_TYPE.movingOverSquare,
|
|
353
|
+
squareFrom: squareFrom,
|
|
354
|
+
squareTo: squareTo,
|
|
355
|
+
piece: this.chessboard.getPiece(squareFrom)
|
|
356
|
+
}
|
|
357
|
+
if (this.moveInputCallback) {
|
|
358
|
+
data.moveInputCallbackResult = this.moveInputCallback(data)
|
|
359
|
+
}
|
|
360
|
+
this.chessboard.state.invokeExtensionPoints(EXTENSION_POINT.moveInput, data)
|
|
405
361
|
}
|
|
406
362
|
|
|
407
363
|
validateMoveInputCallback(squareFrom, squareTo) {
|
|
@@ -413,16 +369,15 @@ export class ChessboardView {
|
|
|
413
369
|
piece: this.chessboard.getPiece(squareFrom)
|
|
414
370
|
}
|
|
415
371
|
if (this.moveInputCallback) {
|
|
416
|
-
// the "oldschool" move input validator
|
|
417
372
|
data.moveInputCallbackResult = this.moveInputCallback(data)
|
|
418
373
|
}
|
|
419
374
|
// the new extension points
|
|
420
375
|
const extensionPointsResult = this.chessboard.state.invokeExtensionPoints(EXTENSION_POINT.moveInput, data)
|
|
421
376
|
// validates, when moveInputCallbackResult and extensionPointsResult are true
|
|
422
|
-
return !(extensionPointsResult === false || !data.moveInputCallbackResult)
|
|
377
|
+
return !(extensionPointsResult === false || !data.moveInputCallbackResult)
|
|
423
378
|
}
|
|
424
379
|
|
|
425
|
-
moveInputCanceledCallback(
|
|
380
|
+
moveInputCanceledCallback(squareFrom, squareTo, reason) {
|
|
426
381
|
const data = {
|
|
427
382
|
chessboard: this.chessboard,
|
|
428
383
|
type: INPUT_EVENT_TYPE.moveInputCanceled,
|
|
@@ -465,88 +420,7 @@ export class ChessboardView {
|
|
|
465
420
|
return this.indexToPoint(index)
|
|
466
421
|
}
|
|
467
422
|
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
const SVG_NAMESPACE = "http://www.w3.org/2000/svg"
|
|
471
|
-
|
|
472
|
-
export class Svg {
|
|
473
|
-
|
|
474
|
-
/**
|
|
475
|
-
* create the Svg in the HTML DOM
|
|
476
|
-
* @param containerElement
|
|
477
|
-
* @returns {Element}
|
|
478
|
-
*/
|
|
479
|
-
static createSvg(containerElement = undefined) {
|
|
480
|
-
let svg = document.createElementNS(SVG_NAMESPACE, "svg")
|
|
481
|
-
if (containerElement) {
|
|
482
|
-
svg.setAttribute("width", "100%")
|
|
483
|
-
svg.setAttribute("height", "100%")
|
|
484
|
-
containerElement.appendChild(svg)
|
|
485
|
-
}
|
|
486
|
-
return svg
|
|
487
|
-
}
|
|
488
|
-
|
|
489
|
-
/**
|
|
490
|
-
* Add an Element to a SVG DOM
|
|
491
|
-
* @param parent
|
|
492
|
-
* @param name
|
|
493
|
-
* @param attributes
|
|
494
|
-
* @param sibling
|
|
495
|
-
* @returns {Element}
|
|
496
|
-
*/
|
|
497
|
-
static addElement(parent, name, attributes, sibling = undefined) {
|
|
498
|
-
let element = document.createElementNS(SVG_NAMESPACE, name)
|
|
499
|
-
if (name === "use") {
|
|
500
|
-
attributes["xlink:href"] = attributes["href"] // fix for safari
|
|
501
|
-
}
|
|
502
|
-
for (let attribute in attributes) {
|
|
503
|
-
if (attributes.hasOwnProperty(attribute)) {
|
|
504
|
-
if (attribute.indexOf(":") !== -1) {
|
|
505
|
-
const value = attribute.split(":")
|
|
506
|
-
element.setAttributeNS("http://www.w3.org/1999/" + value[0], value[1], attributes[attribute])
|
|
507
|
-
} else {
|
|
508
|
-
element.setAttribute(attribute, attributes[attribute])
|
|
509
|
-
}
|
|
510
|
-
}
|
|
511
|
-
}
|
|
512
|
-
if (sibling !== undefined) {
|
|
513
|
-
parent.appendChild(element)
|
|
514
|
-
} else {
|
|
515
|
-
parent.insertBefore(element, sibling)
|
|
516
|
-
}
|
|
517
|
-
return element
|
|
518
|
-
}
|
|
519
|
-
|
|
520
|
-
/**
|
|
521
|
-
* Remove an Element from a SVG DOM
|
|
522
|
-
* @param element
|
|
523
|
-
*/
|
|
524
|
-
static removeElement(element) {
|
|
525
|
-
if(element.parentNode) {
|
|
526
|
-
element.parentNode.removeChild(element)
|
|
527
|
-
} else {
|
|
528
|
-
console.warn(element, "without parentNode")
|
|
529
|
-
}
|
|
530
|
-
}
|
|
531
|
-
|
|
532
|
-
}
|
|
533
|
-
|
|
534
|
-
export class DomUtils {
|
|
535
|
-
static delegate(element, eventName, selector, handler) {
|
|
536
|
-
const eventListener = function (event) {
|
|
537
|
-
let target = event.target
|
|
538
|
-
while (target && target !== this) {
|
|
539
|
-
if (target.matches(selector)) {
|
|
540
|
-
handler.call(target, event)
|
|
541
|
-
}
|
|
542
|
-
target = target.parentNode
|
|
543
|
-
}
|
|
544
|
-
}
|
|
545
|
-
element.addEventListener(eventName, eventListener)
|
|
546
|
-
return {
|
|
547
|
-
remove: function () {
|
|
548
|
-
element.removeEventListener(eventName, eventListener)
|
|
549
|
-
}
|
|
550
|
-
}
|
|
423
|
+
getSpriteUrl() {
|
|
424
|
+
return this.chessboard.props.assetsUrl + "chessboard/pieces/" + this.chessboard.props.style.pieces.file
|
|
551
425
|
}
|
|
552
426
|
}
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* License: MIT, see file 'LICENSE'
|
|
5
5
|
*/
|
|
6
6
|
import {FEN, Position} from "../model/Position.js"
|
|
7
|
-
import {Svg} from "
|
|
7
|
+
import {Svg} from "../lib/Svg.js"
|
|
8
8
|
import {EXTENSION_POINT} from "../model/Extension.js"
|
|
9
9
|
|
|
10
10
|
/*
|
|
@@ -250,7 +250,7 @@ export class PositionAnimationsQueue extends PromiseQueue {
|
|
|
250
250
|
return Promise.resolve()
|
|
251
251
|
} else {
|
|
252
252
|
return super.enqueue(() => new Promise((resolve) => {
|
|
253
|
-
let duration = animated ? this.chessboard.props.animationDuration : 0
|
|
253
|
+
let duration = animated ? this.chessboard.props.style.animationDuration : 0
|
|
254
254
|
if (this.queue.length > 0) {
|
|
255
255
|
duration = duration / (1 + Math.pow(this.queue.length / 5, 2))
|
|
256
256
|
}
|
|
@@ -271,7 +271,7 @@ export class PositionAnimationsQueue extends PromiseQueue {
|
|
|
271
271
|
async enqueueTurnBoard(position, color, animated) {
|
|
272
272
|
return super.enqueue(() => new Promise((resolve) => {
|
|
273
273
|
const emptyPosition = new Position(FEN.empty)
|
|
274
|
-
let duration = animated ? this.chessboard.props.animationDuration : 0
|
|
274
|
+
let duration = animated ? this.chessboard.props.style.animationDuration : 0
|
|
275
275
|
if(this.queue.length > 0) {
|
|
276
276
|
duration = duration / (1 + Math.pow(this.queue.length / 5, 2))
|
|
277
277
|
}
|