Created
November 8, 2018 17:23
-
-
Save QuentinAndre/f69be9338db73751b27bafaa95bde13d to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var default_matrix = [ | |
['V', 'H', 'W', 'X', 'S', 'C', 'E', 'P', 'T', 'E', 'R', 'C', 'R', 'S', 'P', 'S', 'J', 'T'], | |
['S', 'T', 'T', 'T', 'N', 'X', 'D', 'Y', 'D', 'X', 'L', 'M', 'W', 'K', 'A', 'O', 'B', 'C'], | |
['G', 'N', 'A', 'R', 'C', 'W', 'O', 'E', 'A', 'Y', 'T', 'R', 'S', 'V', 'L', 'V', 'G', 'J'], | |
['C', 'T', 'O', 'D', 'O', 'P', 'O', 'F', 'S', 'N', 'N', 'R', 'A', 'H', 'A', 'E', 'G', 'P'], | |
['E', 'O', 'B', 'M', 'R', 'S', 'D', 'R', 'E', 'C', 'O', 'A', 'O', 'E', 'C', 'R', 'I', 'A'], | |
['R', 'I', 'L', 'I', 'M', 'F', 'N', 'M', 'C', 'N', 'E', 'U', 'S', 'K', 'E', 'E', 'P', 'A'], | |
['J', 'E', 'N', 'O', 'A', 'O', 'N', 'O', 'O', 'M', 'S', 'N', 'I', 'T', 'K', 'I', 'U', 'H'], | |
['H', 'C', 'T', 'M', 'N', 'R', 'C', 'H', 'C', 'E', 'O', 'N', 'T', 'N', 'Y', 'G', 'W', 'L'], | |
['E', 'T', 'I', 'R', 'E', 'Y', 'H', 'O', 'H', 'M', 'G', 'T', 'I', 'D', 'H', 'N', 'L', 'N'], | |
['H', 'L', 'R', 'V', 'A', 'E', 'T', 'O', 'L', 'D', 'L', 'G', 'S', 'L', 'U', 'I', 'K', 'J'], | |
['Y', 'T', 'O', 'I', 'A', 'H', 'L', 'I', 'O', 'O', 'H', 'A', 'A', 'U', 'N', 'K', 'V', 'F'], | |
['W', 'G', 'L', 'D', 'B', 'D', 'C', 'M', 'I', 'T', 'R', 'W', 'E', 'E', 'C', 'X', 'E', 'W'], | |
['L', 'A', 'Y', 'O', 'R', 'B', 'T', 'U', 'K', 'D', 'J', 'D', 'B', 'R', 'T', 'K', 'R', 'A'], | |
['S', 'E', 'A', 'L', 'M', 'U', 'C', 'T', 'W', 'I', 'N', 'D', 'S', 'O', 'R', 'C', 'U', 'C'], | |
['Z', 'N', 'E', 'T', 'N', 'E', 'M', 'A', 'I', 'L', 'R', 'A', 'P', 'Z', 'M', 'I', 'L', 'B'], | |
['Z', 'T', 'H', 'R', 'O', 'N', 'E', 'B', 'P', 'A', 'T', 'R', 'O', 'N', 'A', 'G', 'E', 'W'], | |
['V', 'P', 'K', 'M', 'V', 'G', 'F', 'T', 'R', 'A', 'D', 'I', 'T', 'I', 'O', 'N', 'R', 'Q'], | |
['O', 'Z', 'A', 'C', 'G', 'R', 'N', 'T', 'A', 'O', 'Y', 'D', 'L', 'G', 'X', 'C', 'M', 'C'] | |
]; | |
var grid1 = [ | |
['A', 'I', 'V', 'T', 'A', 'L', 'N', 'I', 'E', 'T', 'S', 'N', 'E', 'T', 'H', 'C', 'E', 'I', 'L'], | |
['G', 'N', 'E', 'T', 'H', 'E', 'R', 'L', 'A', 'N', 'D', 'S', 'N', 'P', 'V', 'A', 'A', 'P', 'D'], | |
['R', 'O', 'M', 'A', 'N', 'I', 'A', 'T', 'V', 'I', 'S', 'R', 'O', 'I', 'I', 'I', 'O', 'C', 'B'], | |
['U', 'T', 'E', 'J', 'V', 'I', 'E', 'T', 'Y', 'C', 'N', 'L', 'E', 'R', 'A', 'R', 'I', 'D', 'I'], | |
['O', 'V', 'P', 'M', 'J', 'J', 'S', 'C', 'O', 'B', 'A', 'A', 'T', 'C', 'T', 'P', 'N', 'E', 'G'], | |
['B', 'E', 'C', 'I', 'V', 'E', 'S', 'T', 'N', 'N', 'T', 'S', 'U', 'U', 'E', 'A', 'S', 'V', 'Y'], | |
['M', 'A', 'E', 'I', 'K', 'A', 'L', 'L', 'D', 'A', 'U', 'W', 'G', 'H', 'L', 'E', 'X', 'C', 'A'], | |
['E', 'G', 'J', 'N', 'L', 'A', 'T', 'V', 'O', 'A', 'R', 'A', 'B', 'R', 'T', 'B', 'R', 'Z', 'W'], | |
['X', 'E', 'J', 'W', 'N', 'B', 'S', 'L', 'E', 'V', 'L', 'F', 'E', 'N', 'U', 'I', 'V', 'G', 'R'], | |
['U', 'Y', 'P', 'D', 'I', 'V', 'U', 'S', 'A', 'E', 'A', 'Z', 'L', 'L', 'R', 'L', 'L', 'S', 'O'], | |
['L', 'R', 'R', 'M', 'A', 'C', 'T', 'P', 'N', 'M', 'T', 'K', 'G', 'T', 'N', 'V', 'P', 'N', 'N'], | |
['I', 'A', 'A', 'N', 'A', 'O', 'E', 'I', 'E', 'I', 'Y', 'A', 'I', 'J', 'N', 'S', 'K', 'D', 'J'], | |
['L', 'G', 'N', 'I', 'N', 'C', 'A', 'L', 'W', 'R', 'R', 'H', 'U', 'A', 'E', 'D', 'R', 'N', 'D'], | |
['I', 'N', 'I', 'I', 'T', 'R', 'E', 'S', 'A', 'I', 'H', 'V', 'M', 'L', 'J', 'N', 'A', 'A', 'J'], | |
['N', 'U', 'A', 'V', 'K', 'A', 'A', 'D', 'A', 'N', 'P', 'C', 'A', 'O', 'V', 'A', 'M', 'L', 'Y'], | |
['U', 'H', 'Z', 'U', 'V', 'J', 'O', 'G', 'O', 'R', 'D', 'W', 'E', 'V', 'J', 'L', 'N', 'G', 'L'], | |
['N', 'E', 'D', 'E', 'W', 'S', 'B', 'R', 'N', 'N', 'U', 'V', 'J', 'Z', 'T', 'E', 'E', 'N', 'A'], | |
['D', 'S', 'U', 'R', 'A', 'L', 'E', 'B', 'C', 'T', 'I', 'I', 'G', 'I', 'C', 'R', 'D', 'E', 'T'], | |
['D', 'N', 'A', 'L', 'N', 'I', 'F', 'G', 'E', 'R', 'M', 'A', 'N', 'Y', 'W', 'I', 'M', 'E', 'I']]; | |
var words1 = ['AUSTRIA', 'BELARUS', 'BELGIUM', 'BULGARIA', 'CROATIA', 'CZECHREPUBLIC', 'DENMARK', 'ENGLAND', 'ESTONIA', | |
'FINLAND', 'FRANCE', 'GERMANY', 'GREECE', 'HUNGARY', 'ICELAND', 'IRELAND', 'ITALY', 'LATVIA', 'LIECHTENSTEIN', | |
'LITHUANIA', 'LUXEMBOURG', 'MACEDONIA', 'MALTA', 'NETHERLANDS', 'NORWAY', 'POLAND', 'PORTUGAL', 'ROMANIA', | |
'SCOTLAND', 'SLOVAKIA', 'SPAIN', 'SWEDEN', 'SWITZERLAND', 'UKRAINE', 'WALES']; | |
var grid2 = [ | |
['K', 'P', 'E', 'N', 'C', 'I', 'L', 'C', 'A', 'D', 'N', 'E', 'G ', 'A', 'H', 'L', 'B'], | |
['Y', 'I', 'L', 'E', 'T', 'T', 'E', 'R', 'S', 'L', 'B', 'M', 'E', 'M', 'O', 'Y', 'T'], | |
['E', 'J', 'S', 'J', 'L', 'K', 'I', 'C', 'R', 'P', 'B', 'C', 'C', 'J', 'X', 'R', 'D'], | |
['C', 'E', 'G', 'V', 'Y', 'F', 'Q', 'X', 'H', 'L', 'M', 'M', 'O', 'K', 'E', 'A', 'M'], | |
['U', 'T', 'N', 'E', 'M', 'U', 'C', 'O', 'D', 'A', 'I', 'A', 'V', 'G', 'M', 'N', 'W'], | |
['D', 'M', 'R', 'N', 'T', 'J', 'P', 'R', 'L', 'R', 'I', 'A', 'T', 'K', 'S', 'O', 'T'], | |
['I', 'W', 'P', 'E', 'X', 'G', 'A', 'E', 'E', 'W', 'M', 'R', 'M', 'S', 'T', 'I', 'S'], | |
['A', 'Z', 'W', 'H', 'P', 'D', 'C', 'T', 'N', 'I', 'E', 'G ', 'A', 'E', 'A', 'T', 'T'], | |
['R', 'R', 'U', 'J', 'N', 'A', 'U', 'F', 'R', 'S', 'T', 'E', 'P', 'D', 'P', 'C', 'A'], | |
['Y', 'I', 'D', 'E', 'E', 'P', 'P', 'L', 'P', 'R', 'O', 'D', 'P', 'T', 'L', 'I', 'T'], | |
['T', 'R', 'L', 'N', 'M', 'P', 'O', 'G', 'U', 'B', 'N', 'N', 'O', 'R', 'E', 'D', 'I'], | |
['X', 'A', 'O', 'O', 'L', 'F', 'N', 'L', 'L', 'H', 'R', 'A', 'I', 'A', 'R', 'E', 'O'], | |
['C', 'H', 'C', 'V', 'F', 'I', 'E', 'O', 'C', 'X', 'R', 'H', 'N', 'V', 'D', 'T', 'N'], | |
['P', 'T', 'S', 'I', 'T', 'R', 'T', 'X', 'S', 'R', 'O', 'T', 'T', 'E', 'L', 'R', 'E'], | |
['B', 'A', 'C', 'E', 'G', 'T', 'E', 'T', 'R', 'V', 'I', 'R', 'M', 'L', 'R', 'O', 'R'], | |
['K', 'E', 'E', 'O', 'E', 'L', 'X', 'I', 'D', 'H', 'G', 'O', 'E', 'S', 'O', 'P', 'Y'], | |
['Y', 'M', 'X', 'R', 'A', 'F', 'X', 'B', 'O', 'S', 'S', 'H', 'N', 'X', 'Z', 'E', 'C'], | |
['L', 'X', 'C', 'A', 'V', 'H', 'U', 'A', 'E', 'R', 'I', 'S', 'T', 'B', 'T', 'R', 'X'], | |
['G', 'A', 'H', 'J', 'F', 'T', 'O', 'G', 'U', 'N', 'I', 'G ', 'N', 'I', 'L', 'I', 'F'] | |
]; | |
var words2 = ['AGENDA', 'APPOINTMENT', 'BLOTTER', 'BOSS', 'CALENDAR', 'CHAIR', 'COMPUTER', 'DESK', 'DIARY', | |
'DICTIONARY', 'DOCUMENT', 'FAX', 'FILING', 'LETTER', 'MAIL', 'MEETING', 'MEMO', 'NOTE', 'OFFICE', 'PAPER', | |
'PENCIL', 'PENS', 'PHONE', 'REPORT', 'RULER', 'SHORTHAND', 'STAMPS', 'STATIONERY', 'STAPLER', 'TRAVEL', 'XEROX']; | |
var default_words = [ | |
'throne', | |
'palace', | |
'tradition', | |
'family', | |
'descent', | |
'royal', | |
'kingdom', | |
'prince', | |
'law', | |
'earl', | |
'government', | |
'charter', | |
'sovereign', | |
'orb', | |
'commons' | |
]; | |
class Chronometer { | |
constructor() { | |
this.elapsed = 0; | |
this.timer = setInterval(() => this.tick(), 1000); | |
} | |
tick() { | |
this.elapsed = this.elapsed + 1; | |
} | |
getElapsed() { | |
return this.elapsed; | |
} | |
} | |
function wordsToUpperCase(words) { | |
for (var i = 0; i < words.length; i++) { | |
words[i] = words[i].toUpperCase(); | |
} | |
return words; | |
} | |
class WordSearch { | |
constructor(o) { | |
let obj = o ? o : { | |
'words': default_words, | |
'wordsGrid': default_matrix, | |
'onFindWord': () => null, | |
'parentId': "mydiv" | |
}; | |
this.wordsGrid = obj.wordsGrid; | |
this.words = wordsToUpperCase(obj.words); | |
this.onFindWord = obj.onFindWord; | |
this.rowSize = this.wordsGrid.length; | |
this.colSize = this.wordsGrid[0].length; | |
this.timeToFind = new Array(this.words.length).fill(-1); | |
this.matrix = this.initMatrix(); | |
this.parent = document.getElementById(obj.parentId); | |
this.timer = new Chronometer(); | |
this.drawGameArea(); | |
this.displayScore(); | |
} | |
drawGameArea() { | |
var scoreArea = document.createElement("h2"); | |
var scoreLabel = document.createElement("div"); | |
scoreLabel.id = "score"; | |
scoreArea.append(scoreLabel); | |
this.parent.appendChild(scoreArea); | |
var gridArea = document.createElement("section"); | |
gridArea.setAttribute("class", "ws-area"); | |
this.drawMatrix(gridArea); | |
this.parent.appendChild(gridArea); | |
var wordsArea = document.createElement("ul"); | |
wordsArea.setAttribute("class", "ws-words"); | |
this.drawWordList(wordsArea); | |
this.parent.appendChild(wordsArea); | |
} | |
getScore() { | |
return this.timeToFind.map(i => i > 0 ? 1 : 0).reduce((a, b) => a + b); | |
} | |
getRemaining() { | |
return this.timeToFind.map(i => i > 0 ? 0 : 1).reduce((a, b) => a + b); | |
} | |
getTiming() { | |
return this.timeToFind.slice(); | |
} | |
displayScore() { | |
document.getElementById("score").innerHTML = "Found " + this.getScore() + " out of " + this.words.length + " words so far."; | |
} | |
initMatrix() { | |
let matrix = []; | |
for (var row = 0; row < this.rowSize; row++) { | |
for (var col = 0; col < this.colSize; col++) { | |
var item = { | |
letter: this.wordsGrid[row][col], // Default value | |
row: row, | |
col: col | |
}; | |
if (!matrix[row]) { | |
matrix[row] = []; | |
} | |
matrix[row][col] = item; | |
} | |
} | |
return matrix; | |
} | |
drawWordList(target) { | |
var words = this.words; | |
for (var i = 0; i < words.length; i++) { | |
var liEl = document.createElement('li'); | |
liEl.id = words[i]; | |
liEl.setAttribute('class', 'ws-word'); | |
liEl.setAttribute("text-decoration", "none"); | |
liEl.innerHTML = words[i]; | |
target.appendChild(liEl); | |
} | |
} | |
getItem(row, col) { | |
return (this.matrix[row] ? this.matrix[row][col] : undefined); | |
} | |
getItems(rowFrom, colFrom, rowTo, colTo) { | |
var items = []; | |
if (rowFrom === rowTo || colFrom === colTo || Math.abs(rowTo - rowFrom) === Math.abs(colTo - colFrom)) { | |
var shiftY = (rowFrom === rowTo) ? 0 : (rowTo > rowFrom) ? 1 : -1, | |
shiftX = (colFrom === colTo) ? 0 : (colTo > colFrom) ? 1 : -1, | |
row = rowFrom, | |
col = colFrom; | |
items.push(this.getItem(row, col)); | |
do { | |
row += shiftY; | |
col += shiftX; | |
items.push(this.getItem(row, col)); | |
} while (row !== rowTo || col !== colTo); | |
} | |
return items; | |
} | |
drawMatrix(target) { | |
var rowcount = this.rowSize; | |
var columncount = this.colSize; | |
for (var row = 0; row < rowcount; row++) { | |
// New row | |
var divEl = document.createElement('div'); | |
divEl.setAttribute('class', 'ws-row'); | |
target.appendChild(divEl); | |
for (var col = 0; col < columncount; col++) { | |
var item = this.matrix[row][col]; | |
var cvEl = document.createElement('canvas'); | |
cvEl.setAttribute('class', 'ws-col'); | |
cvEl.setAttribute('width', 25); | |
cvEl.setAttribute('height', 25); | |
// Fill text in middle center | |
var x = cvEl.width / 2, | |
y = cvEl.height / 2; | |
var ctx = cvEl.getContext('2d'); | |
ctx.font = '400 18px Calibri'; | |
ctx.textAlign = 'center'; | |
ctx.textBaseline = 'middle'; | |
ctx.fillStyle = '#333'; // Text color | |
ctx.fillText(item.letter, x, y); | |
// Add event listeners | |
cvEl.addEventListener('mousedown', this.handleMousedown(item)); | |
cvEl.addEventListener('mouseover', this.handleMouseover(item)); | |
cvEl.addEventListener('mouseup', this.handleMouseup()); | |
divEl.appendChild(cvEl); | |
} | |
} | |
} | |
handleMouseover(item) { | |
var that = this; | |
return function () { | |
if (that.selectFrom) { | |
that.selected = that.getItems(that.selectFrom.row, that.selectFrom.col, item.row, item.col); | |
that.clearHighlight(); | |
for (var i = 0; i < that.selected.length; i++) { | |
var current = that.selected[i], | |
row = current.row + 1, | |
col = current.col + 1, | |
el = document.querySelector('.ws-row:nth-child(' + row + ') .ws-col:nth-child(' + col + ')'); | |
el.className += ' ws-selected'; | |
} | |
} | |
} | |
} | |
handleMouseup() { | |
var that = this; | |
return function () { | |
that.selectFrom = null; | |
that.clearHighlight(); | |
that.validateSelection(that.selected); | |
that.selected = []; | |
} | |
} | |
handleMousedown(item) { | |
var that = this; | |
return function () { | |
that.selectFrom = item; | |
} | |
} | |
clearHighlight() { | |
var selectedEls = document.querySelectorAll('.ws-selected'); | |
for (var i = 0; i < selectedEls.length; i++) { | |
selectedEls[i].classList.remove('ws-selected'); | |
} | |
} | |
markAsFound(selected) { | |
for (var i = 0; i < selected.length; i++) { | |
var row = selected[i].row + 1, | |
col = selected[i].col + 1, | |
el = document.querySelector('.ws-row:nth-child(' + row + ') .ws-col:nth-child(' + col + ')'); | |
el.classList.add('ws-found'); | |
} | |
this.displayScore(); | |
this.onFindWord(); | |
} | |
validateSelection(selected) { | |
var wordSelected = ''; | |
for (var i = 0; i < selected.length; i++) { | |
wordSelected += selected[i].letter; | |
} | |
var wordSelectedR = wordSelected.split('').reverse().join(''); | |
var indexOfWord = this.words.indexOf(wordSelected); | |
var indexOfWordR = this.words.indexOf(wordSelectedR); | |
if (indexOfWord > -1) { | |
if (this.timeToFind[indexOfWord] === -1) { | |
this.timeToFind[indexOfWord] = this.timer.getElapsed(); | |
var ele = document.getElementById(wordSelected); | |
ele.style.setProperty("text-decoration", "line-through"); | |
ele.style.setProperty("color", "red"); | |
ele.setAttribute("text-decoration", "line-through"); | |
this.markAsFound(selected); | |
} | |
} | |
if (indexOfWordR > -1) { | |
if (this.timeToFind[indexOfWordR] === -1) { | |
this.timeToFind[indexOfWordR] = this.timer.getElapsed(); | |
var ele = document.getElementById(wordSelectedR); | |
ele.style.setProperty("text-decoration", "line-through"); | |
ele.style.setProperty("color", "red"); | |
ele.setAttribute("text-decoration", "line-through"); | |
this.markAsFound(selected); | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment