eZ Community » Blogs » Gaetano Giunta » Little Nemo in SlumberCode part 1:...

By

Little Nemo in SlumberCode part 1: can jQuery meet the eZ template language?

Sunday 18 March 2012 12:43:38 am

  • Currently 5 out of 5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

First post in a series of "crazy ideas to explore at nighttime", this is dedicated to a new friend of mine: jQuery.

I never used that framework very much (I remain a backend coder at heart), but having been recently involved in whipping up some interactive and cool-looking web pages, I was impressed by the ease with which it allows to select sets of html elements and retrieve / alter their values.

The next (il)logical step was asking myself: can we reproduce such conciseness and ease of use in the eZ template language, where fetch functions are a staple? After all the "content/list" fetch function is used to select a set of nodes from a tree, with some filters applied. And, hey, nodes have attributes too, just like html elements!

Read on for more senseless drivel, erm, detailed analysis...

Ideas for a jquery-like syntax in templates:
============================================

First thing first, let's start with the goal: replacing only fetch content/list. Replacing all fetches in one step is a bit too much even for me!

Then: why use jquery syntax instead of xpath, solr filter syntax or other? I have no idea. Maybe other such micro-languages exist and are better suited. But jquery seems to be well known by web developers right now.

Last: let's concentrate on the selector part for now. How to make selector results more easily iterable/filterable can be done in a 2nd step - and the template syntax with its native support for properties (aka .parent.children.0.name) is already quite good in that aspect. Also the equivalent of jQuery .filter() could reasonably be implemented, but it would be a big perf killer, and we don't want devs to fetch 1 million objects from the db to filter them immediately afterwards and use only 1...

1. use a (new) operator

it is shorter to type than a fetch, eg
{def $items = q(" ... ")}
or
{q(" ... ").name}
to be seen:
. is syntax 2 parsed at all?
. can we have "_" as valid operator name instead of "q"?
. what to return? a node, a template-iterable magic object, an array of nodes?
. when adding into the mix template vars, do we get character soup?
2. useful selectors to implement, working as they do in jQuery (from the ones in http://api.jquery.com/category/selectors/)
* (little useful,  but doable)
#nodeid
[name="value"] ("name" in this case is a field in the data_map)
[name|="value"], [name*="value"], [name$="value"], [name!="value"]
.class (content class)
' > ' (direct child)
' ' (space = ancestor/descendant) => replace with ">>" to ease parsing?
:empty (element with no children, not really that useful)
:eq(), :lt(), :gt() (used for pagination)
['name'] (has an attribute named "name")
:hidden / :visible
[attributeFilter1][attributeFilter2][attributeFilterN] (AND them together)
" , , " multiple selector (implemented via many queries)
:parent
:not (useful ???)
3. missing selectors / functionality:
- sorting
- depth
- section filter
- obj state filter
- fetch count => use qc() operator instead of q()
- language
- object name
- class groups (as in class_filter_array)
- only translated
- main lang only
- main node only
- numerical comparison on attributes (ex: [name<="value"] [name>="value"] )
- between, in, not in comparison for attributes
ideas:
- use "*" for AND and "+" for OR when creating groups
- use (name="value") for filtering on other things than class attributes, and [attrname="value"] or [classname/attrname="value"] for filtering on them
- use gt,ge,lt,le for comparisons on attribute values. benefit: we use the ">" sign only for parent/child relationships
4. technical considerations

It would be nice to lift the parser to interpret the selector string straight off jquery, but it will have to be rewritten in php. Not an easy task.

The perf hit induced by this extra parsing should not be too much as long as it happens only at template-compile time. If it happens at runtime, it has to be measured and compared to the overhead of a standard fetch

Apart from parsing the selector string, the sql conditions generated by this operator will probably not be covered at 100% by the ones existing for the current fetches. So a lot of sql-generation is also on the plate.

5. examples
all children of root for building a menu: down 1 level, 2 classes allowed
#2>.folder+.section
all article comments with a recent date
.article > .comment [date>=XXX]
or
2 >> .article > .comment [date>=XXX]
all articles in section 3
.article :section(3)
or
.article (section=3)
all articles in section 3 and 4
.article (section=3+4)
real life case: root node taken from ini, class from variable, section from variable
{p( concat( "#", ezini('mysection', 'mynode', 'mynodes.ini'), ">>.", $class, "(section=", $sectid, ")" )}

As you can see, the last case is a bit of a letdown: it really is much less readable than the equivalent fetch function...

What do you think?

Proudly Developed with from