Display shapes with javascript frontend?

Topics: Writing modules
Developer
Jan 6, 2012 at 6:44 PM

In a module I have some custom frontend framework that displays content items with javascript. So basically items are added to it along the lines of this (generated in a view template):

frontend.addDisplayItem("name", "title", "text", "url"); // This is JS

Arguments are arbitrary, what configuration is set can vary with different content items (e.g. an item could also fill the "image" argument). The number of items is substantially higher than it's with usual item lists (around 2-300 items on one page at maximum, I'd say 50 on average).

I'd like the whole system to maintain the flexibility Orchard gives with content items (and their display), so generating a series of such method calls in the view in a fixed manner is not an option, somehow the content items should decide how they want themselves to be added to the frontend.

The first thing that has come to my mind was to utilize Orchard's display shapes:

  • Define a new display type
  • Override Content.cshtml for the new display type with a skeleton of such frontend engine registrations, defining local zones
  • Overriding shapes used by the content items in question for the new display type, e.g. the Parts.Title shape
  • Adjust placement (or here rather: whether a shape should or should not be rendered) with Placement.info as usual

This would work great, but has two flaws:

  1. There would be many shape overrides, most of them just to print a string (e.g. RoutablePart's template would contain "@Model.Title", what would then be injected into the registration call in place of "title"). Which, although being fine, takes me to consider whether this is the best approach.
  2. It would have a big impact on performance. On my machine the load time of a page doubled with a quite simple content type and 50 items. Of course this is the price to pay for flexibility, which is fine too.

Despite this, doing it with shapes is nevertheless appealing, but I'm not sure if such a scenario is a sane usage of the system.

What would you advise?

Coordinator
Jan 6, 2012 at 8:30 PM

Maybe something more around JSON serialization? Shape templates are made for HTML rendering, which includes a lot of variation of form rather than variation on the data itself (that's why we have view models, and of course shapes, which represent that unchanging data for the changing rendering). So yes, templates seem like the wrong tool because what you are generating is not a form of presentation markup, it's really data. So I would say if you could have a generic way of transforming that data (the shapes) into JSON, it would maybe work fine. Making sense?

Developer
Jan 6, 2012 at 9:47 PM
Edited Jan 6, 2012 at 9:48 PM

Thanks for the idea, makes sense indeed.

The problem is, although the display shape contains every data that could be displayed in the order it has to be displayed, it could contain more data that should really be displayed (for example we want to show the content of only one property of a part) and it says nothing about how (in terms of textual formatting or semantics) it should be displayed. Well of course, this is what templating is about but although in a more simple sense some templating should here be done too. The first one comes to my mind is limiting the size or otherwise formatting body text.

I'm sure there is a way to convert data represented in shapes to JSON, but that would a bit reverse who is in charge: not the content item would tell what have to be displayed from the set of parts allowed by placement, but the display engine would pick the data it wants to display (returning to the example, this would mean that the full body text would be displayed, and the item can't say it only wants to display the first 200 characters).

I will consider the question whether there is really a need for a kind of templating, or the items should not decide about the specific way they're rendered. It's a tough question though, as I'd like the whole system to provide the same amount of flexibility as it's with ordinary html shape templates. (This module is a quite experimental one, also part of a university research; I'm considering to make it to an open source platform others can build on too.)

Speaking about JSON I though about generating JSON or generally just javascript in templates (since sometimes, e.g. with the mentioned RoutablePart, some semantics should be present in data, because of having an url and a title), but that just sounds awkward.

BTW roughly where should I look if I want javascript shape templates (as .js)?

Coordinator
Jan 6, 2012 at 9:53 PM

"not the content item would tell what have to be displayed from the set of parts allowed by placement, but the display engine would pick the data it wants to display"

This is already exactly what happens today.

Why would you need the extension to be ".js"?

Developer
Jan 6, 2012 at 10:34 PM

Yeah, what I wanted to say that not the content type's (or rather content parts') developer would determine the way the data is displayed or structured (meaning templating here), but the developer of the display engine (by choosing how to display the data, and the content type's developer can't change it).

Forget about the .js, I was thinking about making the templates that would only contain javascript also reflect that in their extension. Meanwhile I don't want it anymore :-) because it should rather be .csjs and even then it would bring absolutely nothing besides the added semantics of the extension.

Developer
Jan 8, 2012 at 12:11 PM

Thinking further, there's a need for some pluggable, uniformed content processing as their are multiple frontend engines, even some that are not javascript.

So another idea:

What about some kind of filters (who are aware of the frontend engine used) that take an IContent instance and insert content into a kind of view model where "zones" are defined (like Content, which would correspond to "text" in the initial example; but it's simple to generate a JSON associative array from zones). Such zones can vary depending on frontend engines (e.g. one frontend engine could have an "Image" zone, another not), but the interface through  they're used is the same. Filters can have weights, which corresponds roughly to the weight used in placement.

I've developed some proof of concept and it seems to work well. I'm a bit hesitant though, I don't want to recreate the built-in shape model, but something similar but as lightweight as possible would be nice.

Jan 8, 2012 at 1:09 PM

I've been wanting to get something similar working. I did some experiments a while ago with adding a flexible "data wrapper" around some shapes which the front-end could then perform certain operations with.

However, I don't think it's feasible to use javascript templates. Also I'm not really sure what your aim is in "letting the content decide how it's displayed". The general intent of the shape/placement system is to let the theme decide how content is displayed.

What I'm not sure about in this thread, are your actual use cases of the system you're describing. The kind of things I'm thinking about are e.g.:

  • Lazy-loading additional items when you scroll down a paged list ("dynamic containers")
  • Clicking a part to edit it in the front end (instead of loading an editor for the entire item, although having an AJAX popup to also do that would be good too)
  • Drag-and-drop relationship and menu management

A lot of these kind of tasks can be accomplished with simple display types and letting the content manager render the templates as normal. It's easy enough to create an AjaxShapeResult to return a rendered shape without the layout. But I think it'd be good to have some sort of framework for storing data attributes in the page and processing them into Ajax calls (and dispatch the data messages to appropriate server-side handlers to find the right shape(s) to render).

Processing individual parts is somewhat trickier. But still possible I think with some of the extensions I've already been adding to placement and shape rendering in my other modules (more detail on this once I've looked over it again).

Can you elaborate on some of the ideas you have for what you want to do with all this?

Developer
Jan 9, 2012 at 1:05 PM

Thanks for the ideas, what I'd like is to use libraries like D3 or JIT, but there is also a need to generate the display of items on the server-side (meaning having items display as an image, but not with these libraries).

Sorry about the continuous confusion with who is in charge for deciding how to display. The thing is, that with these libraries it's not really possible to use the same techniques with theming, as styling is done here through javascript code, not css (at least the big majority of styling is not possible with css).

Shape template overriding of the bits of an item's display could work, but that's problematic otherwise (like the mentioned one print per template or like the use-case of server-side image generation). Particularly I'm also afraid of creating a performance bottleneck (even if using shapes without templating) that can't be solved later when the system is settled. Of course this is very premature optimization, but this is a decision that should last and the solution taken should scale; when shape building (again, just shapes, no displaying yet) adds more than 200ms to load time with simple content types, an average (or it even could be that below average) number of items and on a powerful machine with no load, then I'm considering alternatives: there are plenty of other areas were power will be needed.

So what I imagine specifications for the system I'm aiming for are? I try to be clear this time. From a wider perspective:

  1. It should take content items (similar to BuildDisplay())
  2. Decide which parts should be loaded (I think placement does this too by deciding which drivers run)
  3. Decide from the part loaded specifically what data should be available for display (this is roughly in the territory of templating: the full content part is available in a display shape template, but what to actually display)
  4. Decide what transformations should happen with the data that is meant to be displayed (meaning stripping line breaks or html, limiting string length, etc.; again, this is templating).

It's clear that the system's responsibility covers what shape building, placement and at some extent templating does (although this is not meant to happen mixed with each other inside the system). It gets complicated because frontend engines (like the mentioned at the beginning of this message) should be interchangeable (so there's a need for a uniformed, yet pluggable way of getting all data of an item that should participate in display, already pre-processed).

Shape templating would here have it's place, too, with styling (this would only influence if the frontend engine used is a javascript one, not the server-side one) : the item registration code (that contains styling too, as styling) would reside in its own shape. It could then be overridden from the theme (this is more rigid than with html templating and css, but there's no other way I see). Example:

// This is in a view
foreach(var item in items)
{
    @Display.ShapeForItemType(item)
}

// And in the corresponding ShapeForItemType's template
<script type="text/javascript">
    var options = {
        border-width: "1px",
        border-color: "#000"
    };
    engine.addItem("@item.Id", "@item.Title", 
</script>

I'm currently only gathering ideas, so maybe templating the registration code could be alone sufficient (but than it has to be unique for content types and changed if the content type changes).

Thanks for everyone who've read. Note that what I've written here is somewhat the evolved version of what I've written previously.

Jan 9, 2012 at 1:19 PM

If you want the data out of an item, you could leverage the Export feature and you have a ready-rolled XML format representing all the data in the item. You could easy convert that to JSON notation. How you process that in the front end is up to you.

I'm still a bit confused by some of your points and what exactly you're trying to get out of the system, you haven't given any use cases; but actually I think you're after something different that I thought. The graph visualisations of those two frameworks looks really good, though, and something I'll want to use for Mechanics.

Developer
Jan 10, 2012 at 7:32 PM

Thanks again, I'll get back if I figured something out.