toString hack
x=self+''
console.log(
x[8],x[9],x[6],' ',
x[3],x[1],x[2],' ',
x[10],x[4],x[8],' ',
x[5],x[1],x[11]
)
Hit the “Try it out” and open the console….
x=self+''
console.log(
x[8],x[9],x[6],' ',
x[3],x[1],x[2],' ',
x[10],x[4],x[8],' ',
x[5],x[1],x[11]
)
Hit the “Try it out” and open the console….
const oCan = (
d = document,
b = d.body,
canvas = b.appendChild(document.createElement('canvas')),
c = canvas.getContext('2d'),
props = [],
o = {},
docs = {},
cmds = [],
L,
k,
du,
j,
draw,
id
) => {
;(onresize = () => {
canvas.width = innerWidth
canvas.height = innerHeight
if (draw) {
clearTimeout(id)
id = setTimeout(() => cmds.forEach(v => draw(v)), 500)
}
})()
Object.assign(b.style, { margin: 0, height: '100%' })
// longer way: console.log(Object.getOwnPropertyNames(Object.getPrototypeOf(c)));
for (let i in c) props.push(i)
// make alphabetical since object keys have
// no order
props.sort().map(i => {
L = i.match(/[A-Z]/)
k = i[0]
if (L) k += L[0]
du = 0
if (o[k]) {
j = 0
while (o[k]) k += i[++j]
}
o[k] =
(typeof c[i])[0] == 'f'
? (...args) => c[i].apply(c, args)
: v => (c[i] = v)
docs[i] = k
})
console.log('docs:', JSON.stringify(docs, null, 2))
return (draw = (s, cmd, currFn, args = [], part, fn, num) => {
cmd = s.split(/\s+/)
cmds.push(s)
c.save()
for (let i = 0; i < cmd.length; i++) {
part = cmd[i]
fn = o[part]
if (fn && currFn != fn) {
currFn && currFn.apply(c, args)
currFn = fn
args = []
} else {
num = parseFloat(part)
args.push(!isNaN(num) ? num : part)
}
}
currFn && currFn.apply(c, args)
c.restore()
})
}
const c = oCan()
// `font` & text not suppoted
// make str a function so resize works?
c(`
fS #ccc
fR 0 0 400 ${innerHeight}
fS blue
fR 40 0 20 20
gCl difference
ro .25
fR 50 0 30 30
gCl source-over
fS rgba(200,100,9)
fR 100 100 40 40
`)
I’ve had this idea for a long time, never bothered doing it until now. I wrote it in a semi-golfed style for no reason… Anyway, this lets you write canvas code in a strange obfuscated syntax that looks like this:
c(`
fS #ccc
fR 0 0 400 ${innerHeight}
fS blue
fR 40 0 20 20
gCl difference
ro .25
fR 50 0 30 30
gCl source-over
fS rgba(200,100,9)
fR 100 100 40 40
`)
This snippet logs out some JSON that shows all the method aliases for the canvas context.
const spec = {
get(o, key) {
return o[key] != null ?
o[key] : o[key] = (...args) => {
const el = document.createElement(key);
args.forEach(arg => {
if (typeof arg === 'string') {
const span = document.createElement('span');
span.innerHTML = arg;
el.appendChild(span);
} else if (typeof arg === 'object') {
if (arg.tagName != null) {
el.appendChild(arg);
} else {
for (let i in arg) {
el.setAttribute(i, arg[i]);
}
}
}
});
return el;
}
},
set(o, key, v) {
o[key] = v;
}
}
const dom = new Proxy({}, spec);
document.body.appendChild(
dom.div(
dom.button('cool'),
dom.h2('some text', { style: 'font-style: italic' }),
dom.br(),
dom.input({ placeholder: 'zevan' })
)
);
const { div, input, label } = dom;
document.body.appendChild(
div(
label(
'Slider:',
{
for: 'slider',
style: 'padding:1em;display:block'
},
input({ id: 'slider', type: 'range' })
)
)
);
In this snippet a proxy is used that makes all html node tagNames
valid methods. Each method can take strings and HTMLElements
as arguments in any order to create a dom structure. This may look familiar to people who have looked a bit deeper into the inner workings of some of the popular UI libraries of the last decade.
const target = {}
let value = null;
Object.defineProperties(target, {
magic: {
get() {
console.log('- getter called::', value);
return value;
},
set(val) {
document.body.innerHTML += val + '<br>';
value = val;
}
}
});
target.magic = 'xyz';
target.magic = 'snippet';
target.magic = 'zone';
target.magic = '- last value';
console.log('getting', target.magic);
This snippet shows a way to add getters and setters to a specific key of an existing object. This is powerful for decorating configuration objects with special behaviors. This kind of thing can easily be created with a little more abstraction:
const image = view({
tag: 'img',
src: 'myImage.jpg',
x: '20%',
y: '20%',
size: '50%'
});
const prev = view({
tag: 'button',
x: () => image.x,
y: () => image.bottom
});
const next = view({
tag: 'button',
x: () => image.right - this.width,
y: () => image.bottom
});
const spec = {
get(o, key) {
console.log(key, ':: key');
return o[key] != null ?
o[key] : o[key] = () => {
document.body.innerHTML += `<div>${key}!</div>`;
return anyMethod();
}
},
set(o, key, v) {
o[key] = v;
}
};
const anyMethod = () => new Proxy({}, spec);
anyMethod().now()
.this().is()
.pretty()
.cool()
.confusing()
.evil()?.or()
.maybe().powerful()
['... what <b>do</b> <i>you</i><br>']()
.think();
Proxies can be used for all manner of strange “magic”. I can actually see some uses for this, might post in the next few days…