Last active
July 27, 2022 15:14
-
-
Save gabor-m/0d562247c457b55ade0ee6fee63e75cf to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
$.state = function (val) { | |
if (val && typeof val === 'object' && typeof val.onChange === "function") { | |
throw new Error("Cannot put state into state"); | |
} | |
const handlers = []; | |
return { | |
onChange: function (f) { | |
handlers.push(f); | |
}, | |
get: function () { | |
return val; | |
}, | |
set: function (v) { | |
val = v; | |
handlers.forEach(function (h) { h(v); }); | |
} | |
}; | |
}; | |
$.html = function (strings, ...keys) { | |
let source = []; | |
strings.forEach(function (value, index) { | |
source.push(value); | |
source.push('<span data-placeholder="' + index + '"></span>'); | |
}); | |
source = source.join(""); | |
let $pseudoRoot = $('<div></div>'); | |
let $elem = $(source); | |
$pseudoRoot.append($elem); | |
$pseudoRoot.find('[data-placeholder]').each(function () { | |
function handleItem($e, item) { | |
if (item instanceof jQuery) { | |
$e.replaceWith(item); | |
} else if (item && typeof item === 'object' && typeof item.render === "function") { | |
$e.replaceWith(item.render()); | |
} else if (item && typeof item === 'object' && typeof item.onChange === "function") { | |
var unpacked = item.get(); | |
if (!(unpacked instanceof jQuery)) { | |
unpacked = $('<span data-text-placeholder>' + String(unpacked) + '</span>'); | |
} | |
$e.replaceWith(unpacked); | |
item.onChange((newVal) => { | |
handleItem(unpacked, newVal); | |
if (newVal instanceof jQuery) { | |
unpacked = newVal; | |
} | |
}); | |
} else { | |
if (typeof $e.data('text-placeholder') !== 'undefined') { | |
$e.html(item); | |
} else { | |
$e.replaceWith(String(item)); | |
} | |
} | |
} | |
let index = $(this).data('placeholder'); | |
let item = keys[+index]; | |
handleItem($(this), item); | |
}); | |
$elem.find('[data-placeholder]').remove(); | |
return $pseudoRoot.children(); | |
}; | |
class Counter { | |
constructor() { | |
this.c = $.state(0); | |
} | |
incr() { | |
this.c.set(this.c.get() + 1); | |
} | |
render() { | |
var $elem = $.html`<button>${ this.c }</button>`; | |
$elem.click(() => this.incr()); | |
return $elem; | |
} | |
} | |
var state = $.state($.html`<b>0</b>`); | |
setInterval(function () { state.set($.html`<b>${ Date.now() }</b>`); }, 1000); | |
var item = "Hello World"; | |
var $elem = $.html` | |
<div> | |
${ state } | |
<strong> | |
${ item } | |
</strong> | |
</div> | |
${ new Counter() } | |
`; | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment