jonschlinkert / templates

System for creating and managing view collections, rendering, engines, routes and more. See the "dev" branch for most recent updates.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

new view type: grid

jonschlinkert opened this issue · comments

@doowb and I had an interesting conversation a couple of days ago, as a result we're considering adding a fourth view type: grid, for handling grid systems.

(This is only a partially-formed idea. it's really interesting but is not yet "planned". Feedback welcome)

Synopsis

Whereas "view collections" are used for organizing and caching views, "view types" determine how the individual views in a collection will be handled during the render cycle. For example, views with the partial view type will be merged onto the context before being passed to the template engine for rendering, but views with the layout and renderable types will not.

View types

This library currently supports three view types: partial, renderable and layout. Passed on the viewType option when a collection is created, collections may have one or more view types, defaulting to renderable if no other types are defined.

  • partial: allows "partial views" to be injected into other views. useful for components, document fragments, or other snippets of reusable code or content.
  • layout: allows views to "wrap" other views (of any type, including other layouts or partials) with common code or content.
  • renderable: views that have a one-to-one relationship with rendered files that will eventually be visible to a user or visitor to a website. For example: pages or blog posts.

Proposed

The grid view type would combine concepts from the partial and layout types to allow users to pre-define complex page layout systems, whilst also keeping a separation of concerns between structure and content.

In practice, this means that grids themselves would be defined using a declarative configuration, the markup (rows and columns) of the grid would be entirely composed of user-defined views (templates), and the content that will eventually populate the individual "cells" of the grid can also be defined using a declarative configuration - allowing them to be modified on-the-fly during the build cycle (e.g. just as you can easily change the layout of a view using middleware, you could also customize the cells of a grid on a page-by-page, or collection-by-collection, or task-by-task basis).

The concept

This is totally pseudo-code, but hopefully you will get the idea and be able to give feedback.

Grids will be created like any other views.

app.create('foo', {viewType: 'grid'});

Once created, you would add grid views with app.foo() (like other custom collections). We would add support for two special properties unique to grids (we're open to suggestions on the property names):

  • schema: an object, for defining the actual grid system using columns, rows, and even other (nested) grids.
  • structure: an object that provides a semantic "mapping" between the grid-schema-object, and css-based grid "positions" that can be specified by other views (in other words, this would allow you to add a partial to the "banner" position on a grid, instead of row2.col1-col4 or whatever).
app.foo('magazine', {
  // main content here, along with a "grid" tag defining where the actual grid will be injected
  content: '<div>{% grid %}</div>',
  // grids can also use layouts, like any other view type
  layout: 'main',
  // rows and columns in the schema would define the "grid positions", as well as
  // the context for those individual "cells"
  schema: {
    row1: {
      // like layouts, the templates in "cells" would be resolved before injecting content
      content: '{% row %}',
      col1: {
        content: '{% col %}',
      }
    },
    row2: {
      col1: {
        content: '{% col %}',
      }
    },
    row3: {
      // nested grid
      grid: 'baz',
    }
  },
  structure: {
    nav: 'row1.col1',
    banner: 'row2.col1',
    main: 'row3.grid.row2.co2'
  }
});

Then, renderable views (like pages, posts etc) can specify a grid to use, along with with content to populate the cells. For example:

app.page('whatever', {
  content: 'this is some content...', 
  layout: 'default', 
  grid: {
    name: 'magazine',
    structure: {
      nav: {
        data: {span: 12},
        content: '<div class="nav">...</div>'
      },
      banner: {
        data: {span: 12},
        content: '<div class="banner">...</div>'
      },
      main: {
        data: {span: 6}
        content: 'some content or partials or whatever for the `main` cell on the `magazine` grid'
      }
    }
  }
});