├── README.md ├── examples ├── chessgame.js ├── chessknight.js ├── connectfour.js ├── gameoflife.js ├── quoridorwalls.js ├── simplecheckers.js └── tictactoe.js ├── images ├── bknight.png ├── black.png ├── chess │ ├── bishop.png │ ├── king.png │ ├── knight.png │ ├── pawn.png │ ├── queen.png │ └── rook.png ├── red.png └── white.png ├── index.html ├── jsboard.js └── jsboard.min.js /README.md: -------------------------------------------------------------------------------- 1 | # jsboard 2 | JavaScript library that allows you to easily create board games like [Chess](http://danielborowski.com/jsboard/demo/demo8/) and Conway's [Game of Life](http://danielborowski.com/jsboard/demo/demo9/). 3 |

4 | `jsboard` allows you to focus on your game logic, game AI, and game algorithms rather than focusing on creating and styling your game using HTML and CSS. `jsboard` allows you to create and play 2D board games very easily using its functions so you don't have to worry about how to represent your game in JavaScript or how to display it in the HTML. 5 |

6 | `jsboard` doesn't require jQuery or any other libraries. Simply include the library in your HTML file like in the example below. 7 | 8 | # Contents 9 | 10 | * [Setting Up](#setting-up) 11 | * [Introduction](#introduction) 12 | * [Documentation](#documentation) 13 | * [Examples](#examples) 14 | 15 | # Setting Up 16 | All you need to get started is a simple HTML file and a JS file where your game code will go. Here's how your `index.html` file should look: 17 | 18 | ```html 19 | 20 | 21 | 22 | Title 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | ``` 31 | Then create a blank `index.js` file where the game code will go. 32 | 33 | # Introduction 34 | 35 | You have access to the following objects using jsboard. 36 | 37 | ```javascript 38 | jsboard.board({ attach: tableID, size: NxM [,style: "checkerboard"] [,stylePattern: [color1, color2]] }); 39 | jsboard.piece({ text: pieceName [,cssProperties] }); 40 | ``` 41 | 42 | Here is an example board and piece created with the following properties. 43 | 44 | ```javascript 45 | var b = jsboard.board({ attach: "game", size: "3x3" }); 46 | var x = jsboard.piece({ text: "X", fontSize: "40px", textAlign: "center" }); 47 | ``` 48 | If you open `index.html` you should see the following: 49 | 50 | ![alt text][logo] 51 | 52 | [logo]: http://i.imgur.com/ioWoK5O.png "pic" 53 | 54 | Let's add some functionality to our board. We'll make it so that when we click on an empty space, one of our pieces will be placed down. We'll do this using the `cell` function from `jsboard` which can modify and get properties from spaces within the game board. 55 | 56 | ```javascript 57 | b.cell("each").on("click", function() { 58 | if (b.cell(this).get()===null) { 59 | b.cell(this).place(x.clone()); 60 | } 61 | }); 62 | ``` 63 | You should now be able to place X's on the board. [Check it out here](http://danielborowski.com/jsboard/demo/demo1/) 64 | 65 | Let's actually turn this into a tic-tac-toe game. All we need to do is alternate the placing of pieces X and O. Here's how the final `index.js` should look. 66 | 67 | ```javascript 68 | var b = jsboard.board({ attach: "game", size: "3x3" }); 69 | var x = jsboard.piece({ text: "X", fontSize: "40px", textAlign: "center" }); 70 | var o = jsboard.piece({ text: "O", fontSize: "40px", textAlign: "center"}); 71 | 72 | var turn = true; 73 | b.cell("each").on("click", function() { 74 | if (b.cell(this).get()===null) { 75 | if (turn) { b.cell(this).place(x.clone()); } 76 | else { b.cell(this).place(o.clone()); } 77 | turn = !turn; 78 | } 79 | }); 80 | ``` 81 | 82 | That's it! We just created a functioning tic-tac-toe game using these simple commands. [Check out the tic-tac-toe game here](http://danielborowski.com/jsboard/demo/demo2/) 83 | 84 | What if we want to change the styling of our board? We actually have `jsboard` functions to modify each cell or modify the whole board. We'll make changes to both. 85 | 86 | ```javascript 87 | b.style({ borderSpacing: "8px" }); 88 | b.cell("each").style({ 89 | width: "75px", 90 | height: "75px", 91 | background: "lightblue", 92 | borderRadius: "15px" 93 | }); 94 | ``` 95 | Here's what you should see now. 96 | 97 | ![alt text][logo2] 98 | 99 | [logo2]: http://i.imgur.com/berlbMg.png "pic" 100 | 101 | # Documentation 102 | 103 | Create a board. 104 | ```javascript 105 | jsboard.board({ attach: tableID, size: NxM [,style: "checkerboard"] [,stylePattern: [color1, color2]] }); 106 | // var b = jsboard.board({ attach: "game", size: "3x3" }); 107 | // var c = jsboard.board({ attach: "game", size: "8x8", style: "checkerboard" }); 108 | // var d = jsboard.board({ attach: "game", size: "8x8", style: "checkerboard", stylePattern: ["blue","green"] }); 109 | ``` 110 | 111 | Board properties, methods, and styling. 112 | ```javascript 113 | var b = jsboard.board({ attach: "game", size: "5x8", style: "checkerboard" }); 114 | b.matrix(); // matrix representation containing values from piece.text or null 115 | b.rows(); // 5 116 | b.cols(); // 8 117 | b.removeEvents(event, func); // removes event listeners from all board spaces (see chessknight example) 118 | b.style({ cssProperties }); 119 | ``` 120 | 121 | Create pieces. 122 | ```javascript 123 | jsboard.piece({ text: pieceName [,cssProperties] }); 124 | // var x = jsboard.piece({ text: "X", fontSize: "40px", textAlign: "center" }); 125 | // var k = jsboard.piece({ text: "WK", textIndent: "-9999px", background: "url('images/white.png') no-repeat", width: "50px", height: "50px", margin: "0 auto" }); 126 | ``` 127 | Piece methods and styling. 128 | ```javascript 129 | var p = jsboard.piece({ text: "X", fontSize: "40px", textAlign: "center" }); 130 | p.style({ cssProperties }); 131 | var x = p.clone(); // you must clone a piece before placing it on the board because jsboard.piece only serves as a piece schema and clone() gets it ready for the DOM 132 | ``` 133 | 134 | Cell methods. 135 | ```javascript 136 | var b = jsboard.board({ attach: "game", size: "5x8", style: "checkerboard" }); 137 | var p = jsboard.piece({ text: "X", fontSize: "40px", textAlign: "center" }); 138 | 139 | // styling cells 140 | b.cell("each").style({ cssProperties }); 141 | b.cell([N,M]).style({ cssProperties }); // [N,M] = position on the game board using matrix notation 142 | b.cell(this).style({ cssProperties }); // this = current cell 143 | b.cell(this,K).style({ cssProperties }); // (this,K) = some position K spaces from this cell. Example: b.cell(this,3) represents the cell 3 spaces to the right of this cell (see quoridorwalls example) 144 | 145 | // placing pieces in cells 146 | b.cell("each").place(p.clone()); 147 | b.cell([N,M]).place(p.clone()); 148 | b.cell(this).place(p.clone()); 149 | b.cell(this,K).place(p.clone()); 150 | 151 | // removing pieces from cells 152 | b.cell("each").rid(); 153 | b.cell([N,M]).rid(); 154 | b.cell(this).rid(); 155 | b.cell(this,K).rid(); 156 | 157 | // adding event listeners to cells 158 | b.cell("each").on(event, function); 159 | b.cell([N,M]).on(event, function); // Example: b.cell([0,0]).on("click", function() { alert("clicked!"); } ); 160 | b.cell(this).on(event, function); 161 | b.cell(this,K).on(event, function); 162 | 163 | // removing event listeners from cells 164 | b.cell("each").removeOn(event, function); 165 | b.cell([N,M]).removeOn(event, function); // Example: b.cell([0,0]).removeOn("click", myFunc } ); 166 | b.cell(this).removeOn(event, function); 167 | b.cell(this,K).removeOn(event, function); 168 | 169 | // get content of cell to see if a piece is within some cell 170 | // either null or piece.text is returned 171 | b.cell([N,M]).get(); 172 | b.cell(this).get(); 173 | b.cell(this,K).get(); 174 | 175 | // check where a specific cell is within the game board 176 | // returns matrix notation [N,M] of cell within game board 177 | b.cell(this).where(); 178 | b.cell(this,K).where(); 179 | 180 | // return the DOM node for given cell in order to manipulate using 181 | // standard JS functions. Example: b.cell([0,0]).DOM().classList.add("myclass"); 182 | b.cell([N,M]).DOM(); 183 | b.cell(this).DOM(); 184 | b.cell(this,K).DOM(); 185 | ``` 186 | # Examples 187 | 188 | Basic 189 | * [Tic-tac-toe game](http://danielborowski.com/jsboard/demo/demo3/) simple tic-tac-toe game 190 | * [Connect Four](http://danielborowski.com/jsboard/demo/demo7/) click the top of each column to drop a piece 191 | 192 | Checkerboard style 193 | * [Checkers pieces](http://danielborowski.com/jsboard/demo/demo4/) click the red piece to move around 194 | * [Chessboard knights](http://danielborowski.com/jsboard/demo/demo5/) click the knights to move around 195 | * [One-sided Chess game](http://danielborowski.com/jsboard/demo/demo8/) complete movements for white chess pieces 196 | 197 | Other games and simulations 198 | * [Conway's Game of Life](http://danielborowski.com/jsboard/demo/demo9/) place some life cells down and watch your simulation create and destroy life (here's a list of [interesting patterns](http://www.conwaylife.com/wiki/Category:Patterns) you can try out) 199 | * [Quoridor(ish) wall placement](http://danielborowski.com/jsboard/demo/demo6/) click the piece to move it to the right and click between the spaces to create a wall that prevents the piece from moving past it 200 | -------------------------------------------------------------------------------- /examples/chessgame.js: -------------------------------------------------------------------------------- 1 | // create board 2 | var b = jsboard.board({attach:"game", size:"8x8", style:"checkerboard"}); 3 | b.cell("each").style({width:"60px", height:"60px"}); 4 | 5 | // setup pieces 6 | var knight = jsboard.piece({text:"WK", textIndent:"-9999px", background:"url('images/chess/knight.png') no-repeat", width:"50px", height:"50px", margin:"0 auto" }); 7 | var bishop = jsboard.piece({text:"WB", textIndent:"-9999px", background:"url('images/chess/bishop.png') no-repeat", width:"50px", height:"50px", margin:"0 auto" }); 8 | var rook = jsboard.piece({text:"WR", textIndent:"-9999px", background:"url('images/chess/rook.png') no-repeat", width:"50px", height:"50px", margin:"0 auto" }); 9 | var queen = jsboard.piece({text:"WQ", textIndent:"-9999px", background:"url('images/chess/queen.png') no-repeat", width:"50px", height:"50px", margin:"0 auto" }); 10 | var king = jsboard.piece({text:"WG", textIndent:"-9999px", background:"url('images/chess/king.png') no-repeat", width:"50px", height:"50px", margin:"0 auto" }); 11 | var pawn = jsboard.piece({text:"WP", textIndent:"-9999px", background:"url('images/chess/pawn.png') no-repeat", width:"50px", height:"50px", margin:"0 auto" }); 12 | 13 | // create pieces to place in DOM 14 | var whitePieces = [ 15 | knight.clone(), 16 | knight.clone(), 17 | bishop.clone(), 18 | bishop.clone(), 19 | rook.clone(), 20 | rook.clone(), 21 | queen.clone(), 22 | king.clone() 23 | ]; 24 | for (var i=0; i<8; i++) 25 | whitePieces.push(pawn.clone()); 26 | 27 | // place pieces on board 28 | b.cell([7,1]).place(whitePieces[0]); b.cell([7,6]).place(whitePieces[1]); 29 | b.cell([7,2]).place(whitePieces[2]); b.cell([7,5]).place(whitePieces[3]); 30 | b.cell([7,0]).place(whitePieces[4]); b.cell([7,7]).place(whitePieces[5]); 31 | b.cell([7,3]).place(whitePieces[6]); 32 | b.cell([7,4]).place(whitePieces[7]); 33 | for (var i=8; i0) { 82 | if (b.cell(ULD).get()==null) { newLocs.push(ULD); ULD = [ULD[0]-1,ULD[1]-1]; } 83 | check--; 84 | } 85 | check = 7; 86 | // up right diagonal 87 | var URD = [loc[0]-1,loc[1]+1]; 88 | while (check>0) { 89 | if (b.cell(URD).get()==null) { newLocs.push(URD); URD = [URD[0]-1,URD[1]+1]; } 90 | check--; 91 | } 92 | check = 7; 93 | // down left diagonal 94 | var DLD = [loc[0]+1,loc[1]-1]; 95 | while (check>0) { 96 | if (b.cell(DLD).get()==null) { newLocs.push(DLD); DLD = [DLD[0]+1,DLD[1]-1]; } 97 | check--; 98 | } 99 | check = 7; 100 | // down right diagonal 101 | var DRD = [loc[0]+1,loc[1]+1]; 102 | while (check>0) { 103 | if (b.cell(DRD).get()==null) { newLocs.push(DRD); DRD = [DRD[0]+1,DRD[1]+1]; } 104 | check--; 105 | } 106 | } 107 | 108 | // movement for rooks 109 | // queen also moves like a rook 110 | if (thisPiece=="WR"||thisPiece=="WQ") { 111 | var check = 7; 112 | var U = [loc[0]-1,loc[1]]; 113 | while (check>0) { 114 | if (b.cell(U).get()==null) { newLocs.push(U); U = [U[0]-1,U[1]]; } 115 | check--; 116 | } 117 | check = 7; 118 | // up right diagonal 119 | var L = [loc[0],loc[1]-1]; 120 | while (check>0) { 121 | if (b.cell(L).get()==null) { newLocs.push(L); L = [L[0],L[1]-1]; } 122 | check--; 123 | } 124 | check = 7; 125 | // down left diagonal 126 | var R = [loc[0],loc[1]+1]; 127 | while (check>0) { 128 | if (b.cell(R).get()==null) { newLocs.push(R); R = [R[0],R[1]+1]; } 129 | check--; 130 | } 131 | check = 7; 132 | // down right diagonal 133 | var D = [loc[0]+1,loc[1]]; 134 | while (check>0) { 135 | if (b.cell(D).get()==null) { newLocs.push(D); D = [D[0]+1,D[1]]; } 136 | check--; 137 | } 138 | } 139 | 140 | // movement for king 141 | if (thisPiece=="WG") { 142 | newLocs.push( 143 | [loc[0]-1,loc[1]], [loc[0]+1,loc[1]], 144 | [loc[0],loc[1]-1], [loc[0],loc[1]+1], 145 | [loc[0]-1,loc[1]-1], [loc[0]-1,loc[1]+1], 146 | [loc[0]+1,loc[1]-1], [loc[0]+1,loc[1]+1] 147 | ); 148 | } 149 | 150 | // remove illegal moves by checking 151 | // content of b.cell().get() 152 | (function removeIllegalMoves(arr) { 153 | var fixedLocs = []; 154 | for (var i=0; i1 && !stopped) 107 | setTimeout(function() { startSim(); }, 150); 108 | } 109 | 110 | // stop simulation 111 | function stopSim() { stopped = true; } 112 | -------------------------------------------------------------------------------- /examples/quoridorwalls.js: -------------------------------------------------------------------------------- 1 | // create board 2 | var b = jsboard.board({attach:"game", size:"2x15"}); 3 | b.cell("each").style({width:"65px", height:"65px"}); 4 | 5 | // setup pieces 6 | var player = jsboard.piece({text:"P", textIndent:"-9999px", background:"url('images/black.png') no-repeat", width:"50px", height:"50px", margin:"0 auto" }); 7 | var piece_wall = jsboard.piece({text:"wall", fontSize:"0px"}); 8 | 9 | // create piece to place in DOM 10 | var p1 = player.clone(); 11 | b.cell([0,0]).place(p1); 12 | 13 | // give functionality to your piece 14 | p1.addEventListener("click", function() { 15 | var w = b.cell(this.parentNode,1).get(); 16 | // if next space is not a wall then you can move past it 17 | if (w!="wall") { 18 | // allow board overlapping but modify movement 19 | var nextSpace = b.cell(this.parentNode,2).where(); 20 | var curRow = b.cell(this.parentNode).where(); 21 | if (nextSpace[0]!=curRow[0]) b.cell(this.parentNode,1).place(p1); 22 | else b.cell(this.parentNode,2).place(p1); 23 | } 24 | }); 25 | 26 | // add functionality for placing red walls 27 | for (var r=0; r 2 | 3 | 4 | 5 | Test 6 | 9 | 10 | 11 | 16 |
17 | 18 | 19 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /jsboard.js: -------------------------------------------------------------------------------- 1 | /* 2 | The MIT License (MIT) 3 | 4 | Copyright (c) 2015 Daniel Borowski 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in 14 | all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | THE SOFTWARE. 23 | */ 24 | 25 | window.jsboard = (function(){ 26 | 27 | 'use strict'; 28 | 29 | // constr 30 | function Board(props,size,attached) { 31 | 32 | var matrixForm = []; 33 | 34 | var methods = { 35 | 36 | // return matrix form of game board 37 | matrix: function() { 38 | while (matrixForm.length>0) { matrixForm.pop(); } 39 | for (var r=0; r0) { wh[1] -= 1; } 88 | else { wh[1] = size[1]-1; wh[0] -= 1; } 89 | keepDec++; 90 | } 91 | } 92 | else { 93 | while (keepDec>0) { 94 | if (wh[1]size[0]-1||arr[1]>size[1]-1) { return document.createElement("div"); } 105 | return document.getElementById(attached).getElementsByClassName("boardRow_"+arr[0])[0].childNodes[arr[1]]; 106 | } 107 | else { 108 | var wh = getObjFromDataAtr(arr.attributes["data-matrixval"].value); 109 | if (wh[0]<0||wh[1]<0||wh[0]>size[0]-1||wh[1]>size[1]-1) { return document.createElement("div"); } 110 | var th = getBoardCell(wh[0],wh[1]); 111 | if (typeof th.childNodes[0] == "undefined") { return document.createElement("div"); } 112 | return getBoardCell(wh[0],wh[1]); 113 | } 114 | }, 115 | // styling for cells 116 | style: function(props) { 117 | if (arr=="each") { 118 | for (var st in props) { 119 | for (var r=0; rsize[0]-1||arr[1]>size[1]-1) { return "OOB"; } 128 | for (var st in props) { 129 | getBoardCell(arr[0],arr[1]).style[st] = props[st]; 130 | } 131 | } 132 | else { 133 | var wh = getObjFromDataAtr(arr.attributes["data-matrixval"].value); 134 | if (wh[0]<0||wh[1]<0||wh[0]>size[0]-1||wh[1]>size[1]-1) { return "OOB"; } 135 | var th = getBoardCell(wh[0],wh[1]); 136 | for (var st in props) { 137 | th.style[st] = props[st]; 138 | } 139 | } 140 | }, 141 | // place cloned piece in cell 142 | place: function(piece) { 143 | if (arr=="each") { 144 | for (var r=0; rsize[0]-1||wh[1]>size[1]-1) { return "OOB"; } 163 | var th = getBoardCell(wh[0],wh[1]); 164 | while (th.firstChild) { th.removeChild(th.firstChild); } 165 | getBoardCell(wh[0],wh[1]).appendChild(piece); 166 | } 167 | }, 168 | // remove all pieces from cell 169 | rid: function(piece) { 170 | if (arr=="each") { 171 | for (var r=0; rsize[0]-1||wh[1]>size[1]-1) { return "OOB"; } 185 | var th = getBoardCell(wh[0],wh[1]); 186 | while (th.firstChild) { th.removeChild(th.firstChild); } 187 | } 188 | }, 189 | // event listener for cells 190 | on: function(ev,func) { 191 | if (arr=="each") { 192 | for (var r=0; rsize[0]-1||arr[1]>size[1]-1) { return "OOB"; } 200 | getBoardCell(arr[0],arr[1]).addEventListener(ev, func); 201 | } 202 | else { 203 | var wh = getObjFromDataAtr(arr.attributes["data-matrixval"].value); 204 | if (wh[0]<0||wh[1]<0||wh[0]>size[0]-1||wh[1]>size[1]-1) { return "OOB"; } 205 | var th = getBoardCell(wh[0],wh[1]); 206 | th.addEventListener(ev, func); 207 | } 208 | }, 209 | // remove event listener for cells 210 | removeOn: function(ev,func) { 211 | if (arr=="each") { 212 | for (var r=0; rsize[0]-1||arr[1]>size[1]-1) { return "OOB"; } 220 | getBoardCell(arr[0],arr[1]).removeEventListener(ev, func); 221 | } 222 | else { 223 | var wh = getObjFromDataAtr(arr.attributes["data-matrixval"].value); 224 | if (wh[0]<0||wh[1]<0||wh[0]>size[0]-1||wh[1]>size[1]-1) { return "OOB"; } 225 | var th = getBoardCell(wh[0],wh[1]); 226 | th.removeEventListener(ev, func); 227 | } 228 | }, 229 | // get content of given cell 230 | // this is why text property of a piece is required 231 | // otherwise it would return null 232 | get: function() { 233 | if (typeof arr[0] == "number") { 234 | if (arr[0]<0||arr[1]<0||arr[0]>size[0]-1||arr[1]>size[1]-1) { return "OOB"; } 235 | var th = getBoardCell(arr[0],arr[1]); 236 | if (typeof th.childNodes[0] == "undefined") { return null; } 237 | // need data because it returns object 238 | else { return th.childNodes[0].childNodes[0].data; } 239 | } 240 | else { 241 | var wh = getObjFromDataAtr(arr.attributes["data-matrixval"].value); 242 | if (wh[0]<0||wh[1]<0||wh[0]>size[0]-1||wh[1]>size[1]-1) { return "OOB"; } 243 | var th = getBoardCell(wh[0],wh[1]); 244 | if (typeof th.childNodes[0] == "undefined") { return null; } 245 | else { return th.childNodes[0].childNodes[0].data; } 246 | } 247 | }, 248 | // get where in matrix current cell is 249 | where: function() { 250 | var wh = getObjFromDataAtr(arr.attributes["data-matrixval"].value); 251 | if (wh[0]<0||wh[1]<0||wh[0]>size[0]-1||wh[1]>size[1]-1) { return "OOB"; } 252 | return [wh[0],wh[1]]; 253 | } 254 | }; 255 | return cellMethods; 256 | } 257 | 258 | }; 259 | 260 | return methods; 261 | 262 | } 263 | 264 | function Piece(node) { 265 | 266 | var node = node; 267 | 268 | var methods = { 269 | clone: function() { 270 | var nn = node.cloneNode(true); 271 | var ra = Math.floor((Math.random() * 3000) + 1); 272 | nn.className = "pieceID_"+ra; 273 | return nn; 274 | }, 275 | style: function(props) { 276 | for (var st in props) { 277 | node.style[st] = props[st]; 278 | } 279 | } 280 | }; 281 | 282 | return methods; 283 | 284 | } 285 | 286 | // methods to create new game board and pieces 287 | var methods = { 288 | 289 | // create new game board 290 | board: function(props) { 291 | var size = []; 292 | for (var el in props) { 293 | if (el=="size") { 294 | if (!props.attach) { console.log("Need attachment for game board"); } 295 | else { 296 | var s = props[el].split("x"); 297 | var attachedBoard = document.getElementById(props.attach); 298 | 299 | size.push(parseInt(s[0]),parseInt(s[1])); 300 | // create table data to represent game board in DOM 301 | for (var i=0; i0;)a.pop();for(var t=0;te)for(;0>e;)r[1]>0?r[1]-=1:(r[1]=t[1]-1,r[0]-=1),e++;else for(;e>0;)r[1]t[0]-1||e[1]>t[1]-1?document.createElement("div"):document.getElementsByClassName("boardRow_"+e[0])[0].childNodes[e[1]];var r=n(e.attributes["data-matrixval"].value);if(r[0]<0||r[1]<0||r[0]>t[0]-1||r[1]>t[1]-1)return document.createElement("div");var i=a(r[0],r[1]);return"undefined"==typeof i.childNodes[0]?document.createElement("div"):a(r[0],r[1])},style:function(r){if("each"==e)for(var i in r)for(var o=0;ot[0]-1||e[1]>t[1]-1)return"OOB";for(var i in r)a(e[0],e[1]).style[i]=r[i]}else{var l=n(e.attributes["data-matrixval"].value);if(l[0]<0||l[1]<0||l[0]>t[0]-1||l[1]>t[1]-1)return"OOB";var s=a(l[0],l[1]);for(var i in r)s.style[i]=r[i]}},place:function(r){if("each"==e)for(var i=0;it[0]-1||f[1]>t[1]-1)return"OOB";for(var d=a(f[0],f[1]);d.firstChild;)d.removeChild(d.firstChild);a(f[0],f[1]).appendChild(r)}},rid:function(){if("each"==e)for(var r=0;rt[0]-1||d[1]>t[1]-1)return"OOB";for(var o=a(d[0],d[1]);o.firstChild;)o.removeChild(o.firstChild)}},on:function(r,i){if("each"==e)for(var o=0;ot[0]-1||e[1]>t[1]-1)return"OOB";a(e[0],e[1]).addEventListener(r,i)}else{var l=n(e.attributes["data-matrixval"].value);if(l[0]<0||l[1]<0||l[0]>t[0]-1||l[1]>t[1]-1)return"OOB";var s=a(l[0],l[1]);s.addEventListener(r,i)}},removeOn:function(r,i){if("each"==e)for(var o=0;ot[0]-1||e[1]>t[1]-1)return"OOB";a(e[0],e[1]).removeEventListener(r,i)}else{var l=n(e.attributes["data-matrixval"].value);if(l[0]<0||l[1]<0||l[0]>t[0]-1||l[1]>t[1]-1)return"OOB";var s=a(l[0],l[1]);s.removeEventListener(r,i)}},get:function(){if("number"==typeof e[0]){if(e[0]<0||e[1]<0||e[0]>t[0]-1||e[1]>t[1]-1)return"OOB";var r=a(e[0],e[1]);return"undefined"==typeof r.childNodes[0]?null:r.childNodes[0].childNodes[0].data}var i=n(e.attributes["data-matrixval"].value);if(i[0]<0||i[1]<0||i[0]>t[0]-1||i[1]>t[1]-1)return"OOB";var r=a(i[0],i[1]);return"undefined"==typeof r.childNodes[0]?null:r.childNodes[0].childNodes[0].data},where:function(){var r=n(e.attributes["data-matrixval"].value);return r[0]<0||r[1]<0||r[0]>t[0]-1||r[1]>t[1]-1?"OOB":[r[0],r[1]]}};return o}};return n}function t(e){var e=e,t={clone:function(){var t=e.cloneNode(!0),r=Math.floor(3e3*Math.random()+1);return t.className="pieceID_"+r,t},style:function(t){for(var r in t)e.style[r]=t[r]}};return t}var r={board:function(t){var r=[];for(var a in t)if("size"==a)if(t.attach){var n=t[a].split("x");r.push(parseInt(n[0]),parseInt(n[1]));for(var i=0;i