Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Consider allowing element-list to be an array. #4

Closed
Raynos opened this issue May 2, 2013 · 12 comments
Closed

Consider allowing element-list to be an array. #4

Raynos opened this issue May 2, 2013 · 12 comments

Comments

@Raynos
Copy link

Raynos commented May 2, 2013

Current JSONML:

var jsonml = ["ul",
    ["li", { "style" : "color:red" }, "First Item"],
    ["li", {
        "title" : "Some hover text.",
        "style" : "color:green"
    }, "Second Item"],
    ["li",
        ["span", { "class" : "code-example-third" }, "Third"],
        " Item"
    ]
]

If we were to allow element-list to be '[' element-list ']' then it would make the jsonml look like:

var jsonmlarr = ["ul", [
    ["li", { "style" : "color:red" }, "First Item"],
    ["li", {
        "title" : "Some hover text.",
        "style" : "color:green"
    }, "Second Item"],
    ["li", [
        ["span", { "class" : "code-example-third" }, "Third"],
        " Item"
    ]]
]]

Some immediate advantages of this format are:

  • that jsonml became a triplet you can pass into a render(tagName, props, children) {} function.
  • jsonml elements are triplets rather then variadic arrays which makes them easy to manipulate as data structures
  • Since children is an array rather then variadic elements you can do nice things like ["ul", items.map(createLi)]

Note that I recommend supporting both formats, the array format is a lot easier to manipulate and transform, the non-array format saves a few bytes for over the wire.

@mckamey
Copy link
Owner

mckamey commented May 2, 2013

Where where you in 2006? ;) But seriously, while I do like this suggestion, I need to think through the implications. I personally now have other bigger things which are built on top of the JsonML format, which would be immediately affected.

The few extra bytes are relatively minimal compared to other suggestions I've heard over the years, especially if GZip is involved. It would also be interesting to consider the memory consumption changes of adding another array between.

@Raynos
Copy link
Author

Raynos commented May 2, 2013

@mckamey I just discovered this today! was previously using hyperscript

Now franctically replacing h("div", { ... }, [...]) with ["div", { ... }, [...]] and now bathing in the glory of data structures for templates.

I've been waiting to do this since I read a recent clojure article about data structures !

I don't think the memory issue is going to matter much. If it does then you have too much html and you should just stream it and then GC makes the memory problem go away.

@mckamey
Copy link
Owner

mckamey commented May 2, 2013

When I use JsonML-based structures (e.g., in DUEL), I find I'm able to build really great UI without sending it back and forth across the wire. So apps work more like Gmail where they load the UI in its entirety (or at least in large chunks) and they sit as data structures in memory, dormant until needed. No parsing at runtime other than the execution of the resulting scripts. My PHP/ASP-like markup in DUEL gets compiled at build-time and then combined with other JavaScript to produce a payload that is sent to the browser on page load and heavily cached. Each subsequent app load then grabs the entire UI from browser cache, and only data is needed to send across the wire.

I never write, parse or manipulate JsonML by hand anymore. It is simply an intermediate format between the HTML/JS that drives my templates and the DOM.

@heapwolf
Copy link

heapwolf commented May 2, 2013

Quite a long time ago I wrote a jsonml like parser, before I realized many people have done this. I implemented element-list as an array. It was a fun project and definitely verified my belief that json is a far more effective data structure for representing the presentation layer.

@Raynos
Copy link
Author

Raynos commented May 2, 2013

@mckamey having a custom HTML/JS hybrid language feels like it defeats the point.

JsonML shines for me in the ability to express templates in JavaScript and data structures. For example your counting iteration can be expressed as a simple function

function count(n, cb) {
    var list = []
    for (var i = 0; i < n; i++) {
        list.push(cb(i, n))
    }
    return list
}

function section(data) {
    return ["ul", count(4, function (index, count) {
        return ["li", "The same " + data.foo + " for " + index + 
            " of " + count + " items."]
    })]
}

Abandoning html completely and just using JavaScript data structures gives us many interesting possibilities.

Although thinking about it, this is very different from the original purpose of jsonML which is just an intermediate wire protocol format and not a "templating language" per se.

@mckamey
Copy link
Owner

mckamey commented May 28, 2013

@Raynos the "point" was to get work done. I've built a lot of UI doing just what you are talking about. The first version of http://internetris.net was written exactly this way. Over time, I found that I was writing a lot of iterative code to express the same things. Having the template language emit the glue code and being able to use HTML editors made life better. Also I found it really helpful for designers to hand me a static HTML mock up and I just add loops and conditionals around parts and it is ready to go. When it comes time to deploy the site, it is exactly what you are writing by hand but the common binding parts are pulled out and de-duplicated.

