let currentColor = ''
const colorsList = [
'white',
'black',
'',
'#F44848',
'#ab0c0c',
'#F29E4A',
'#F0F04C',
'#A1F051',
'#53EE53',
'#59EEA3',
'#5BECEC',
'#5DA3EA',
'#6262EA',
'#A664E8',
'#E869E8',
'#E66BA8',
'#E67070',
"#333",
'#231f20',
'#e32119',
'#ffd300',
'#e1c8b4',
'#618227'
]
const palette = document.getElementById('palette');
colorsList.forEach(color => {
const btn = document.createElement('button')
Object.assign(btn.style, {
background: color,
display: 'inline-block',
width: '40px',
height: '40px',
border: '1px solid black'
})
if (color === currentColor) {
btn.className = 'active'
}
palette.appendChild(btn)
btn.addEventListener('click', (e) => {
currentColor = color
e.preventDefault()
document.querySelector('#palette button.active')?.classList.remove('active');
btn.classList.add('active')
})
})
function renderAllLevels() {
allLevels.forEach((level, levelIndex) => {
addLevelEditorToList(level, levelIndex)
})
}
function addLevelEditorToList(level, levelIndex) {
const {name, bricks, size, svg,color} = level
let div = document.createElement('div')
div.innerHTML = `
`;
document.getElementById('levels').appendChild(div)
renderLevelBricks(levelIndex)
updateLevelBackground(levelIndex)
}
function updateLevelBackground(levelIndex){
const div=document.getElementById("bricks-of-"+levelIndex)
const {svg, color}= allLevels[levelIndex]
Object.assign(div.style, svg ?
{backgroundImage:`url('data:image/svg+xml,${encodeURIComponent(svg)}')`, backgroundColor:'transparent'} :
{backgroundImage:'none', backgroundColor:color||'#111'}
)
}
function renderLevelBricks(levelIndex) {
const {size, bricks} = allLevels[levelIndex]
const buttons = []
for (let x = 0; x < size; x++) {
for (let y = 0; y < size; y++) {
const index = y * size + x
buttons.push(``)
}
}
const div = document.getElementById("bricks-of-" + levelIndex)
div.innerHTML = buttons.join('')
Object.assign(div.style, {
width: size * 40 + 'px',
height: size * 40 + 'px'
})
}
document.getElementById('levels').addEventListener('change', e => {
const levelIndexStr = e.target.getAttribute('data-level')
if ( levelIndexStr) {
const levelIndex = parseInt(levelIndexStr)
const level = allLevels[levelIndex]
if( e.target.getAttribute('type') === 'color'){
level.color = e.target.value
level.svg = ''
updateLevelBackground(levelIndex)
}else if( e.target.getAttribute('type') === 'checkbox' && e.target.hasAttribute('data-field')){
level[e.target.getAttribute('data-field')] = !!e.target.checked
}
save()
}
})
document.getElementById('levels').addEventListener('click', e => {
const resize = e.target.getAttribute('data-offset-level-size')
const moveX = e.target.getAttribute('data-offset-x')
const moveY = e.target.getAttribute('data-offset-y')
const levelIndexStr = e.target.getAttribute('data-level')
if (!levelIndexStr) return
if (e.target.tagName!=='BUTTON') return
const levelIndex = parseInt(levelIndexStr)
const level = allLevels[levelIndex]
const {bricks, size} = level;
if (resize) {
const newSize = size + parseInt(resize)
const newBricks = []
for (let x = 0; x < Math.min(size, newSize); x++) {
for (let y = 0; y < Math.min(size, newSize); y++) {
newBricks[y * newSize + x] = bricks[y * size + x] || ''
}
}
level.size = newSize;
level.bricks = newBricks;
} else if (moveX && moveY) {
const dx = parseInt(moveX), dy = parseInt(moveY)
const moved = []
for (let x = 0; x < size; x++) {
for (let y = 0; y < size; y++) {
moved[(y + dy) * size + (x + dx)] = bricks[y * size + x] || ''
}
}
level.bricks = moved;
} else if (e.target.getAttribute('data-rename')) {
const newName = prompt('Name ? ', level.name)
if (newName) {
level.name = newName
e.target.textContent = newName
}
}else if (e.target.getAttribute('data-delete')) {
if (confirm('Delete level')) {
allLevels=allLevels.filter((l,i)=>i!==levelIndex)
save().then(()=>window.location.reload())
}
}else if(e.target.getAttribute('data-set-bg-svg')){
const newBg = prompt('New svg code',level.svg||'')
if(newBg){
level.svg=newBg
level.color = ''
}
updateLevelBackground(levelIndex)
}
renderLevelBricks(levelIndex)
save()
}, true)
let applying = undefined
function colorPixel(e) {
if (typeof applying === 'undefined') return
const index = e.target.getAttribute('data-set-color-of')
const level = e.target.getAttribute('data-level')
if (index && level) {
const levelIndex = parseInt(level)
e.target.style.background = applying || 'transparent'
allLevels[levelIndex].bricks[index] = applying
}
}
document.getElementById('levels').addEventListener('mousedown', e => {
const index = e.target.getAttribute('data-set-color-of')
const level = e.target.getAttribute('data-level')
if (index && level) {
const before = allLevels[parseInt(level)].bricks[parseInt(index)] || ''
applying = before === currentColor ? '' : currentColor
colorPixel(e)
}
})
document.getElementById('levels').addEventListener('mouseenter', e => {
if (typeof applying !== undefined) {
colorPixel(e)
}
}, true)
document.addEventListener('mouseup', e => {
applying = undefined
save()
})
document.getElementById('new-level').addEventListener('click', e => {
const name = prompt("Name ? ")
if (!name) return;
allLevels.push({
name,
size: 8,
bricks: ['white'],
svg: '',
})
const levelIndex = allLevels.length - 1
addLevelEditorToList(allLevels[levelIndex], levelIndex)
save()
}, true)
renderAllLevels()
function save() {
return fetch('/', {
method: 'POST', headers: {
'Content-Type': 'text/plain'
},
body: 'let allLevels=' + JSON.stringify(allLevels, null, 2)
})
}