Allow explicit instantiation of cells
See original GitHub issueAccording to the official documentation, the canonical way to instantiate a cell is like this:
var x = {
$cell: true,
$type: 'div', // or some other element type
// ...
};
This automatically appends the cell to the end of the body tag (unless $type
is 'body'
, in which case it gets injected instead). But this is very limiting: the claim that you can reuse cells by simply pasting them into existing apps is weakened by the fact that you have no real control over where those cells end up in your document without using an iframe
.
Of course, as you are probably about to point out, there is already an undocumented solution to this problem:
var x = {
$type: 'div',
// ...
};
window.addEventListener('load', function() {
document.querySelector('#myContainerElement').$build(x);
});
This works well, although it’s a little unfortunate that we have to wait for the load
event because the $build
function hasn’t been added to the existing DOM elements yet. This feature is powerful and useful, and I think it should be (at the very least) officially documented and supported.
It would be even nicer if we didn’t have to wait for the load
event. Since we’ve already loaded the script by the time we get here, perhaps it would be better to put the $build
function on some existing object so we can access it immediately:
document.$build(document.querySelector('#myContainerElement'), x);
It might also be nice to add a $parent
key on the genotype that could be used to specify a (static) parent for the element:
<body>
<div id="myContainerElement"></div>
<script src="https://www.celljs.org/cell.js"></script>
<script>
var x = {
$cell: true,
$type: 'div',
$parent: document.querySelector('#myContainerElement'),
// ...
};
</script>
</body>
However, I hope you keep the imperative version as well, because it allows developers to avoid polluting the global namespace. For example:
// This does not work:
const x = {
$cell: true,
$type: 'div',
// ...
};
// But this does:
const y = {
$type: 'div',
// ...
};
window.addEventListener('load', () => {
document.querySelector('#myContainerElement').$build(y);
});
Issue Analytics
- State:
- Created 6 years ago
- Reactions:1
- Comments:9 (4 by maintainers)
Top GitHub Comments
My concern is mainly about namespace collisions. For example:
Bugs like that are subtle, and will tend to come back to bite you long after you’ve forgotten what you named that variable.
As you say, there should only ever be one global variable in the app, representing the root element, so maybe this isn’t the most horrible thing. But it does feel like a spooky side effect in an otherwise very functional approach. (I also wonder about performance – do you go through every single property of
window
looking for a$cell
attribute?)I think a
Cell()
function or similar would be a safer and more explicit way of achieving the same effect, and if you decide not to implement it I’ll probably use the$build
API out of an abundance of paranoia, but I wouldn’t call it an existential design issue. 😃@Caffeinix you are totally right that
let
andconst
variables don’t get detected in the global scope.My first instinct to your comment was to ask “when would we need lexical scoping to declare cell variables though?”. It’s probably because in most cases I would only use a single Cell variable in the global scope to build an entire DOM tree, in which case there’s no need for lexical scoping to begin with.
But I do want to understand if there are cases where using let or const makes sense. Could you share some scenarios where using
let
orconst
instead ofvar
makes more sense? Would appreciate your input. Thank you!