D3
OG
Old school D3 from simpler times
All examples
By author
By category
About
allenbh
Full window
Github gist
Cryptogram Interactive Puzzle
<!-- Cryptogram Interactive Puzzle Solve the puzzle by replacing letters to reveal the hidden message. Use the keyboard and mouse to move the cursor. Type a letter to make a guess and advance the cursor. Correct mistakes by typing over them or with backspace and delete. --> <style> .puzzle { font-family: monospace; font-size: 2em } .guess { font-style: normal; font-weight: bold; color: darkslateblue} .solved { color: darkgreen} .error { color: red } .cursor { background-color: lightgray } .curchr { text-decoration: underline } </style> <body> <h1>Cryptogram</h1> <p>Solve the puzzle by replacing letters to reveal the hidden message.</p> <p>Use the keyboard and mouse to move the cursor. Type a letter to enter a guess and advance the cursor. Correct mistakes by typing over them or with backspace and delete.</p> <p id="puzzle"></p> <script src="https://d3js.org/d3.v3.min.js" charset="utf-8"></script> <script> var alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; var encodeCypher = {}; var decodeCypher = {}; var textClear = ""; var textAlpha = ""; var textKey = ""; var textHidden = ""; var textSolved = ""; function setPuzzle(text) { textClear = text; textAlpha = makeAlpha(textClear); textKey = makeKey(textAlpha.length); encodeCypher = makeCypher(textAlpha, textKey); decodeCypher = makeCypher(textKey, textKey.toLowerCase()); textHidden = translate(textClear, encodeCypher, true); textSolved = translate(textHidden, decodeCypher, true); } function setGuess(cypherVal, clearVal) { cypherVal = cypherVal.toUpperCase(); clearVal = clearVal.toUpperCase(); if(decodeCypher.hasOwnProperty(cypherVal)) { decodeCypher[cypherVal] = clearVal; textSolved = translate(textHidden, decodeCypher, true); } } function clearGuess(cypherVal) { cypherVal = cypherVal.toUpperCase(); if(decodeCypher.hasOwnProperty(cypherVal)) { decodeCypher[cypherVal] = cypherVal.toLowerCase(); textSolved = translate(textHidden, decodeCypher, true); } } function makeCypher(from, to) { var cypher = {}; for(var i = 0; i < from.length; ++i) { cypher[from.charAt(i)] = to.charAt(i); } return cypher; } function translate(text, cypher, preserve) { var arry = text.split(""); for(var i = 0; i < arry.length; ++i) { var arryval = arry[i].toUpperCase(); if(cypher.hasOwnProperty(arryval)) { var cypherval = cypher[arryval]; if(!preserve) { arry[i] = cypherval; } else { if(arryval != arry[i]) { arry[i] = cypherval.toLowerCase(); } else { arry[i] = cypherval.toUpperCase(); } } } } return arry.join(""); } function makeAlpha(text) { var arry = text.toUpperCase().replace(/[^A-Z]/g,"").split(""); arry.sort(); var i = 0, j = 0; while(j < arry.length) { arry[i] = arry[j]; while(j < arry.length && arry[i] === arry[j]) { ++j; } ++i; } return arry.slice(0, i).join(""); } function scramble(alpha) { var arry = alpha.split(""); for(var i = arry.length; 0 < i; --i) { var j = Math.floor(i * Math.random()); var tmp = arry[i-1]; arry[i-1] = arry[j]; arry[j] = tmp; } return arry.join(""); } function makeKey(length) { return scramble(alphabet).substr(0, length); } </script> <script> var puzzleOptions = [ "By three methods we may learn wisdom: first, by reflection, which is noblest; second, by imitation, which is easiest; and third, by experience, which is the bitterest. --Confucius", "Computers make it easier to do a lot of things, but most of the things they make it easier to do don't need to be done. --Andy Rooney", "The typewriting machine, when played with expression, is no more annoying than the piano when played by a sister or near relation. --Oscar Wilde.", "The first rule of any technology used in a business is that automation applied to an efficient operation will magnify the efficiency. The second is that automation applied to an inefficient operation will magnify the inefficiency. --Bill Gates", ]; setPuzzle(puzzleOptions[Math.floor(Math.random()*puzzleOptions.length)]); var cursorPos = 0; var cursorBlink = true; var cursorTimer = null; var puzzle = d3.selectAll("#puzzle"); puzzle.classed("puzzle", true); var data = puzzle.selectAll("*").data(d3.range(textSolved.length)); data.enter().append("span"); data.exit().remove(); data.order(); function getTextAt(i) { return textSolved.charAt(i); } function getGuessAt(i) { var hiddenVal = textHidden.charAt(i).toUpperCase(); if(!decodeCypher.hasOwnProperty(hiddenVal)) { return false; } else { var decodeVal = decodeCypher[hiddenVal]; return decodeVal === decodeVal.toUpperCase(); } } function update() { var curChr = textHidden.charAt(cursorPos).toUpperCase(); if (curChr === curChr.toLowerCase()) curChr = undefined; var guessCount = {}; for(var k in decodeCypher) { var decodeVal = decodeCypher[k]; if(decodeVal === decodeVal.toUpperCase()) { guessCount[decodeVal] = 1 + (guessCount[decodeVal] || 0); } } function getErrorAt(i) { if(!getGuessAt(i)) { return false; } else { var decodeVal = textSolved.charAt(i).toUpperCase(); return guessCount[decodeVal] > 1; } } var elems = puzzle.selectAll("*"); elems.text(getTextAt); elems.classed("guess", getGuessAt); elems.classed("error", getErrorAt); elems.classed("curchr", function(i) { return curChr === textHidden.charAt(i).toUpperCase(); }); elems.classed("solved", textSolved === textClear); elems.on("click", cursorUpdate); } function cursorCallback() { var data = puzzle.selectAll("*"); data.classed("cursor", function(d) { return d === cursorPos ? cursorBlink : false; }); cursorBlink = !cursorBlink; } function cursorUpdate(pos) { if(cursorTimer != null) { clearInterval(cursorTimer); } while(pos < 0) { pos += textHidden.length; } while(textHidden.length <= pos) { pos -= textHidden.length; } cursorPos = pos; cursorBlink = true; update(); cursorCallback(); cursorTimer = setInterval(cursorCallback, 800); } function setGuessAtCursor(val) { setGuess(textHidden.charAt(cursorPos), val); update(); } function clearGuessAtCursor() { clearGuess(textHidden.charAt(cursorPos)); update(); } function updateKey(key) { switch(key) { case 37: //left arrow cursorUpdate(cursorPos-1); return true; case 32: //space case 39: //right arrow cursorUpdate(cursorPos+1); return true; case 36: //home cursorUpdate(0); return true; case 35: //end cursorUpdate(-1); return true; case 8: //backspace cursorUpdate(cursorPos-1); clearGuessAtCursor(); return true; case 46: //delete clearGuessAtCursor(); return true; } // letter if(65 <= key && key < 91) { var val = String.fromCharCode(key).toUpperCase(); setGuessAtCursor(val.toUpperCase()); cursorUpdate(cursorPos+1); return true; } return false } function keyDownCallback() { if(updateKey(d3.event.keyCode || d3.event.which)) d3.event.preventDefault(); } d3.selectAll("body").on("keydown", keyDownCallback); cursorUpdate(0); </script> </body>
Modified
http://d3js.org/d3.v3.min.js
to a secure url
https://d3js.org/d3.v3.min.js