<html>
<head>
<meta charset="utf-8">
<title>JS Bin</title>
</head>
<body>
<h3 id="turn"></h3>
<p class="counts">
<span id="p1"></span> -
<span id="p2"></span>
</p>
<table>
<tr>
<td class="gap"></td>
<td class="hLine"></td>
<td class="gap"></td>
<td class="hLine"></td>
<td class="gap"></td>
<td class="hLine"></td>
<td class="gap"></td>
<td class="hLine"></td>
<td class="gap"></td>
<td class="hLine"></td>
<td class="gap"></td>
<td class="hLine"></td>
<td class="gap"></td>
</tr>
<tr>
<td class="vLine"></td>
<td class="box"></td>
<td class="vLine"></td>
<td class="box"></td>
<td class="vLine"></td>
<td class="box"></td>
<td class="vLine"></td>
<td class="box"></td>
<td class="vLine"></td>
<td class="box"></td>
<td class="vLine"></td>
<td class="box"></td>
<td class="vLine"></td>
</tr>
<tr>
<td class="gap"></td>
<td class="hLine"></td>
<td class="gap"></td>
<td class="hLine"></td>
<td class="gap"></td>
<td class="hLine"></td>
<td class="gap"></td>
<td class="hLine"></td>
<td class="gap"></td>
<td class="hLine"></td>
<td class="gap"></td>
<td class="hLine"></td>
<td class="gap"></td>
</tr>
<tr>
<td class="vLine"></td>
<td class="box"></td>
<td class="vLine"></td>
<td class="box"></td>
<td class="vLine"></td>
<td class="box"></td>
<td class="vLine"></td>
<td class="box"></td>
<td class="vLine"></td>
<td class="box"></td>
<td class="vLine"></td>
<td class="box"></td>
<td class="vLine"></td>
</tr>
<tr>
<td class="gap"></td>
<td class="hLine"></td>
<td class="gap"></td>
<td class="hLine"></td>
<td class="gap"></td>
<td class="hLine"></td>
<td class="gap"></td>
<td class="hLine"></td>
<td class="gap"></td>
<td class="hLine"></td>
<td class="gap"></td>
<td class="hLine"></td>
<td class="gap"></td>
</tr>
<tr>
<td class="vLine"></td>
<td class="box"></td>
<td class="vLine"></td>
<td class="box"></td>
<td class="vLine"></td>
<td class="box"></td>
<td class="vLine"></td>
<td class="box"></td>
<td class="vLine"></td>
<td class="box"></td>
<td class="vLine"></td>
<td class="box"></td>
<td class="vLine"></td>
</tr>
<tr>
<td class="gap"></td>
<td class="hLine"></td>
<td class="gap"></td>
<td class="hLine"></td>
<td class="gap"></td>
<td class="hLine"></td>
<td class="gap"></td>
<td class="hLine"></td>
<td class="gap"></td>
<td class="hLine"></td>
<td class="gap"></td>
<td class="hLine"></td>
<td class="gap"></td>
</tr>
<tr>
<td class="vLine"></td>
<td class="box"></td>
<td class="vLine"></td>
<td class="box"></td>
<td class="vLine"></td>
<td class="box"></td>
<td class="vLine"></td>
<td class="box"></td>
<td class="vLine"></td>
<td class="box"></td>
<td class="vLine"></td>
<td class="box"></td>
<td class="vLine"></td>
</tr>
<tr>
<td class="gap"></td>
<td class="hLine"></td>
<td class="gap"></td>
<td class="hLine"></td>
<td class="gap"></td>
<td class="hLine"></td>
<td class="gap"></td>
<td class="hLine"></td>
<td class="gap"></td>
<td class="hLine"></td>
<td class="gap"></td>
<td class="hLine"></td>
<td class="gap"></td>
</tr>
<tr>
<td class="vLine"></td>
<td class="box"></td>
<td class="vLine"></td>
<td class="box"></td>
<td class="vLine"></td>
<td class="box"></td>
<td class="vLine"></td>
<td class="box"></td>
<td class="vLine"></td>
<td class="box"></td>
<td class="vLine"></td>
<td class="box"></td>
<td class="vLine"></td>
</tr>
<tr>
<td class="gap"></td>
<td class="hLine"></td>
<td class="gap"></td>
<td class="hLine"></td>
<td class="gap"></td>
<td class="hLine"></td>
<td class="gap"></td>
<td class="hLine"></td>
<td class="gap"></td>
<td class="hLine"></td>
<td class="gap"></td>
<td class="hLine"></td>
<td class="gap"></td>
</tr>
<tr>
<td class="vLine"></td>
<td class="box"></td>
<td class="vLine"></td>
<td class="box"></td>
<td class="vLine"></td>
<td class="box"></td>
<td class="vLine"></td>
<td class="box"></td>
<td class="vLine"></td>
<td class="box"></td>
<td class="vLine"></td>
<td class="box"></td>
<td class="vLine"></td>
</tr>
<tr>
<td class="gap"></td>
<td class="hLine"></td>
<td class="gap"></td>
<td class="hLine"></td>
<td class="gap"></td>
<td class="hLine"></td>
<td class="gap"></td>
<td class="hLine"></td>
<td class="gap"></td>
<td class="hLine"></td>
<td class="gap"></td>
<td class="hLine"></td>
<td class="gap"></td>
</tr>
</table>
</body>
</html>
// Player objects
function Player (name, className, scoreBox) {
this.name = name;
this.className = className;
this.scoreBox = scoreBox;
this.score = 0;
}
// State
var players = [new Player('Blue', 'blue-mark', 'p1'),
new Player('Red', 'red-mark', 'p2')],
currentPlayerIdx = 0,
currentPlayer = players[currentPlayerIdx],
turnBox = document.getElementById('turn');
// Helpers
function toArray (o) {
return Array.prototype.slice.call(o);
}
function nodeIndex (node) {
return toArray(node.parentNode.children).indexOf(node);
}
function fill (el) {
el.classList.add('filled');
}
function isFilled (el) {
return el.classList.contains('filled');
}
// Checks
function checkHorizontalLines (node, idx) {
var left = node.previousElementSibling,
right = node.nextElementSibling;
return isFilled(left) && isFilled(right);
}
function checkVerticalLines (node, idx) {
var row = node.parentNode,
up = row.previousElementSibling.children[idx],
down = row.nextElementSibling.children[idx];
return isFilled(up) && isFilled(down);
}
function checkSurroundingLines (node) {
var idx = nodeIndex(node),
surrounded = checkVerticalLines (node, idx) && checkHorizontalLines(node, idx);
if (surrounded) {
node.classList.add('marked');
node.classList.add(currentPlayer.className);
return true;
}
}
function checkHorizontalBoxes (line) {
var left = line.previousElementSibling,
right = line.nextElementSibling;
if (left) checkSurroundingLines(left);
if (right) checkSurroundingLines(right);
}
function checkVerticalBoxes (line) {
var index = nodeIndex(line),
up = line.parentNode.previousElementSibling,
down = line.parentNode.nextElementSibling;
if (up) checkSurroundingLines(up.children[index]);
if (down) checkSurroundingLines(down.children[index]);
}
// State sets
function setInfo () {
turnBox.className = currentPlayer.className;
turnBox.innerHTML = currentPlayer.name + "'s Turn";
players.forEach(function (p) {
document.getElementById(p.scoreBox).innerHTML = p.score;
});
}
function getScores() {
players.forEach(function (p) {
p.score = document.querySelectorAll('.box.marked.'+p.className).length;
});
}
function changeTurn () {
currentPlayerIdx = 1 - currentPlayerIdx;
currentPlayer = players[currentPlayerIdx];
setInfo();
}
function updateGame() {
getScores();
changeTurn();
}
// Events
function addHLine (e) {
fill(this);
this.removeEventListener(e.type, addHLine);
checkVerticalBoxes(this);
updateGame();
}
function addVLine (e) {
fill(this);
this.removeEventListener(e.type, addVLine);
checkHorizontalBoxes(this);
updateGame();
}
function assignHandler (sel, ev, fn) {
var els = document.querySelectorAll(sel);
toArray(els).forEach(function (el) {
el.addEventListener(ev, fn);
});
}
assignHandler('.hLine', 'click', addHLine);
assignHandler('.vLine', 'click', addVLine);
setInfo();
Output
You can jump to the latest bin by adding /latest
to your URL
Keyboard Shortcuts
Shortcut | Action |
---|---|
ctrl + [num] | Toggle nth panel |
ctrl + 0 | Close focused panel |
ctrl + enter | Re-render output. If console visible: run JS in console |
Ctrl + l | Clear the console |
ctrl + / | Toggle comment on selected lines |
ctrl + ] | Indents selected lines |
ctrl + [ | Unindents selected lines |
tab | Code complete & Emmet expand |
ctrl + shift + L | Beautify code in active panel |
ctrl + s | Save & lock current Bin from further changes |
ctrl + shift + s | Open the share options |
ctrl + y | Archive Bin |
Complete list of JS Bin shortcuts |
JS Bin URLs
URL | Action |
---|---|
/ | Show the full rendered output. This content will update in real time as it's updated from the /edit url. |
/edit | Edit the current bin |
/watch | Follow a Code Casting session |
/embed | Create an embeddable version of the bin |
/latest | Load the very latest bin (/latest goes in place of the revision) |
/[username]/last | View the last edited bin for this user |
/[username]/last/edit | Edit the last edited bin for this user |
/[username]/last/watch | Follow the Code Casting session for the latest bin for this user |
/quiet | Remove analytics and edit button from rendered output |
.js | Load only the JavaScript for a bin |
.css | Load only the CSS for a bin |
Except for username prefixed urls, the url may start with http://jsbin.com/abc and the url fragments can be added to the url to view it differently. |