@brettz9
Copy link

brettz9 commented Jul 26, 2013

FYI, I started some code to address this issue quite a while ago but finally getting to publishing a regular repo. Although I subsequently found this request here, I think a separate project may be merited anyways, as I also like the potential for expressing siblings at the top level: https://github.com/brettz9/jml . The code still needs to incorporate aspects of your work, and some aspects are unfinished (including the API not being fully stable), but in case it gives some ideas, I thought I'd share. Feedback is welcome!

@Raynos
Copy link
Author

Raynos commented Jul 26, 2013

Actually using an array of children is a bad idea in practice. I've found the double ]] and overloading [] to mean both list of elems and elements to be a maintenance and writing pain.

@mckamey
Copy link
Owner

mckamey commented Jul 26, 2013

Thanks for the update @Raynos about the practicality of this.

@mckamey mckamey closed this as completed Jul 26, 2013
@brettz9
Copy link

brettz9 commented Jul 26, 2013

Hope you don't mind one more comment... My purpose is really to examine it fully for mutual benefit rather than self-promotion.

While I agree it is less than ideal to have this overloading Raynos mentioned, and it can be a source of bugs, personally, I also find it confusing (as with JsonML) when children are allowed at the same level as the parent (i.e., with parent and child both as fellow items of the same array). A string at the same level can either be an element name or text node.

Admittedly, JsonML's default at least can usually let you save a little work in writing, though my approach with JML does let you avoid needing to encapsulate each sibling element within an array.

See https://raw.github.com/brettz9/jml/master/example.txt vs. http://www.jsonml.org/samples/bulletedlist.txt . (Again, my API is not finalized.)

Whatever the case, for regular template use, I don't think there is any comparison about the advantages of being able to define reusable functions which can return insertable fragments. It is invaluable if one's purpose is templating, and I have been making some use of this approach in one form or another over quite a long period of time.

Not sure what you want to do with JsonML, but note that if you have given up on plain arrays, you might still allow an object as I also allow to allow fragments--e.g., something like this:

['div',
    'text0',
    {'#': ['text1', ['span', ['inner text']], 'text2']},
    'text3'
]

While the fragment is still in an array, it is at least set off clearly by an object (and the key as "#" won't let it get confused with an attribute; it also reminds one of URL hashes (#) which also points, in the XPointer sense at least, to document fragments).

@mckamey
Copy link
Owner

mckamey commented Jul 29, 2013

To me this seems like an unnecessary change. It might simplify or reduce overhead of one specific case (not surrounding siblings in an array) but then adds to other cases. You have the same positional ambiguity with multiple tagName strings now being siblings but logically part of different elements. It just doesn't buy me anything yet breaks about 7 years of code.

Also I'm not sure what you mean by a fragment. What DOM object does that map to? Doesn't seem like you mean Document Fragments (which JsonML denotes with an empty string for the tagName).

@brettz9
Copy link

brettz9 commented Aug 4, 2013

Thanks, I did mean document fragments as I had not noticed the empty string possibility earlier. The ability to express that in that manner is quite convenient, and I see it can be used to overcome the inability for templates to transclude function return results.

I think my approach may be shorter if there are a lot of empty elements and yours shorter when a lot of elements have children (which is probably the more common case). However, I guess it comes down to a matter of taste, as I still prefer requiring the explicit child structure. I don't think it is positionally ambiguous with siblings (sibling elements are by definition part of different elements) as my point is that I prefer the same kind of thing being stored at the same level in the hierarchy if represented in the same manner--i.e., unless set off by another type of more deeply nested structure (such as an attribute object or another child array).

But again, I think it is a matter of taste, and now I am clear that JsonML also has a way to deal with inline transclusion of fragments.


One little unrelated FYI as far as lossless transfer, I am thinking of adding a structure to deal with ordered attributes because:

  1. The WhatWG has now specified attributes as ordered
  2. ECMAScript indicates object iteration order as implementation dependent (and browsers have never been truly consistent in practice anyways and seem to be getting less so: http://code.google.com/p/chromium/issues/detail?id=883 ).

Having reliable order can be important if doing diffs (although harmonizing serialization in IE < 9 as I've tried to do with an XMLSerializer() shim for testing JML (now renaming to Jamilih) has a whole set of other issues including unreliable attribute order).

I just mention it as a throwaway comment, not as something I need as a feature in JsonML.

Anyways, thanks for your important work in this area. Yours is a helpful resource as well as a useful project in and of itself.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants