Add interactiveness to HTML outputs. #4
					 1 changed files with 107 additions and 5 deletions
				
			
		|  | @ -5,7 +5,109 @@ import ch.fritteli.labyrinth.generator.renderer.Renderer; | |||
| import lombok.NonNull; | ||||
| 
 | ||||
| public class HTMLRenderer implements Renderer<String> { | ||||
|     private static final String POSTAMBLE = "</body></html>"; | ||||
| 
 | ||||
|     private static final String POSTAMBLE = "<script>" | ||||
|             + "let userPath = [];" | ||||
|             + "const DIR_UNDEF = -1;" | ||||
|             + "const DIR_SAME = 0;" | ||||
|             + "const DIR_UP = 1;" | ||||
|             + "const DIR_RIGHT = 2;" | ||||
|             + "const DIR_DOWN = 3;" | ||||
|             + "const DIR_LEFT = 4;" | ||||
|             + "function getCoords(cell) {" | ||||
|             + "    return {" | ||||
|             + "        x: cell.cellIndex," | ||||
|             + "        y: cell.parentElement.rowIndex" | ||||
|             + "    };" | ||||
|             + "}" | ||||
|             + "function distance(prev, next) {" | ||||
|             + "    return Math.abs(prev.x - next.x) + Math.abs(prev.y - next.y);" | ||||
|             + "}" | ||||
|             + "function direction(prev, next) {" | ||||
|             + "    const dist = distance(prev, next);" | ||||
|             + "    if (dist === 0) {" | ||||
|             + "        return DIR_SAME;" | ||||
|             + "    }" | ||||
|             + "    if (dist !== 1) {" | ||||
|             + "        return DIR_UNDEF;" | ||||
|             + "    }" | ||||
|             + "    if (next.x === prev.x) {" | ||||
|             + "        if (next.y === prev.y + 1) {" | ||||
|             + "            return DIR_DOWN;" | ||||
|             + "        }" | ||||
|             + "        return DIR_UP;" | ||||
|             + "    }" | ||||
|             + "    if (next.x === prev.x + 1) {" | ||||
|             + "        return DIR_RIGHT;" | ||||
|             + "    }" | ||||
|             + "    return DIR_LEFT;" | ||||
|             + "}" | ||||
|             + "(function () {" | ||||
|             + "    const labyrinthTable = document.getElementById(\"labyrinth\");" | ||||
|             + "    const labyrinthCells = labyrinthTable.getElementsByTagName(\"td\");" | ||||
|             + "    const start = {x: 0, y: 0};" | ||||
|             + "    const end = {" | ||||
|             + "        x: labyrinthTable.getElementsByTagName(\"tr\")[0].getElementsByTagName(\"td\").length - 1," | ||||
|             + "        y: labyrinthTable.getElementsByTagName(\"tr\").length - 1" | ||||
|             + "    };" | ||||
|             + "    for (let i = 0; i < labyrinthCells.length; i++) {" | ||||
|             + "        let cell = labyrinthCells.item(i);" | ||||
|             + "        cell.onclick = (event) => {" | ||||
|             + "            let target = event.target;" | ||||
|             + "            const coords = getCoords(target);" | ||||
|             + "            if (coords.x === end.x && coords.y === end.y) {" | ||||
|             + "                alert(\"HOORAY! You did it! Congratulations!\")" | ||||
|             + "            }" | ||||
|             + "            if (userPath.length === 0) {" | ||||
|             + "                if (coords.x === start.x && coords.y === start.y) {" | ||||
|             + "                    userPath.push(coords);" | ||||
|             + "                    target.classList.toggle(\"user\");" | ||||
|             + "                }" | ||||
|             + "            } else {" | ||||
|             + "                const dir = direction(userPath[userPath.length - 1], coords);" | ||||
|             + "                switch (dir) {" | ||||
|             + "                    case DIR_UNDEF:" | ||||
|             + "                        return;" | ||||
|             + "                    case DIR_SAME:" | ||||
|             + "                        userPath.pop();" | ||||
|             + "                        target.classList.toggle(\"user\");" | ||||
|             + "                        return;" | ||||
|             + "                    default:" | ||||
|             + "                        if (userPath.find(value => value.x === coords.x && value.y === coords.y)) {" | ||||
|             + "                            return;" | ||||
|             + "                        } else {" | ||||
|             + "                            switch (dir) {" | ||||
|             + "                                case DIR_UP:" | ||||
|             + "                                    if (target.classList.contains(\"bottom\")) {" | ||||
|             + "                                        return;" | ||||
|             + "                                    }" | ||||
|             + "                                    break;" | ||||
|             + "                                case DIR_RIGHT:" | ||||
|             + "                                    if (target.classList.contains(\"left\")) {" | ||||
|             + "                                        return;" | ||||
|             + "                                    }" | ||||
|             + "                                    break;" | ||||
|             + "                                case DIR_DOWN:" | ||||
|             + "                                    if (target.classList.contains(\"top\")) {" | ||||
|             + "                                        return;" | ||||
|             + "                                    }" | ||||
|             + "                                    break;" | ||||
|             + "                                case DIR_LEFT:" | ||||
|             + "                                    if (target.classList.contains(\"right\")) {" | ||||
|             + "                                        return;" | ||||
|             + "                                    }" | ||||
|             + "                                    break;" | ||||
|             + "                            }" | ||||
|             + "                            userPath.push(coords);" | ||||
|             + "                            target.classList.toggle(\"user\");" | ||||
|             + "                            return;" | ||||
|             + "                        }" | ||||
|             + "                }" | ||||
|             + "            }" | ||||
|             + "        };" | ||||
|             + "    }" | ||||
|             + "})();" | ||||
|             + "</script></body></html>"; | ||||
| 
 | ||||
|     private HTMLRenderer() { | ||||
|     } | ||||
|  | @ -23,7 +125,7 @@ public class HTMLRenderer implements Renderer<String> { | |||
|         } | ||||
|         final Generator generator = new Generator(labyrinth); | ||||
|         final StringBuilder sb = new StringBuilder(this.getPreamble(labyrinth)); | ||||
|         sb.append("<table>"); | ||||
|         sb.append("<table id=\"labyrinth\">"); | ||||
|         while (generator.hasNext()) { | ||||
|             sb.append(generator.next()); | ||||
|         } | ||||
|  | @ -39,11 +141,12 @@ public class HTMLRenderer implements Renderer<String> { | |||
|                 "<meta charset=\"utf-8\">" + | ||||
|                 "<style>" + | ||||
|                 "table{border-collapse:collapse;}" + | ||||
|                 "td{border:0 solid black;height:1em;width:1em;}" + | ||||
|                 "td{border:0 solid black;height:1em;width:1em;cursor:pointer;}" + | ||||
|                 "td.top{border-top-width:1px;}" + | ||||
|                 "td.right{border-right-width:1px;}" + | ||||
|                 "td.bottom{border-bottom-width:1px;}" + | ||||
|                 "td.left{border-left-width:1px;}" + | ||||
|                 "td.user{background:hotpink;}" + | ||||
|                 "</style>" + | ||||
|                 "<script>" + | ||||
|                 "let solution = false;" + | ||||
|  | @ -59,7 +162,6 @@ public class HTMLRenderer implements Renderer<String> { | |||
|                 "</script>" + | ||||
|                 "</head>" + | ||||
|                 "<body>" + | ||||
|                 "<input type=\"checkbox\" onclick=\"toggleSolution()\">show solution</input>"; | ||||
|                 "<input id=\"solutionbox\" type=\"checkbox\" onclick=\"toggleSolution()\"/><label for=\"solutionbox\">show solution</label>"; | ||||
|     } | ||||
| 
 | ||||
| } | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue