List Grid Part 6: Palette
by nevkatz
HTML
<script src="https://unpkg.com/vue@2"></script>
<!-- set the root -->
<div id="root" v-on:mousedown="isDown = true" v-on:mouseup="isDown=false">
<div id="palette-container">
<ul id="palette">
<template v-for="(type,idx) in numTypes">
<li :data-type="idx" @click="setType">{{ idx }} </li>
</template>
</ul>
</div>
<div id="map-container">
<div>
<input id="numCols" type="range" min="1" max="16" v-model.number="numCols" v-on:change="setMap"/>
<label for="numCols">Columns: {{ numCols }} </label>
</div>
<div>
<input id="numRows" type="range" min="1" max="16" v-model.number="numRows" v-on:change="setMap"/>
<label for="numRows">Rows: {{ numRows }}</label>
</div>
<div>
<div id="curType" :data-type="currentType">
{{ currentType }}
</div>
</div>
<table id="theme-switcher">
<template v-for="row in numRows">
<tr>
<template v-for="cell in numCols">
<td data-type="0" :data-row="row" :data-col="cell" v-on:mouseover="checkMouse" v-on:mousedown="setCurrent">
<label>{{ row }}-{{ cell }}</label>
</td>
</template>
</tr>
</template>
</table>
</div>
<div id="output">
{{ printedMap }}
</div>
<!-- this is the markup that gets styled. -->
</div>
CSS
body {
font-family: Arial;
}
div#root {
display: flex;
flex-wrap: wrap;
}
div#output {
width: 100%;
font-family: Courier;
}
table {
border-collapse: collapse;
}
td {
width: 30px;
height: 30px;
padding: 0px;
font-size: 10px;
position: relative;
cursor: pointer;
border: 1px solid grey;
background-clip: padding-box;
background-color: lightgrey;
color: grey;
}
div#palette-container {
width: 40px;
margin-right: 20px;
}
div#map-container {
display: block;
}
ul#palette {
list-style-type: none;
padding-left: 0px;
}
ul#palette li {
width: 30px;
height: 30px;
cursor: pointer;
}
*[data-type="0"] {
background-color: #000;
color: #fff;
}
*[data-type="1"] {
background-color: lightgrey;
}
*[data-type="2"] {
background-color: navy;
color: white;
}
*[data-type="3"] {
background-color: brown;
color: white;
}
*[data-type="4"] {
background-color: green;
color: white;
}
*[data-type="5"] {
background-color: red;
color: white;
}
*[data-type="6"] {
background-color: orange;
}
*[data-type="7"] {
background-color: blue;
color: white;
}
td label {
pointer-events: none;
position: absolute;
top: 0px;
left: 0px;
border-width: 0px;
}
input[type="range"] {
position: relative;
top: 6px;
}
div#curType {
width: 30px;
height: 30px;
margin-bottom: 20px;
}
JavaScript
function init() {
//define a new vue that grabs onto the root element.
let vm = new Vue({
el:'#root',
data: {
isDown:false,
numTypes:7,
numRows:2,
numCols:2,
currentType:0,
lastClicked:"none",
map:{
grid:"hello"
},
printedMap:'none'
},
methods:{
showAlert:function() {
alert('alert!');
},
initMap:function () {
this.map.grid = [];
for (var i = 0; i < this.numRows; i++) {
this.map.grid[i] = [];
for (var j = 0; j < this.numCols; j++) {
this.map.grid[i][j] = 0;
}
}
this.printedMap = JSON.stringify(this.map);
},
setMap:function() {
// this.map.grid = [];
for (var i = 0; i < this.numRows; i++) {
if (!this.map.grid[i]) {
this.map.grid[i] = [];
for (var k = 0; k < this.numCols; ++k) {
this.map.grid[i][k] = 0;
}
}
else {
for (var j = 0; j < this.numCols; j++) {
if (this.map.grid[i][j] == undefined) {
this.map.grid[i][j] = 0;
}
// check for revealed cells.
let val = this.map.grid[i][j];
let row = document.querySelectorAll('tr')[i];
let cell = row.querySelectorAll('td')[j];
cell.setAttribute('data-type',val);
} // end for
}
}
this.printedMap = JSON.stringify(this.map);
},
updateMapItem:function(i,j,val) {
if (!this.map.grid[i]) {
this.map.grid[i] = [];
}
this.map.grid[i][j] = val;
this.printedMap = JSON.stringify(this.map);
},
checkMouse:function(e) {
if (this.isDown) {
...