Future major features

Element Library

 
 
Me!
Element Library
Group DevelopersGroup Moodle HQGroup Particularly helpful MoodlersGroup Testers
On the roadmap for Moodle 2.8 is the "Element Library" - Sam Hemelryk and I have been prototyping, investigating and specifying how we think this should be approached. We think that the scope of this issue, is much bigger than adding a few html pages with different sized headings - there are some improvements needed to the output API ("fix all the things") in Moodle that will deliver benefits to developers and themers.

Please read our specification here: http://docs.moodle.org/dev/Render_library_specification (Yes, the entire thing - and the links). We would love to get as much feedback from themers and developers as possible (I'll link to this post in those forums).

There is one very important point to think about while reading that specification:
* We do not want to break anything - everything we do will be fully backwards compatible (and not in an annoying - debugging messages kind of way).

Thanks for your time, please put your comments in a reply on this discussion, not on the wiki page - Sam and I will curate any feedback and update the doc.
 
Average of ratings:Useful (7)
It's only an avatar...
Re: Element Library
Group DevelopersGroup Documentation writersGroup Particularly helpful MoodlersGroup Testers

Groan... ...

I can see hard times ahead...

Good read though.

Still 2015 should see Moodle in better shape if all this goes ahead.

Thanks for the hard work so far!

Mary

 
Average of ratings: -
Picture of Simon Coggins
Re: Element Library
Group DevelopersGroup Particularly helpful Moodlers

Excellent, really glad to see a solid plan for this, I think it's a really important piece of work.

I think you've captured the essence of what I had in mind when we discussed the element library at the hackfest in Perth. Having a really robust set of elements to work with will make development and theming easier, and allow the work needed to meet Moodle's many requirements (responsive design, multi-lingual, accessible, progressive JS enhancement, etc) to be centrally managed. It will also help consolidate the overall UI to improve consistency.

Some thoughts:

  • Without wanting to instantly double to scope of this work (really!), I just wanted to mention templates. Given the scope of work needed to rewrite existing renderers has there been any consideration of integrating a template engine like TWIG? This could provide improved XSS protection and help enforce the separation of style from content, provide better support for layout changes in themes and make it easier for non-programmers to write/edit themes.
  • I agree that the lack of a connection between a renderer's HTML and accompanying CSS is a problem. Do you have a plan in mind for how that could be overcome?
  • It would be nice to use a convention for classes/ids that have been added for use via JS, so you can easily tell if it is safe to change something or if it is being used for JS.
  • You talk about the fact that bootstrap specific classes are included in renderers, and about the idea of making things CSS framework agnostic. If I've understood correctly you are achieving that by inserting the classes required by the framework into the renderer as required (approaches A and B). That seems quite complex, and I'm not 100% convinced there is sufficient payoff as opposed to just standardising on a single framework (like using YUI for JS). Is there a huge demand from themers to be able to use different frameworks?
  • It would be good for the style guide to recommend a standard layout for similar pages. For example, it's really common to have a page with a list of items and a "create new item" option. It would be great if the style guide recommended the "create new item" was a button and it should be positioned above and to the right of the list of items. Even better would be a renderer that could be used for any type of items where the developer just provides the elements/components. That way a theme designer could override the renderer and have it change everywhere.
  • I'm a bit concerned that aiming for full backward compatibility may limit the scope of what you can achieve.

Simon


 
Average of ratings:Useful (1)
Me!
Re: Element Library
Group DevelopersGroup Moodle HQGroup Particularly helpful MoodlersGroup Testers
Thanks Simon - the Totara Element library was/is an excellent starting point for this discussion.

1. Templates

Ah yes templates. I am definitely if favour of using templates for renderer methods - this is achievable now in a theme (I did a proof of concept a while ago using RainTPL). We are not proposing to move to templates as part of this change because:
* I think that it will take a while to get consensus on a big change like that
* Choosing one template engine over all others is not to be done lightly and could lead to rainbows and sunshine - or a dark, dark place much worse than we are in now
* If this decision is made, we should commit to changing most of core to use it in a single release - having 10% of moodle using templates is not a good result

So the scoping / discussions for that change are definitely bigger than a single dev cycle and the proposed changes are a pre-requisite towards getting to that point (and I definitely have it in mind).

* This work will make it easier to use a template engine in future by:
** Reducing the number of renderer methods that need converting
** Cleaning up / removing logic from the renderer methods

2. renderable / CSS connection - What I have in mind is that for each of the new renderables, if they require CSS it should be kept in its own separate less file (with a naming convention), with one mega less file to include all the others.

3. JS classes / ids - how to change HTML without breaking the JS. Really - I don't think there is a one size fits all approach here. Sometimes it makes sense to work purely with ids in JS, sometimes, it makes sense to use classes so the JS can run once on a page and affect all instances. The file-picker JS used a convention for this (I think it was !) - but no-one understood it and the JS / HTML / CSS there was so complicated and fragile that I doubt anyone was ever brave enough to style it much. Really I think the renderable should have good documentation for themers on what is required from the HTML for the JS to function - and this info should be presented in the element library.

4. Different frameworks - in core now we have an unsupported bootstrap version, so we will need to change to something else in future (I'm not saying bootstrap 3). We need an abstraction here to prevent us going though all this pain every 18 months. And this is not just about JS - think grids - where each framework uses different classes to achieve roughly the same thing.

5. I see this as a Layout type renderable. Any time we are creating common patterns, we should create a layout and reuse it.

6. I think it's easily achievable for full backwards compatibility - and realistically it will take years to clean up all the pages in Moodle (we don't even have renderers everywhere yet).

 
Average of ratings:Useful (1)
Picture of Simon Coggins
Re: Element Library
Group DevelopersGroup Particularly helpful Moodlers


1. Cool. I can see how this work would make using templates easier. One step at a time smile

2. Makes sense assuming that themes can still override if necessary (no reason why not).

4. I'm afraid I'm still not with you on this one but I may be missing something. The move from Bootstrap 2 seems analogous to the YUI2->3 move, painful yes but how does supporting more frameworks help with that? If bootstrapbase was just one of several "framework" base themes it would still be necessary to migrate all the renderers in the bootstrapbase theme once it fell out of support.

5. Sounds good!

6. Yeah I suppose you are right (in that existing code doesn't need to change to be rendered) although until a significant fraction of (core) code is using the new approach it won't be possible to rely too much on the element library when testing a theme.

Simon


 
Average of ratings: -
Picture of Richard Oelmann
Re: Element Library
Group Particularly helpful MoodlersGroup Testers

4. One example is the move from Bootstrap2->3 Simon. Another is that I already have a couple of themes (one in use on a personal site, several others experimental) that use flexbox for layouts rather than bootstrap grids (personal example, but there may be other developers out there with other ideas to develop too). For as long as those elements can be overridden in theme layout files or renderers that's fine, but the minute we lock into a single framework through all of core it becomes restrictive.

The discussion, as I see it, is that work is being undertaken which - while Moodle core can (and should) focus on a single framework - could either restrict developers to that framework OR create a means where 3rd party developers, if they so choose, are able to (fairly easily) adopt a different framework, with the added benefit of making future upgrades to the supported core framework easier to manage.

=> my +1 for being as framework agnostic as possible in anything that cannot be overidden by plugins smile

 
Average of ratings: -
Picture of Danny Wahl
Re: Element Library
Group DevelopersGroup Particularly helpful Moodlers

this is the last time I read about templates, and I'm guessing it's forgotten, but if it's the same type of templating you're talking about then it should be possible now: http://docs.moodle.org/dev/Theme_changes_in_2.0#Templates_.28maybe_in_future.29

as to multiple frameworks, while there's not a huge demand now, abstracting the classes (and even larger chunks of HTML) to a renderer might make migration easier even from BS2 to BS3.  For example something like start_grid('pure'); or start_grid('bs3');

 
Average of ratings: -
Picture of Joseph Rézeau
Re: Element Library
Group DevelopersGroup Particularly helpful MoodlersGroup TestersGroup Translators

Simon "[templates] make it easier for non-programmers to write/edit themes".

I know that argument about templates making things easier for non-programmers. I have worked with a few php-based sites using templates and have always found that templates made things more complicated for programmers.

Please, please, do not introduce templates in Moodle.mixed

Joseph

 
Average of ratings:Useful (1)
Picture of Jez H
Re: Element Library
Group Particularly helpful Moodlers

I also think templates make things harder not easier, that was certainly my experience with Smarty dead

I am not convinced that many "non programmers" are going to find this:


much (if any) easier than this:




 
Average of ratings: -
Dan at desk in Moodle HQ, Perth
Re: Element Library
Group DevelopersGroup Moodle Course Creator Certificate holdersGroup Moodle HQGroup Particularly helpful MoodlersGroup Testers
Ah, the regular recurring cycle of the use of templating systems in Moodle. We have these discussions every two years or so. smile This is the one I most fondly remember.

I have worked with a few php-based sites using templates and have always found that templates made things more complicated for programmers.

Well IMO, we need to make things simpler for designers, else we'll have the most elegant code nobody wants to use. So if that is the tradeoff, i'm OK with it. (Especially as I think more complicated tends to mean... abstracting better).

 
Average of ratings:Useful (1)
Picture of Danny Wahl
Re: Element Library
Group DevelopersGroup Particularly helpful Moodlers
  • The render system allows for the overriding of renderers to occur. Theme designers can overwrite any renderer in their theme. The more that renderers that get implement the more of Moodle you can customise.

This is probably outside the scope of the proposal, but I think that ANY component that that uses global OUTPUT should be able to extend or overwrite any renderer.  Why should only themes be allowed to override output_favicon();?  Why should plugins only be allowed to extend plugin_renderer_base() and not core_renderer()?

  • We have no established best practices, nor even documentation on what constitutes a good renderer, or considerations that should be paid mind in planning and designing of code.

Yes! I have asked before in general developer for recommended best practices on using html_writer()- which is inevitably a large component of a renderer.  For example I have seen several ways of building "stuff" with html writer.

  1. Nested: html_writer::tag('div', html_writer::tag(a, 'hi', array())); 
  2. stuffed $foo= html_writer::tag('a', 'hi', array()); $foo = html_writer::tag('div', $foo);
  3. concatenated: $foo = html_writer::starttag('div'); $foo .= html_writer:starttag('a', array()); $foo .= 'hi.';

There has to be a best way (personally I don't like any of them...).

  • Logic-full renderers greatly hinder theming.

I think this also puts too much "power" into the hands of a theme.  Where a theme should maximally control only look and feel of output there is a feature creep to add to output in a way that is beyond that scope, e.g. injecting analytics, enabling web fonts, etc... which all belong in a proper separate plugin whose output should then be passed to the theme (IMO).

  • Finally define a comprehensive list of low level widgets we can add to core as renderables. This is a library of components that should be used by other renderers (by compositing them).

seems like another good argument for other plugin types to be able to access core_renderer.  Quiz and forum need access cancel_button() too...

  • (draft!) Categories for renderables

why create our own taxonomy instead of using the one in the linked article(s) and pattern lab?  atoms-> molecules -> organisms -> templates -> pages

  • Progressively convert renderers

Perhaps a good place to start is with components that have not yet been converted to a renderer like /login/ - simultaneously getting a POC for the design pattern and knocking off an existing tracker issue, so even if it needs to be rewritten (hope not) at least it now exists as a renderer.

  • A "good renderer" is not:

Where then IS the appropriate place for this logic?  Many custom themes are introducing complex logic in overridden renderers (like custommenu) to add functionality.  If that doesn't belong in a renderer- then where?

FWIW, I like Approach "A".

 
Average of ratings: -
Me!
Re: Element Library
Group DevelopersGroup Moodle HQGroup Particularly helpful MoodlersGroup Testers
A plugin can call e.g. "$output = $PAGE->get_renderer('mod_assign');"

$output->pix_icon(XXX); can then be overridden in the plugin renderer (which inherits from core_renderer).

 
Average of ratings: -
Tim at Lone Pine Koala Sanctuary
Re: Element Library
Group DevelopersGroup Documentation writersGroup Particularly helpful Moodlers

Acutally, it is really important that plugin renderers do not override core_renderer. However, we fake things using PHP __call magic, to make it seem like it does, and this is really important.

Let me try to explain. To understand this, let us just think about core_renderer::single_button, and mod_quiz_renderer::view_page, which uses it, and let us pretend that the code is really simple so it looks like:

class core_renderer {
function single_button($label) {
return '<input type="button" value="' . $label . '">';
}
}

class plugin_renderer_base {
protected $page;
protected $output;
public function __construct($page) {
$this->page = $page;
$this->output = $this->page->get_renderer('core');
}
public function __call($method, $arguments) {
return call_user_func_array(array($this->output, $method), $arguments);
}
}

class mod_quiz_renderer extends plugin_renderer_base {
function view_page() {
return $this->single_button('Start attempt');
}
}

(The real code is a bit more complex than this, because it deals with things like error handling, but it is essentailly the same. Feel free to go an look at the real code. I have tried to simplify things without being misleading.)

The point about this is that a theme can override core_renderer, and change what single_button does, and that changes all buttons everywhere in Moodle. That is done by defining

class theme_example_core_renderer extends core_renderer {
function single_button($label) {
// Something fancy here!
}
}

In the plugin_renderer_base constructor, the $this->page->get_renderer('core') call will return an instance of theme_example_core_renderer, rather than core_renderer, when you are using this theme, and so the $this->single_button call in the quiz renderer will go to theme_example_core_renderer.

If, instead, we had done 

class mod_quiz_renderer extends core_renderer {
...
}

and did not use the __call magic, then the $this->single_button call would always go to core_renderer, and themes could not override it.

I hope that explanation makes sense.

 
Average of ratings:Useful (3)
Picture of Danny Wahl
Re: Element Library
Group DevelopersGroup Particularly helpful Moodlers

Tim, that's helpful, thanks for the explanation.  What I want to know is there then a way for mod_quiz_renderer{} to extend the inherited theme_example_core_renderer{} method?

For example maybe you wanted to output a 'button' instead of an 'input'?

 
Average of ratings: -
Tim at Lone Pine Koala Sanctuary
Re: Element Library
Group DevelopersGroup Documentation writersGroup Particularly helpful Moodlers

I am not sure that I understand this question. I don't think it works like that at all.

mod_quzi_renderer should be written thinking in terms of elements like button and link. If the quiz wants to use a link for the start attempt action, rather than a button, then it should call the $this->link method instead of the $this->button element.

It should not somehow subvert core_renderer->button to display a link.

And, the button or link element is a conceptual thing. It should be up to the current theme how they are displayed.

 
Average of ratings: -
Picture of Danny Wahl
Re: Element Library
Group DevelopersGroup Particularly helpful Moodlers
perhaps I over simplified what I was asking if it's possible to do.  core_renderer has a class called do_something.  Theme extends that method in some unique way with theme_do_something extends do_something.  Is it possible for a plugin via magic or another way to extend theme_do_something or to modify its output?  Here are some examples of what I'm talking about:

  • add "share this" social network links to forum posts
  • set a site favicon regardless of theme
  • extend the features of the custom_menu

AFAIK all of those can only be accomplished at the theme level, because themes can extend renderers other than renderer_base but all of those, IMO, seem like candidates for plugins.  And in my strongest opinion all of those things do NOT belong in themes, because a theme should only modify look and feel, not functionality.

I know this is a little off topic, so I appreciate your clarifications and help Yes

 
Average of ratings: -
Me!
Re: Element Library
Group DevelopersGroup Moodle HQGroup Particularly helpful MoodlersGroup Testers
In short - no - themes should have the final say.

 
Average of ratings:Useful (1)
Tim at Lone Pine Koala Sanctuary
Re: Element Library
Group DevelopersGroup Documentation writersGroup Particularly helpful Moodlers

To give a slighly fuller answer

  • add "share this" social network links to forum posts is not something that a theme should be doing. It is forum functionality. It needs to be coded in the forum module. Or done as a separate block add-on.
  • The theme controls the favicon. If you want multiple theses with the same favicon, you need to make several themes with the same favicon. Just like if you want several themes with the same top bar.
  • Ditto.
 
Average of ratings: -
Picture of Danny Wahl
Re: Element Library
Group DevelopersGroup Particularly helpful Moodlers
Thanks Tim for the fuller answer, and that was my understanding of the situation as it is smile But your answers seem to point to my case that a plugin should be able to modify output:
  • I don't wanna hack mod_forum, or fork and extend mod_forum2, how about a local plugin that extends a single class with share links...
  • I don't wanna upload a favicon to every theme we let users use- or add code for touch icons! how about a local plugin that modifies get_favicon() or standard_html_head()
  • Ditto.

I understand the way moodle works now- I guess the question is: should it change?

I agree that themes shouldn't be adding this type of functionality- but right now they're the only way to do it w/o changing core code.  I mean I guess I could create a dozen little themes that only contain renderers with a handful of methods that output a single "widget" each where I can then include those themes as a parent/grandparent of any other theme and gain the functionality as needed...

 
Average of ratings: -
Davo
Re: Element Library
Group DevelopersGroup Particularly helpful Moodlers

You can also create a local plugin that contains it's own renderer factory and then get all themes to use that.

e.g.

class local_mylocal_renderer_factory extends theme_overridden_renderer_factory {
    public function __construct(theme_config $theme) {
        parent::__construct($theme);
        array_unshift($this->prefixes, 'local_mylocal');
    }
}

Then in your theme config.php:

require_once($CFG->dirroot.'/local/mylocal/renderer.php');
$THEME->rendererfactory = 'local_mylocal_renderer_factory';


This will give your local plugin the final say on any renderers. With the major proviso that, for any renderer classes you create in your local plugin, any renderers overriding the same classes in your themes will be ignored (unless you subclass your local renderers from the theme renderers).

 
Average of ratings: -
Picture of Michael Hughes
Re: Element Library
Group Developers

I'm hoping that Michael De Raadt & Martin D pointed out that there was a discussion about this at the UK Moodle Moot:

http://docs.moodle.org/dev/Hackfest_UK_2014

Specifically at http://docs.moodle.org/dev/Hackfest_UK_2014#Element_Library

Which started a bookmarked a "specs" page at http://docs.moodle.org/dev/Element_library

It may be worth killing off this page (?)


M

 
Average of ratings: -
Picture of Dale Davies
Re: Element Library
 
I just skimmed over the spec but it looks great, looks like you've got you're work cut out implementing it all without breaking backward compatibility!
 
Average of ratings: -
Picture of David Scotson
Re: Element Library
Group DevelopersGroup Documentation writers
That all looks very positive, I agree with the general direction.

Some miscellaneous feedback:

1. I'd like to see some thought given to how a 3rd party developer, who may not be a professional software developer, can quickly and easily create a UI that will work in multiple versions (2.6, 2.7, 2.8 etc.) and multiple themes (Standard, Clean, a Bootstrap3 or PureIO-based theme) and fit in and work in all of them. There should be functions that they can call that take care of making it all work, but it seems today a lot of things are simply hardcoded and so are fragile and break compatibility easily.

2. Any existing API that simply takes the classname from the dev and outputs it into the DOM needs to go, it's impossible to support the stated goals and that at the same time. This also allows for the API to be improved e.g. the current notification renderer going from notification("anything_you_want") to alert_danger, alert_warning, alert_info, alert_success or similar (and then cleaning up the oddities that do other stuff, like "notifytiny").

3. I'd like to see the stuff that can be fixed within a current theme shipped immediately to get feedback. There's no reason why, for example, the code that just landed to provide Bootstrap compatible progress bars should not be shipped as soon as possible in 3rd party themes. There's no need to wait till the next version of Moodle ships and then the 6-12 months till that actually gets widely deployed before checking our progress on this. In general this is a powerful feature of Moodle's existing renderer system which I think is criminally underutilized.

4. The current continue renderer doesn't return a "A message and a button to continue to the next page", but only a button. We do need one that takes a message but since the current one doesn't we'll need to come up with a new one and transition to it.

5. Any time the "single button" renderer is used twice to create a form with two buttons side by side, then that renderer should not be used, probably one or more new renderers should be created to fulfill those use cases.

6. Totally minor but... some of your table entries are duplicated (navbar_item, progress_bar).

7. Converting the non-renderer code that does the same thing (or subtly different thing for no good reason) as a current renderer to call that renderer would be a very good place to start this project. There's a fair bit of this, but it's fairly mindless, easy work and you basically can't do anything interesting with a renderer till all the "fake" versions of it have been cleaned up.

8. There's a lot of independent things here that can be worked on in parallel. What is the plan for coordinating everyone's work?

 
Average of ratings:Useful (3)
Sam Hemelryk
Re: Element Library
Group DevelopersGroup Moodle HQGroup Particularly helpful MoodlersGroup Testers
Thanks for taking the time to read the spec and have a think about (that goes to everyone here btw)

1. In my mind that is entirely facilitated by the elements and components that make up the library as well as the library itself. It will need to be extensible and we'll have to keep a ear to the ground on what is being done to either suggest approaches or adopt missing pieces. Obviously there will need to be an evaluation process of some fashion for that. As for an actual example that is harder to provide without putting in the ground work on the elements and components, of course once started it should become visible very early on how a UI can be constructed.

2. 100% agreement - that means must end. No HTML or CSS should be passed into renderers, everything should be internal and options such as those you've used in your example should be provided as options to the renderable or the render method.

3. Yes, for sure fixes should go back. Better documentation on process will help this. If I am thinking of the same issue you are that wasn't backported primarily because of the changes to the JS that were made. Better association between the JS and CSS as is being purposed here will in my mind greatly reduce the cases like that one. Of course that documentation will be key, we need to be very clear on what gets backported for theme improvements, as perhaps some should be treated as bugs more than improvements. Maybe a policy issue will be required in the future for it, let us see.

4. Yes

5. Yes

6. Yes

7. This really ties in with the below answer.

8. That is one of the really great things about this project. There is going to be a large amount of "grunt" work in several areas.
The purpose of this specification is really to nail down what we want to achieve, the first thing that will happen once we have settled on that is to break up the required work into manageable tasks and establish what can be done when. I imagine we will end up with "stages" organised under the epic and within each stage achievable tasks.
Like most issues we will appreciate any help we can get when implementing this, and most certainly as much help as we can get on conversions.
For sure once we have the organisation of tasks sorted we will share how we intend to tackle this and what areas we'd appreciate help on.
 
Average of ratings:Useful (1)
Picture of Guy Thomas
Re: Element Library
 

This specification is a really positive step forward.

I'm particularly interested in the existing javascript issues outlined in the specification:

"we lack good examples and documentation on how to deliver output templates for JavaScript User Interfaces as well as the creation, and manipulation of HTML structures that are enhanced by JavaScript"

Can I recommend that we consider using an MVW javascript framework to help address this issue - for example ember.js ?

An MVW javascript approach provides a clear separation between data, logic and presentation. It also means we are less likely to be writing lots of code with event handlers everywhere. Why? Because with MVW frameworks, the relationships defined between the data and the template automatically trigger re-rendering when data is provided or manipulated.

At the moment for someone to understand the HTML generated by my YUI javascript they would have to mentally picture it in segments or simply inspect the DOM at render time.

With MVW you have templates for HTML so you can easily see what is going to be output (makes it so much easier for developers at all levels)

Unfortunately YUI does not provide a MVW framework and in my own javascript libraries for Moodle plugins I have created and manipulated HTML in a less than ideal fashion (mainly because I'm doing things the YUI way).

I would like to stress that I'm not trying to bash YUI here, I'm just saying that it is not an ideal framework for laying out the relationship between javascript, html and data.

 
Average of ratings:Useful (1)
Me!
Re: Element Library
Group DevelopersGroup Moodle HQGroup Particularly helpful MoodlersGroup Testers
YUI provides handlebars which does this already, the problem is that you need to provide the handlebar template somehow - and hardcoding it in the JS prevents themers from being able to override it (without replacing the entire JS). Some efficient way to supply the handlebars template from a renderer is needed - but the specifics need to be worked out, and then this approach needs to be applied consistently.

 
Average of ratings:Useful (1)
Picture of Guy Thomas
Re: Element Library
 

I didn't know YUI included handlebars - according to YUI documentation its just a wrapper for the handlebars project. It looks like Atto makes use of handlebars in Moodle 2.7, so its great to know it's being used already smile

Ember.js also includes handlebars but the real benefit of ember.js is the dynamic relationship between models and templates - e.g. change something in a model and the template instantly updates (and vice-a-versa for editing data).

Supplying the handlebars template from a renderer would be great for themers. Providing the themer includes all the relevant handlebars in their overridden template it shouldn't (hopefully) affect the javascript.

At the very least, if handlebar templates where used for outputting all JS initiated HTML (I avoided saying dynamic HTML there), it would be much clearer as to the structure and location of the HTML.

 
Average of ratings: -
Picture of Frédéric Massart
Re: Element Library
Group DevelopersGroup Moodle Course Creator Certificate holdersGroup Moodle HQGroup Particularly helpful MoodlersGroup Testers

Hi guys,

I have chatted a few times with Damyon in the office, but I thought that sharing my views here would not hurt.

In general, I tend to prefer the approach B. Mainly because it does not involve much API change, but just some clarifications on how a to write a good renderer and renderable. However, there are a few things that I am not sure I agree with.


Anything can be a renderable

This is a great feature because it allows a developer to very quickly pass something to a renderer, but I'm afraid that this can quickly expand to be unmanageable and bug prone.

Say you are developing a plugin that is mainly using one class. Rather than defining a new class to implement renderable you will implement renderable to your class. So far, that's not really an issue.

Now you are working in your renderer and calling the different properties of your class to construct HTML. But you stumble upon some value for which you have not define a property, though it is accessible from a method A. So you will call the method A, and it will work just fine, but by doing so you break the rule where a renderable should only contain simple values. Anyway, let's say that this is acceptable because the method A is extremely simple.

But your plugin evolves, and that method A called in your renderer too. Now it contains much more logic than before, and it calls other methods, those methods query the database, use caching, trigger events, etc... Of course, whenever you updated the method A, you forgot that it was called from the renderer.

At this point, your renderer has become ugly, it is doing a lot of computation under the hood through the renderable that was supposed to contain only simple scalar values. Who does that hurt? Well, luckily the theme designer is not too much affected because the logic is not contained in the renderer, but we ended up lying to ourselves when we said that we would not have any more logic in renderers, we just moved it somewhere else and closed our eyes.

I can this of those typical: 'is_visible()', 'get_post_content()' or 'can_edit()'.

Now, let's say that we can live with that, and let's think about templates for a moment. Surely our ultimate goal is to move to templates, and with renderables it is extremely easy: you fetch all the properties from the object, pass them to the template, and there you go, done! But what about our method A... from a coding point of view, how would I know that I need to fetch the return value of method A? Surely we could define somewhere the list of properties/methods to fetch from a renderable, but that should not be the case... you get the point.

Oh, did I mention the private/protected properties on my renderable? And the open access to anything public, or caught by __call(), __get(), etc...?


Renderables can only be rendered by one renderer

If you consider renderables as containers of information, then there is no reason this container could not be re-used in other circumstances and renderered differently. For example, a link_renderable could contain 'text', 'url' and possibly 'icon'. This renderable can be re-used anywhere, in a dropdown, a flat list of links, an indented list of link (navigation), etc...

If there is only one way to render a renderable, that means that a link_renderable should be rendered with an icon and a text. But what if I want to display a list of icon without text? In this example I cannot call the common render_link() method because it outputs the text of the link, therefore I have to create another renderable that is icon_link_renderable, and that renderable only contains the URL and the link. But that is not a good option.

This option means that the developer makes strong decisions on how the content should be displayed because they pass a certain renderable to the renderer. In this last example, the icon_link_renderable does not contain the text, so a themer will never be able to render it with a text.

As renderables only contain information, there is no reason we should duplicate them in order to create a different output. We already have the information ready, let's just make use of it. For instance you would never know how a user_renderable should be displayed (with link, without, only picture, only name, ...) but it would always contain the information that are crucial for a themer to change its layout.

One would say that if a renderable can be rendered differently in different locations it does not help a themer. Actually, it does not change anything for a themer, or maybe it even makes it easier for them. There would be more renderers if we have less renderables, and more renderables if we have less renderers, but the naming convention of the renderers would make more sense.

For instance, you could create your own new renderer that receives a user_renderable and create your own specific output from it. Whereas if you have to overwrite the renderer username_and_picture to display just the user name of the user because of your design decisions, the name does not make sense any more.


Dom manipulation

I strongly disagree with the logic that uses some sort of dom_utils to edit the content or classes of a node that was generated in another renderer. This is placing complex logic back into the renderers, and even if they are tied to the 'display', I do not agree that should exist.

I am not sure how to solve this, but if a renderable can be passed around to other renderers, then it should be alright to overwrite the corresponding renderers, or create new ones to output the renderer the way you need.


Those are the majors concerns that I have about the specification. We have to write proper new renderers and make sure that the rules are defined for this to evolve in the right direction in the future.

Many thanks!
Fred

 
Average of ratings:Useful (5)
Tim at Lone Pine Koala Sanctuary
Re: Element Library
Group DevelopersGroup Documentation writersGroup Particularly helpful Moodlers

I finally made time to read the latest version of the spec.

I have only got half way so far, but most of what I have read so far has been really good. I have to go to an orchestra rehearsal now, so expect more comments later.

Project Goals & Benefits

I think you have done a really good job at the top of http://docs.moodle.org/dev/Render_library_specification of distilling the essential goals of this project down to a few short bullet points. Hopefully this pays us all back by keeping the (huge amount of) work focussed.

So what is the problem

I disagree with the "We have no established best practices". Three-layer archtecture, separating UI, logic, and persistence, is a well established pattern, and renderers are Moodle's way of doing that separation of the output code from the logic. So, lots of software design best practice does apply, and is applied, by many Moodle developers. I am prepared to accept your statement that this is insufficiently documented.

"Developers are encouraged to push functionality boundaries in order to take it places observed in other projects or to challenge oneself." I think this is unfair. At least in the quiz, where I have gone for a design that is not a copy of something somewhere else in Moodle, that is becuase I have been trying to develop the best UI I can for that bit of functionality. Functionality that users need.

I don't think this list curretnly puts the most important things first. E.g. "Themers have a mammoth task ..." is much more important than lack of dev docs. (The order only matters in that it makes the document more readable to get to the importnat points first.)

The elephant in the room

Suddently, when we get to the "Element library and style guide" section, it is taken as read that Elements will be rendeables: "Establish a definition method of elements, and compositions of elements as renderables."

This is certainly not a given. If you think we muse use renderables everywhere (that is, for any thing that you want to output, you have to define a PHP class) then that is something that you need to justify carefully. I am not convinced. I will probably post more on this point when I have read the whole spec.
Thoughts on naming

From private chat with you, I know none of us are big fans of all the Atomic design terms. Particularly 'organism'. However, it is something of a standard, so I think we should just grimace and use the standard terms.

Style guide

I was wondering if it was really neceassry to have a separate style-guilde, or whether we could get everything we want from the Element library. However, I see that the propose style guide is at a higher, more meta, level than the element library, and something there probably is necessary. However, it should be kept as a short statement of principles, and should not duplicate the kind of information that is embodies in the element library.

... this is as far as I got in my reading just now.

Minor quibbles from earlier in the document.

In "Understanding renderers in Moodle"

"Renderers were introduced in a time before Object Orientation was used in Moodle" - this is not true. There was lots of object orientation in Moodle when we introduced renderers. I more accurate sentence would be "Renderers were introduced at a time when we were starting to greatly increase the user of Object Orientation was in Moodle core."

At the end of that paragraph, I would be inclined to add the sentence "Renderers were the closest thing to templates that it was possible to implement in Moodle at the time."

More history

For anyone wanting more of the history, renderers were originally a concept I came up with, in response to demands to let people override the design of Moodle with templates. See MDL-19077. Looks like the original spec was delete from the dev docs, because it was obsolete.

I worked on them while I was at Moodle HQ, in the first half of 2009. Nico also helped. Then I went back to the OU, passing the baton to Sam Hemelryk, who had recently started at Moodle. (What a baptism of fire!)

Later, towards the end of 2009, Petr Skoda had a big hand in improving the concept, particularly at the themes end of the system. See https://moodle.org/mod/forum/discuss.php?d=140089.

David Mudrak was also important, becuase in rewriting the Workshop module he was one of the early adopters of renderers, which helped shape and validate the design.

So, those are the people who deserve the praise/blame for renderers.

 
Average of ratings:Useful (1)
Sam Hemelryk
Re: Element Library
Group DevelopersGroup Moodle HQGroup Particularly helpful MoodlersGroup Testers
Hi Tim and Fred, thanks for the feedback.

I really would like to discuss this idea of renderables for everything.
I apologise in advance, this is going to be long. Perhaps the integrator in me coming out to describe fully what I want to convey.

As Fred mentioned at the start of his post, prototype B is appealing in that the "magic" lies documentation and understanding, the actual code is simple and familiar.
But there are hurdles for it.

Prototype A is object heavy, really too object heavy. But it tries to solve a couple of the hurdles faced by prototype B.
I wrote that approach and even I am not a fan of it, but it does the following things that I think are important and from it I've forms the following impression of the situation.

** disclaimer, I am discussing ideas, not specific elements. Please DO NOT tell me that element A should not be an element, I am not discussing what should and shouldn't be, but how generic things should and shouldn't be. Sad faces for anyone who chimes in to tell me that a search component is silly.

  1. When within a render method and a renderable "property" (coming from anywhere) is encountered the render method calls render on it. It never renderers it itself unless it is absolutely necessary.
    Why. Because when in my theme I override the render_button method I want to see it take effect on every button used in every component, and then if I need to change how a button looks for a component I want to target that component explicitly, overriding how it produces the button (more on that shortly).
    If you have a search component, and you've styled how buttons look in your theme of course you want the button in the component to inherit initially from your "standard" button.
    This implies the following:
    a. the button must be a renderable, in turn as button is just an example, anything you can design must be a renderable.
    It assumes:
    b. we want to re-use our design to achieve consistency. Starting at the smallest element we want to design up, if you've a component that needs an element to look unique the component has to do the work, and I would expect justify why it is unique (another sad face for the first person to say "but that doesn't fit with bootstrap")
  2. When rendering an element output context (not to be confused with Moodle contexts) should be given to provide background and flexibility on what is being rendered.
    I think this is a real devil, its very tempting when rendering a component that contains a button onto which you must set attributes that the component render method creates the HTML for the button with the requires HTML attributes.
    If you consider point 1 above a rule, then this approach would break it. By having the component render method produce the button your button no longer inherits the button design of the theme. It is not consistent through the render chain.
    To allow for this we give the render method context of what is being rendered.
    When rendering an element by itself there is no context given, when rendering the same element within a component the component gets indicated to the render method.

    That sounds a bit convoluted, and I myself misinterpreted the design of this in prototype A.
    This is how I achieved it in prototype A.
    There I introduced an output chain. When you called render on a component a "prerender" method was called, that populated a heirarchy for the component, so that each element contained within the component knew who it belonged to.
    That hierarchy was then used when render was called, the magic render method we already did looked for additional render methods that may or may not exist within the render chain.
    Using the menu as an example:
    • Their is a menu component
    • The menu component contains elements Menu > Element[]

    If you had a link that contained a button the following render methods would be looked for.
    • render_link_button
    • render_button (this you should have anyway, if element is a button this is render_button)

    Within core/a plugin you could define the first method if you had specific needs that were not already being met by the default method such as attributes.
    When overriding the renderer in a theme methods would be looked for in the following order.
    • theme renderer :: render_menu_element
    • theme renderer :: render_element
    • core renderer :: render_menu_element
    • core renderer :: render_element

    So you can see how defaults are respected here. When the theme says "this is how an element looks" that is the default that is then applied to the element in all of its output contexts.

    Worth mentioning is that I don't think that I got the approach quite correct in Prototype A.
    I've used the component in the method name to provide context, however thats not the complete context.
    The complete context would be to include the purpose the element serves as well somehow.
    So in the case of a complex component where more than one element of the same type were used for different things they would be distinguishable.
    It is already complex enough as it is of course.
  3. Components can impose properties onto elements that belong to them.
    This comes about again so that we adhere to point 1. We call render on everything. In point 2 you can see how render methods allow for output customisation to occur, the default is preferred for consistency but you can take control if you want.
    Point 2 however is very much limited to output. You can add attributes, change HTML etc. However there is also this notion of properties.
    Properties describe something about an element in relation to the component it is used within/
    A great example of this is that a menu node can be active, to describe the element in the menu as relating to the page the user is looking at.
    The element in the menu could be a number of different elements (link, button, search component etc) and this property should apply to all of them. However it only applied when those elements are used within this component.
    It's super duper important to differentiate active as a property from say a CSS class ".active".
    .active is how the active property may be described. But that won't apply to all frontend designs. Some designs may want to use a different class, or another attribute, or even a different tag.
    Prototype A facilitates this on the core_ui_element class, in which methods exist for adding, and setting properties.
  4. There is a finite number of elements and components
    This doesn't really fit as a rule, but I think its extremely important to mention.
    Don't get the idea into your head that you will be writing elements. You won't be. Elements are the basic building blocks they will be defined within core and they will change rarely. Written once, used often.
    Don't get the idea into your head that you will have to write components often. You won't. Components should be reusable. They should not be specific to what you are creating unless what you are creating is truly absolutely unique and new.
    We want to be able to create 99% of our interfaces with the elements and components in core.
    Even then you will need to write one component, maybe a couple if you're determined to make themers lives hard again.
    Tim I think I can hear you arguing this already. But really I don't believe it will happen but once in a blue moon.

Those points I consider to be important.

It's very important to note one other thing.
All of this magic in regards to which method gets used, I think these rules only apply core/plugins.
Themes, I would like to think that themes can do what they want.
This approach is about building a consistent system that they can use, and that favours minimal work as I see it in themes.
If they choose to override the render_menu and render absolutely everything in there I think that is entirely acceptable.
It is still up to the themer to craft the end result that they are looking for in the way they want.
But hopefully this magic provides them a way to do it easily, making the page easy to restyle.

I am sure that with strict rules and proper understanding we can apply these to prototype B.
We can require people to always call the render method, we can invent a way to publish theme defaults methods past the core more exclusive methods, and we can continue to employ dark magic (dom manipulation, I really dislike this, I wish there was a better solution).

Obviously we've got to make a decision, the decision we make is what we will live with.
There is more unknown with the OO approach, and for sure it is complex.
But I don't think it should be dismissed lightly.

I've tried to simplify the approach a bit and have come up with these two alternatives:

Ok enough for now.
Please please please give the OO approach some thought and let me know.
I myself an not sold on it, but I think we are dismissing it to lightly.

Cheers
Sam

Edit: We'll utilise MDL-45885 to discuss and document the fine details once this conversation on approach matures.
 
Average of ratings: -
Me!
Re: Element Library
Group DevelopersGroup Moodle HQGroup Particularly helpful MoodlersGroup Testers
Thanks Sam,

While I like the simplicity of approach B - I do not think the DOM manipulation is simple/scalable. Imagine a list with 1000 items - parsing the entire dom of the list to add an attribute to the top level node is wasteful. Neither do I think it can be solved with regexes or any other "quick fix" - I think it's doomed to fail.

I also thing that approach A was too complex. There was a lot of hidden detail in that branch, that I could not follow from reading the code alone.

Freds suggestion does sound good initially - but I agree that if you take that path down the road you will have to overide 20 render methods to change the style of a button consistently.

Really I like the further work you did - and the prototype_3 branch seems the closest to a nice solution I have seen. It is relatively simple, but allows parent containers to put some additional "state" into the renderables it contains. The method for rendering a (e.g.) button is defined only once - but it is flexible enough to cover the different uses.

There are some more fine details to be worked out there, such as the stripping of "core_ui_" prefixes or whether we want to use namespaces such as in https://tracker.moodle.org/browse/MDL-41663 to achieve this. (I don't think I am in favour of stripping the prefixes even if it means long render method names - at least the long names lead to easier finding of the exact method to overwrite - less magic).

So - ATM I give my vote to prototype_3 with a bit more finesse-ing.


 
Average of ratings: -
Tim at Lone Pine Koala Sanctuary
Re: Element Library
Group DevelopersGroup Documentation writersGroup Particularly helpful Moodlers

There is mention of various prototypes. Where?

I have more to say, but no time. Argh!

 
Average of ratings: -
Picture of Frédéric Massart
Re: Element Library
Group DevelopersGroup Moodle Course Creator Certificate holdersGroup Moodle HQGroup Particularly helpful MoodlersGroup Testers

(Markdown seems to play tricks on my post, it seems more readable here)

Hi Sam,

thanks for your feedback. I have to say that I do not disagree with your approach, I agree with most of it. the only thing that I dislike is the developer that makes assumptions on how things should be displayed.

If you have a renderable that is called dropdown_renderable, then it is awkward for a designer to overwrite that to display it differently as the name does not make sense any more. For instance if I do not want a dropdown, but a horizontal list of links, or tabs, ...

What I am suggesting is that renderables are containers of information that are not tied to their display. If you look at it from a templating point of view, you would say that the renderables contain the variables to pass to the template, ignoring what the final display would be. This is common to a more stricter MVC model, and I guess we could apply it to Moodle.

If the developers hold the logic in the controller, gather from the model the information, and sends the data to the renderers, then themers have full control at the view level. That is what I would like us to achieve, leaving developers away from the design decisions and giving full control to themers. Of course developers will have to make a decision for the view implemented in core, but that does not stop anyone from rendering things differently.

We could talk about backwards compatibility too. If at some point we decide to change the layout of a page, we will have to update the controller to change the renderable to something else. As a themer, that means that the renderer I wrote for that renderer is not called in that location any more, and thus it breaks the layout I had in mind.

Let me try to explain with examples, and some code.

Actions not links

How are links supposed to be displayed? Well, commonly, they would be displayed as an anchor tag, with or without an icon. But they could be displayed differently in different locations. They could be real buttons attached to a form, or triggered with JavaScript, they could be just icons, they could be anchors styled as buttons, they are not necessarily links, to me those are actions.

By creating a link_renderable, the developers implies that it should be a link. While if you define it as an action_renderable, it is an action and it is displayed differently depending on its location.

Code example

Let's see how that could look in code, we will create renderables and renderers to display a basic forum post that has a few actions like 'reply' and 'delete'.

First we assume that core has an action_renderable, and a standard way to display it.

// Renderable.
class action_renderable implements renderable {
    $text = 'Something';
    $destination = 'http://somewhere';
    $icon = pixurlObject;
    $disabled = false;
    active = false;
}

// Default renderer.
public function render_action(action_renderable $renderable) {
    $text = $this->render($renderable->icon) . $renderable->text;
    return html_writer::link($renderable->destination, $text);
}

This is the very base, and it follows the different prototypes, now let's define a dropdown menu in core.

// Renderable of list of actions.
class actions_list_renderable implements renderable {
    $actions = array of action_renderable;
}

// Default renderer.
public function render_dropdown(actions_list_renderable $actions) {
    $html = '<div class="dropdown">';
    $html .= '<ul>';
    foreach ($actions as $action) {
        $html .= '<li>' . $this->render($action) . '</li>';
    }
    $html .= '</ul>';
    $html .= '</div>';
    return $html;
}

As you can see, the renderer for the dropdown menu does not specifically accept a dropdown_renderable, but a list of actions.

Now in my module, I would have something like this to output a forum post:

// Renderable for a post.
public function render_post(myown_renderable $renderable) {
    $html = '<div class="post">';
    $html .= '<div class="content">';
    $html .= $renderable->content;
    $html .= '</div>';
    $html .= '<div class="actions">';
    $html .= $this->render_dropdown($renderable->actions);
    $html .= '</div>';
    $html .= '</div>';
    return $html;
}

If we stop thinking further for the moment, we find the same benefits as for the other prototypes:

  • The designer can overwrite the default look of an action_renderable.
  • The designer can overwrite the default look of a dropdown.
  • The designer can change the look of the post

Now let's say that the themer does not want to have a dropdown in the post, they want a horizontal list of links. We have three options here.

1/ They use CSS specific to the module

They use CSS, target the specific pages they are interested in, and use the existing markup to layout the dropdown as a list. But there are two issues with this solution:

  • The CSS cannot be easily re-used throughout Moodle for other dropdowns that they want to see as lists.
  • The existing markup might not fit their styling needs (lack of divs, classes, ...).

2/ There is a core renderer for horizontal list of actions.

The designer will overwrite the default implementation of render_post, and call the render_horizontal_list_of_actions.

// Renderable for a post.
public function render_post(myown_renderable $renderable) {
    $html = '<div class="post">';
    $html .= '<div class="content">';
    $html .= $renderable->content;
    $html .= '</div>';
    $html .= '<div class="actions">';
    $html .= $this->render_horizontal_list_of_actions($renderable->actions);
    $html .= '</div>';
    $html .= '</div>';
    return $html;
}

3/ Core does not provide such a method.

And so they create their own and overwrite the default render_post() renderer.

// Renderer for a horizontal list.
public function render_horizontal_list_of_actions(actions_list_renderable $actions) {
    $html = '<div class="dropdown">';
    $html .= '<ul>';
    foreach ($actions as $action) {
        $html .= '<li>' . $this->render($action) . '</li>';
    }
    $html .= '</ul>';
    $html .= '</div>';
    return $html;
}

// Renderable for a post.
public function render_post(myown_renderable $renderable) {
    $html = '<div class="post">';
    $html .= '<div class="content">';
    $html .= $renderable->content;
    $html .= '</div>';
    $html .= '<div class="actions">';
    $html .= $this->render_horizontal_list_of_actions($renderable->actions);
    $html .= '</div>';
    $html .= '</div>';
    return $html;
}

Solution #2 is the easiest, and surely the encouraged one, but the solution #3 is a good enough alternative because it creates a re-usable component. It also means that if later on we update core not to display a dropdown but something else, my own design will not be affected as the renderable I am getting is identical.

Adapting to other frameworks

Now, if we think of the adaptation to other frameworks, and the need to change the dom structure and add classes and stuff, you will notice that the dropdown_render method is not quite right because it refers to render_action(). So we have to provide a way for designers to change the look of an action within the context of the dropdown.

We have two solutions here:

1/ Specifically create a new render_action_in_dropdown()

public function render_action_in_dropdown(action_renderable $renderable) {
    $text = $this->render($renderable->icon . $renderable->text);
    return html_writer::link($renderable->destination, $text);
}

public function render_dropdown(actions_list_renderable $actions) {
    $html = '<div class="dropdown">';
    $html .= '<ul>';
    foreach ($actions as $action) {
        $html .= '<li>' . $this->render_action_in_dropdown($action) . '</li>';
    }
    $html .= '</ul>';
    $html .= '</div>';
    return $html;
}

2/ The display-context is passed to render()

We could define more specific renderers attached to a display-context (or components), and have something like:

public function render_dropdown_action(action_renderable $renderable) {
    $text = $this->render($renderable->icon . $renderable->text);
    return html_writer::link($renderable->destination, $text);
}

public function render_dropdown(actions_list_renderable $actions) {
    $html = '<div class="dropdown">';
    $html .= '<ul>';
    foreach ($actions as $action) {
        $html .= '<li>' . $this->render($action, $context = 'dropdown') . '</li>';
    }
    $html .= '</ul>';
    $html .= '</div>';
    return $html;
}

The render method would be smart enough to first check for the existence of a render method called render_dropdown_action, and if it does not exist refer to the default one, render_action.

Of course, the context should be well defined and only used within the same context. It would unacceptable from render_dropdown() to call render($action, $context = 'tabs').

Maybe there is a magical way to guess the context we are in from the render() method without having to pass an argument.

Complex list of actions

In some dropdowns (see Bootstrap 3), you can include dividers, and headers. So we have to think about more complex list of actions that can contain not only action_renderable, but also divider_renderable and header_renderable.

Let's try.

// PHP logic.
$actions = array(
    new header_renderable('Some pages'),
    new action_renderable('http://', 'Page 1', $icon),
    new divider_renderable(),
    new action_renderable('http://', 'Page 2', $icon),
    new action_renderable('http://', 'Page 3', $icon),
    new divider_renderable(),
    new action_renderable('http://', 'Page 4', $icon),
);
$list = new actions_list_renderable($actions);
$post = new myown_renderable($foo, $actions);
echo $OUTPUT->render($post);

// Renderer for dropdown dividers.
public function render_dropdown_divider(divider_renderable $renderable) {
    return '<div class="divider"></div>';
}

// Renderer for dropdown headers.
public function render_dropdown_header(header_renderable $renderable) {
    return '<div class="header">' . $renderable->text . '</div>';
}

// Renderer for dropdowns.
public function render_dropdown(actions_list_renderable $actions) {
    $html = '<div class="dropdown">';
    $html .= '<ul>';
    foreach ($actions as $action) {
        $html .= '<li>' . $this->render($action, $context = 'dropdown') . '</li>';
    }
    $html .= '</ul>';
    $html .= '</div>';
    return $html;
}

Being able to pass/guess the context from the render method is really helful here, because we can automatically match the different types of objects contained in the actions_list_renderable.

And if core were not to provide a renderer for headers in dropdown, I could add it to my theme renderers when I adapt it to Boostrap 3 for instance.

Ideas of renderables

  • action_renderable: An action, represented as a link, a button, etc...
  • actions_list_renderable: A list of actions, rendererd as a dropdown, tabs, list of links, ...
  • user_renderable: Rendered as picture, picture + name, name
  • post_renderable: For comments, blogs, or forum posts. (time, author, content, actions)
  • block_renderable: For any kind of block of content that contains a header, content and footer (blocks, course sections, forum discussion page)

I am not really in favour of layout renderables (2 vertical columns, grid, etc...) because essentially the output should always be defined from a renderer, and I can overwrite that renderer to change 2-columns to 2-rows if I want. I do not see any benefit for a designer to change a 2-column component to 2-rows site-wide.

Food for thoughts

While writing this list, it came in my mind that maybe we would want to introduce a collection_renderable, that contains a list of objects, and call render on them with the 'collection' context, leading to:

  • render_collection_user
  • render_collection_block

Javascript

I did not look at all at the Javascript in your patches, but if the renderable is a container of information, without a context, you could simply extract its data, json'd it, and pass it to Javascript. Maybe it could also be easy to create handlebars templates from PHP by having ->render() to replace the final variables with {{ context:placeholder }} or something. I don't know, I haven't thought about this really.

Plugin renderers

For core and non-core, plugins should always define a renderer, even if it does not contain anything. Then they should always get their own renderer rather than $OUTPUT. If their renderer is empty it will fully rely on core, which is fine, but at least themers can override the output of a specific plugin if they need to.

Final thoughts

Briefly looking at your patch, I would be concerned about the difficulty for designers to understand the PHP logic when dealing with core_ui stuff. Calling add_class() or is() is fine for developers but not so much for designers. Though, I give you that it is a lot simpler than the existing renderers we have.

Also, I saw somewhere that we would have to deal with cloning objects to prevent random behaviours when modifying their values, I am definitely sure that designers should never ever have to think about that.

You and Damyon have done a great work on this already, and I am coming once the spec is already well written, and I apologize for that. I am surely missing some cases in the ideas developed above, but hopefully there is something to get out of it.

Thanks! Fred

 
Average of ratings: -
Tim at Lone Pine Koala Sanctuary
Re: Element Library
Group DevelopersGroup Documentation writersGroup Particularly helpful Moodlers

Sorry, Sam, but I have to say that your post is almost incomprehensible. So many words. I have not idea what they are saying (probably not helped by the fact that I don't have enough time to read them properly, but still.)

Fred's post, with code snippets to make it clear what he means, is so much easier to follow.

 
Average of ratings: -
Me!
Re: Element Library
Group DevelopersGroup Moodle HQGroup Particularly helpful MoodlersGroup Testers
Freds post - while useful does not contain the detail of an entire branch of code with all the edge cases discovered - that is why me and Sam made branches of different solutions that produce exactly the same output as required by the 4 different frameworks.

All the prototype branches are listed here or on the spec page.

Repeating them:
A) https://github.com/samhemelryk/moodle/tree/output_prototype
B) https://github.com/damyon/moodle/tree/MENU_RENDERABLE
C) https://github.com/samhemelryk/moodle/tree/output_prototype_2
D) https://github.com/samhemelryk/moodle/tree/output_prototype_3

I am mulling over a proper (detailed) response to Freds suggestion which contains a mix of positives and negatives (just like the other suggestions). I think we have not arrived at a solution yet but we are edging closer.
 
Average of ratings: -
Tim at Lone Pine Koala Sanctuary
Re: Element Library
Group DevelopersGroup Documentation writersGroup Particularly helpful Moodlers

I know that Fred's post does not contain a complete working prototype of a whole system. Such prototypes are very useful, it is great that you have made them, and I need to find time to study them.

However, what I was trying to say is that small snippets of code, showing particular aspects of the system, really help the explanation. After all, the key things is how this new API looks to users. So, just like we make UI mock-ups in the tracker to quickly make it clear what were are talking about when designing a new bit of Moodle functionality, we need something similar here. API are the 'user-interface' that third-party developers user to interact with Moodle, and it should be possible to present a quick sketch of the key things like:

  • I am making a plugin, and I want to output a user picture.
  • I am a themed and I want to change how the user picture is displayed.
  • I am making a plugin, and I want to define a new thing like a forum post that can be displayed.
Sure, there also needs to be a lot of clever back-end code to make what is shown in the mock-ups work, but that is an implementation detail, and only a few people need to understand that. Many people will need to work with the public face of this in future, so that is why it is worth showing small snippets that mock-up how that will look.
 
Average of ratings: -
Tim at Lone Pine Koala Sanctuary
Re: Element Library
Group DevelopersGroup Documentation writersGroup Particularly helpful Moodlers

Let me try to summarise (in a short post wink) some of the things that have been said about one of the key issues:

Should we pass 'real' objects to renderers, or specially made renderables objects that only contain the information needed for output?

As Damyon/Sam said in the spec: "... This means that the renderable class [a real object] can be a mixture of data and methods that perform logic associated with the module. This also means that the renderer can call those methods on the renderable class - effectively using the API of the module."

Certainly, calling a method on an object that has been passed into the renderer is one of the more subtle ways to sneak logic into a renderer, and that is bad. However, I think the general assumption in Moodle is that developers are non-malicious. If you want people not to do something, then it is normally enough to just ask them nicely (in the coding guidelines) and then check it in peer review and integration review. After all, any developer could add a call to undefined_function() in there renderer and crash Moodle. That is far worse than sneaking logic into a renderer, but it does not happen and we don't try to prevent it. (Of course, logic in renderers does happen sad )

However, there are plenty of methods on objects that would be fine to call in a renderer. The best example I can think of is the context object, and the methods $context->get_context_name() and $context->get_url(). Those would be completely fine to call in a renderer. So, I think this line of code is fine. (However, a lot of the other code in that renderer does not belong there!)

An advantage of using methods like this is that it means we do not compute something (e.g. the URL or the context name) unless we actually need it. This is like lazy evaluation, and is good. It is like the LISP/Scheme notion of a 'thunk'. In PHP a logically side-effect-free method of an object (which you can hide behind a PHP magic method if you like) is the simplest way to achieve this.

The other key point is Fred's, that using real objects give more flexibility to themes. For example don't have separate link and button renderables. The concept here is an action, so the element should be an action, and it is up to the theme whether it should be a link or a button. (Of course, the action needs enough meta-data, such as whether it is a GET or POST request, to help the theme render it appropriately.)

Another good example would be user picture. Sadly, we don't (yet) have a a real user object in Moodle. Perhaps we should, in the same way that $context stdClasses were converted to be real context classes. When a forum wants to output the information about who made the post, as part of rendering that post, then the current way is to call the user_picture renderer. However, what it really wants is to display information about the user in a particular amount of space. It would be more flexible if the theme could decide how to do that. The default is the picture with the name beside it, but why should the theme be limited to that?

(Of course, for consistency, a theme would want to change how users are shown everywhere, not just in forum posts, if it was changing this.)

Oh dear, I seem to have failed to do what I promised. This post is not short, and I spent more time giving my own opinions than summarising what others said.

Since this is already long, let me finish with one anecdote about passing limited data to templates.

One time I wanted to modify the output of CVSweb. The screen I wanted to customise was the one that showed the diff between two versions of the file. It showed useful information about one of the files, but not the other. I wanted to add the missing information. CVSweb uses templates, but it just passes to the template the values it thinks it needs. So, more like the renderable idea than the real object idea. Since it did not pass the two file objects to the template, the only way to get the information I needed was to change the code that called the template, as well as the template itself. Hence, there was no benefit to this system using templates. I hope we do better.

 
Average of ratings: -
Tim at Lone Pine Koala Sanctuary
Re: Issue in renderers
Group DevelopersGroup Documentation writersGroup Particularly helpful Moodlers

Heading slighly off topic, but somewhat related to cleaning up renderers, I just spotted this problem: MDL-46031

Basically, in a number of places, we were using static variables to track whether something had been output already on a page. (E.g. the contents of the mod chooser, which is output the first time we output an 'Add activity or resource' link, but not again if we output many such links on a page.)

Static variables are bad for this, because this should be tracked per-page, and we have a class page_requirements_manager designed for tracking this sort of thing.

I just made a patch that shows one way it could be cleaned up. See MDL-46031 for details. Let me know if that seems like a viable approach. If people  are generally happy with the approach, I will tidy up the patch and add unit tests. Anyway, if you are interseted in this sort of thing, please have a look at the patch.

I am pretty sure some of the method/variable names could be improved. Suggestions welcome. Thanks.

 
Average of ratings:Useful (1)
Sam Hemelryk
Re: Element Library
Group DevelopersGroup Moodle HQGroup Particularly helpful MoodlersGroup Testers

Hi everyone,

Thanks for the excellent feedback so far.

I've read through whats being shared here and have been discussing this with Damyon and others. We've settled upon a prototype for output elements that we think ticks as many of the boxes as we can tick presently. If you have a little more time to spare we'd really appreciate any futher feedback you can muster on it.

The prototype code can be found within my github repository in the branch output_prototype_5. As before the branch contains a local plugin called output that contains how we intend the renderers and elements to look.

Branch: https://github.com/samhemelryk/moodle/tree/output_prototype_5 Diff: https://github.com/samhemelryk/moodle/compare/output_prototype_5~2...output_prototype_5 Local plugin: https://github.com/samhemelryk/moodle/tree/output_prototype_5/local/output

The prototype has been build ontop of Damyon's proposed solution for MDL-41663 that allows for renderers and renderables to be autoloaded and namespaced.

To accompany the prototype I have written a guide to creating output elements in the developer docs that outlines the process and basics of creating elements.

While I wait anxiously for any feedback I will be continuing to work on the documentation for the list of initial elements, renderer best practices, and a CSS style guide.

Many thanks Sam

 
Average of ratings: -
Tim at Lone Pine Koala Sanctuary
Re: Element Library
Group DevelopersGroup Documentation writersGroup Particularly helpful Moodlers

That would be https://github.com/samhemelryk/moodle/compare/output_prototype_5~2...output_prototype_5

(Why didn't URL auto-linking work in your post?)

Yay! 11,000 lines of code, all an one commit, with a one-word commit comment giving no clues as to what is going on. You really want to maximise the challenge you set us, don't you?! smile

Can I suggest you rebuild it as a branch with several commits:

  1. Add required gallery module.
  2. ... well I was going to make some intelligent suggestions here, but I can't even work out what the files are from the name
I mean, when I see something called output_bs3, the though that comes to my mind is probably not the intention you mean to communicate through your code. So there may be a prerequisite step to obsess over the names you have given things.

I would expect the branch to look like something like:
  1. Add third-party stuff that we can skip over.
  2. Core changes (if any) required to make the new system work. (Probably the smallest patch, but the key one to review.)
  3. Examples that show the new system working.
  4. Add the first version of the element library tool.
 
Average of ratings: -
Sam Hemelryk
Re: Element Library
Group DevelopersGroup Moodle HQGroup Particularly helpful MoodlersGroup Testers
Sorry Tim - I didn't think you'd read it if I made it too long!

(jokes of course you know I value your opinion)
 
Average of ratings: -
Sam Hemelryk
Re: Element Library
Group DevelopersGroup Moodle HQGroup Particularly helpful MoodlersGroup Testers

Let me try to more clearly explain the proposal, it covers how to implement elements within Moodle.

Design

  • Use atomic design terminology, supplemented with "element" as a meta form of all atoms, molecules and organisms.
  • An element base class(https://github.com/samhemelryk/moodle/blob/output_prototype_5/local/output/classes/output/element.php) in code that provide common functionality for adding attributes and properties as requirement dictate.
  • Not all atoms will be reflected by classes. Done for simplicity in renderers, only atoms with more requirements greater than fixed HTML will have classes.
  • All molecules and organisms will have classes, and all implementations of a molecule or organism will extend the base molecule or organism class.
  • Relies upon MDL-41663 which essentially adds support for an Output API when autoloading.
  • Output classes will be namespaced as either \core\output\xxx or \plugintype_pluginname\output\xxx
  • Base classes element, atom, molecule, and organism are located in lib/classes/output/xxx.php and namespaced as above for autoloading.

Organisation and implementation

  • Core components being created will be required to use the new elements.
  • Plugin developers will be encouraged but not required to use the new elements.
  • We will have a guide to writing elements
  • We will have a best practices guide for renderers - in draft now, see this section of the above guide for some of what that will contain.
  • We will have a CSS style guide - in draft now.
  • We will decide upon the list of elements we'll have initially in core.
  • Write the "core" elements and their associated tests+generators.
  • Likely convert an entire component to use the new renderables, likely changing its interface.
  • Likely convert an entire plugin, likely changing its interface.
  • Conversion of Moodle core will be an ongoing process and we will encourage developers to use this method as we originally did encourage developers to use renderers. This is the next step.

The proposal

  • Shows how element will be written, where they will be located, and how they should be rendered.
  • Has a local_output plugin (local/output) that contains classes and a renderer to reflect cleanly how this will look. Obviously the actual implementation will not be done in a local plugin it will be done in core, but as that would lead to messy diffs I did it this way and I believe it will be easier to understand the nature of the proposal.
  • Consists of 8 commits now, each with a notable purpose and each with a short commit message to explain its purpose.

The commits:

  1. Added YUI module: required only for the PureIO theme
  2. Required core changes other than to core_renderer
  3. Create basic local_output plugin
  4. Add an element class
  5. Added atom, molecule, and organism abstract classes
  6. Added action, link, button and text atoms
  7. Added menu, and dropdown menu display
  8. Added themes to show how this looks when you override the renderers

What I think of this approach

It is a step forward for output, it is not the perfect means of producing output. I don't believe the perfect approach to producing output in Moodle is possible presently as it would require more time, effort and planning than we can afford. This however takes us in the right direction. We introduce a more rigid method of producing output, and document it with guides and best practices. It will continue to evolve along this narrower path and both with the aid of and within the constrain of the API we continue to let it do so. It will be required in core to use this for new interfaces, existing interfaces can be improved as time and effort permits. For plugin developers we encourage and shout the benefits of this system, they are not required to use it but hopefully the advantages will. The actual benefits can be summarised as for developers it will be less design, for designers it will be less development and design. There will be more code initially but as custom interfaces are replaced with reusable elements we will end up with less code as well.

 
Average of ratings:Useful (1)
Tim at Lone Pine Koala Sanctuary
Re: Element Library
Group DevelopersGroup Documentation writersGroup Particularly helpful Moodlers

Yay! sam. That is much more digestable. It will still take some time to digest. Some initial questions spring to my mind, which hopefully I will be able to answer myself when I have read and thought about it more:

Initial thoughts

  • Are three levels (atom, molecule, organism) always enough? (I guess they are for other proponents of Atomic design.)
  • What benefit do we get from the atom, molecule, organism base classes? (I am guessing it just serves a documentation function.)
  • Why does the element base class have public get/set_attribute & add_class methods? I though we wanted to move away from developers putting hard-coded classes on thigns, since that goes against the point of elements making things easy to style.
  • Similarly, it is worrying to see button and link as example atoms. action is a good atom. It is a conceptual thing: Somethign you click to do something. Whether that is output is HTML as <input type="button" ...> or <a href="..."> is exactly the sort of thing that the renderer should be deciding, not the developer.
  • Oh dear, I had thought I was resigned to the way MDL-41663 was going, but now I am concerned again. Are we sure we have the right proposal there. There will be many elemnts in core/classes/output and mod/quiz/output Are we sure we don't want more hierarchy like mod/quiz/renderers, mod/quiz/atoms, mod/quiz/molecules, etc? At any rate, I would hold off on the details of MDL-41663 until this proposal is further along. I don't think that matters. We don't want people renaming their renderers and renderables until they move directly to elements.

I really need to go to the supermarket now. I will continue reading later.

Where renderables came from

Incidentally, I did recently re-discover why we have renderabels in the first place. Have a look at MDL-46030, which I am still working on. Specifically the new renderer method: https://github.com/timhunt/moodle/commit/b9a5d388f6ad93806298d91bdebbe384b7f71571#diff-7999b363de96d73a6c618bc44614e547R67 . That is a pretty bad renderer method. There are about 30 lines that aer mostly logic, just getting the right attributes that will be required to make the JavaScript work. Clearly it should not be there in the renderer method (becuase that will be a pain for a theme wanting to override it.)

On the other hand, we should not move that code into the place that calls the renderer, becuase that would be horrible duplication. FOr someone who wants to print a 'Create new question' button (or link), the call to ask the renderer to output that should be as simple as possible.

Hence, you need a third place to put that code, and that is the renderable object. The person who wants to output a 'Create new question' button (or link) creates a rendererble for that, jsut passing in the key values. Then the renderable object can compute all the technical stuff. Then the renderer can easily get that technical stuff to put in the HTML.

I think the original example where this was worked out was user_picture.

Where renderables are going

Just to say tha now renderables are being reinvented as elements, which makes them a more conceptual thing, rather than just being an implementation detail to get logic out of renderer methods.

This is probably a good thing, but it requires care.

 
Average of ratings:Useful (1)
Tim at Lone Pine Koala Sanctuary
Re: Element Library - renderer classes do two things
Group DevelopersGroup Documentation writersGroup Particularly helpful Moodlers

Thinking about this cycling home, I realised that as currently implemented, renderer classes have to serve two duties, and I am wondering if this causes problems.

What I mean is, on one hand renderer provide an API for the plugin developer do display things: e.g.

echo $OUTPUT->user_picture(...);
echo $myrenderer->widget(...);

On the other hand, they define the methods that themes can override to change how things are displayed, e.g.

class theme_mytheme_core_renderer extends core_renderer {
    protected function render_user_picture(...) {
        // ...
    }
}

This does not seem to cause huge problems, but it does mean that the class that themes override is more complex than it needs to be.

Then, it occurred to me that it is conceivable to change this without breaking too much backwards compatibility. Obviously the thing that themes have to override must continue to be called ..._renderer, since it is referred to directly by name as in 'theme_mytheme_core_renderer extends core_renderer'.

However, the $OUTPUT or $myrenderer objects that developers use to do output are obtained by a call to $PAGE->get_renderer. That could return an object of any class, we could call it something like core_output, or type_myplugin_output. Then, the ..._output class would have receive API calls form the developer doing output, and translate them into calls to the ..._renderer object that themers override to do the output.

If the ..._output class does not exists, then the $PAGE->get_renderer call could just return a ..._renderer object as at present, hence almost completely backwards compatible.

(The only compatibility breakage I can see is when the return from $PAGE->get_renderer is passed to a function that has a type hind on that parameter, which names a specific class.)

I have no idea whether done this is a good idea or not. But it is possible.

  • It replaces one complex class with two responsibilities with two simpler classes.
  • But that requires more different classes for people to understand and implement. 
Update: I just got to this bit of your prototype: https://github.com/samhemelryk/moodle/commit/ad10639cf68e5e03ae53cdcde90de872da688298#diff-cccc22b53bd9bed7ec9f8106dff13222R109. Logic in a renderer? Does what I am wittering on about here help? I still don't know.

 
Average of ratings: -
Tim at Lone Pine Koala Sanctuary
Re: Element Library - forwards and backwards compatbility
Group DevelopersGroup Documentation writersGroup Particularly helpful Moodlers

Another thing I have been thinking about is the issue of forwards and backwards compatibility. Actually, I have been thinking about this off and on from when you first asked for comments on this spec, and I really did not like the though of 'everything is a renderable', because that seemed to require many classes.

If you want an example, here is a recent thing: https://github.com/timhunt/moodle/commit/554e3bf53b689cee16320971ca6b1ac71e582675#diff-8ccc4cc7f10e952926d0e945446e82f4L740

It is the kind of renderer method which takes many arguments, not just one renderable object, and I needed to change one of the arguments, which I was able to do in a mostly backwards compatible way, but only by adding logic if (is_string($preflightcheckform)) { in the renderer. (Slap wrist!)

We know that APIs with many arguments make it a pain to change the API when necessary, although PHP default parameter values make it possible more often than not. However, it does mean that when the API changes, it is pretty obvious what is going on. The parameter list changes. That is clear to see.

Now contrast that to the

public function render_widget(widget_renderable $thing) {

case. In this situation, the API will never change. What will change is the set of fields available on the $thing object.

However, that does not prevent things breaking if a field is added or removed. And, the breakage could be quite subtle. Will it be obvious what has broken and why? It is not as clear as a changed parameter list.

(As I say, I got this far trying to work out why I thought making everything a renderable object was and. However, it turned out I was wrong ...)

BUT ... we are very good in Moodle, when we add or remove a field or a method from an object, about handling the deprecation. That is, we will leave the old method in place @deprecated, and with some debugging() output to explain how to upgrade the calling code. Similarly for fields we can do __get magic to make the change explicable.

So, actually, having renderable objects for everything is better for forwards/backwards compatibility.

(At least, that is what I think this week wink)

 
Average of ratings: -
Sam Hemelryk
Re: Element Library - forwards and backwards compatbility
Group DevelopersGroup Moodle HQGroup Particularly helpful MoodlersGroup Testers
Hi Tim,

Just letting you know that I am working on a reply to you here, the feedback is much appreciated.
I'm traveling to Christchurch for the weekend and this is being printed as my reading material.

Have a great weekend yourself.

Cheers
Sam
 
Average of ratings: -
Tim at Lone Pine Koala Sanctuary
Re: Element Library - forwards and backwards compatbility
Group DevelopersGroup Documentation writersGroup Particularly helpful Moodlers

I can't help thinking that my reading material for this weekend will be more fun than yours. I just bought Kent Beck, Test-Driven Development by Example. Actually, it is very good read. I started reading it over supper, and have already read the first two chapters (out of three). Recommended.

Meanwhile, I am going to make some more posts about other points. Sorry.

 
Average of ratings:Useful (1)
Tim at Lone Pine Koala Sanctuary
Re: Element Library - Why stop at organisms? We should have templates/pages
Group DevelopersGroup Documentation writersGroup Particularly helpful Moodlers

This is something I have tried to do in the quiz code. Each page just has one renderer call, like https://github.com/moodle/moodle/blob/master/mod/quiz/attempt.php#L148.

(Actually, I am lying - but that is a minor detail. It does not invalidate my point about what the ideal is.)

This gives a complete separation between the output code and the logic. (Between the V and the C in MVC, if you like.) However, this is just a theoretical advantage.

The practical advantage is that it gives the theme complete control over that page, if the theme wants it.

In terms of the atomic design language you are using, this is the template or page level.

Ah! I need to read what you are actually saying, not what I think you are saying. You are saying that in Moodle, the first three levels, atoms, molecules, and organisms will be represented by Elements, that is PHP classes.

You are not saying that we won't have renderer methods like this. Just that they won't be classes.

That makes sense. We hope that elements are re-usable, where as the quiz attempt page is only output in one place, here, so we need not define a class.

Is that what you are saying? I don't want to put words into your mouth.

And, for one page, https://github.com/moodle/moodle/blob/master/mod/quiz/view.php#L247, it turned out to be so bloody complicated that I ended up with a bloody horribly class to hold all the data that was needed: https://github.com/moodle/moodle/blob/master/mod/quiz/renderer.php#L1188. Should that class be an element/renderable? (Or should it just be taken out and shot?)

If course there is no need to display pages in the element library. If you want to see what a page looks like in your theme, just go there. (Of course, it might be nice if the element library, where it lists all the elements specific to each plugin, like mod_forum:post, or mod_quiz:nav-block, could also have a list of all the pages in that module. Sort-of like http://docs.moodle.org/dev/Quiz_user_interface_overview, but less graphics and more list-y.

Summary

(Since this thread seems to incite long posts.)

  1. Should each script in Moodle only have one output line at the end:
    echo $output->xxx_page(...);
  2. Is this consistent with adopting atomic_design in Moodle?
  3. Are these pages handled like other elements, or something else?

I think Yes, Yes, and something else / I don't know.

I am hoping that you agree with me on 1. and 2. and will be putting 1. in your best practice documentation.

I hope you are way ahead of me on 3. and have a good idea about how this should work.

 
Average of ratings: -
Tim at Lone Pine Koala Sanctuary
Re: Element Library - how will this look to plugin developers
Group DevelopersGroup Documentation writersGroup Particularly helpful Moodlers

Aside

As I just said, it seems to be a rule that posts in this thread are excessively long and rambly. Clearly I was worried this one might come out too short, so here is a mostly irrelevant aside to pad it out wink

As I see it, there are three roles a developer might take which are affected by this proposal, and only one of them is easy to give a name to.

  1. There are the theme designers. This proposal should make things a lot easier for them, and looking at the corresponding thread to this one in the themes forum, they agree.
  2. There are the developers adding a new feature to Moodle, whether in a plugin or Moodle core. They are the people who will have to create the renderers that theme designers will be able to override, and to define new custom elements, where absolutely necessary. (E.g. mod_forum:post makes sense an element - I guess that would be an organism?) As you can see, this is the role I can't think of a good name for, and I bring it up because they are the people I want to write about in this post, once I get to the point.
  3. There are the theme system implementors, who have to build all the infrastructure that makes the whole system works. Actually, this role has a name at the moment, or rather two: Sam and Damyon smile

That is something of a point. There (we hope) many theme designers, and Moodle add-on developers. There are very few people who work on the core of the system.

Therefore, if we have to make a trade-off that makes life simpler for everyone else, but more complex for the theme system implementors, then they will just have to suck it up. Fortunately, I think they are likely to be able to handle whatever is thrown at them (metaphorically only!). Of course, we hope that the core of the system comes out looking really elegant and simple, since that is easiest to maintain. However, if that is achieved, the I am sure that it will be one of those things that only looks elegant and simple with hind-sight, because people sweated over it for hours.

(Is this post long and rambly enough yet?)

To get to the point

My concern is for people who implement Moodle features (2. above).

I don't yet get what they will have to do, and since I am quiz module maintainer, that is a question close to my heart.

I think I understand the concept. To display the quiz info page (view.php), I am supposed to do that by outputting a bunch of standard (or custom if necessary) elements. Well, I think the code is already pretty close to that: https://github.com/moodle/moodle/blob/e20392edc002ad70f5230f573d3ccc01f12bdfb5/mod/quiz/renderer.php#L695 (That is not perfect in various ways I won't go into here. If you don't like that one, look at attempt_page, summary_page, review_page, etc in the same file.)

Then, those large-scale elements (organisms) that make up the page are meant to be output as smaller elements, molecules or atoms. Well, again, https://github.com/moodle/moodle/blob/e20392edc002ad70f5230f573d3ccc01f12bdfb5/mod/quiz/renderer.php#L711- I think I already deserve at least some marks for effort there.

OK, so how will that look in the brave new world of the Element library? Well, I am afraid it looks pretty ugly to me. Going through the prototype to try to find comparable code I get to: https://github.com/samhemelryk/moodle/blob/ad10639cf68e5e03ae53cdcde90de872da688298/local/output/classes/output/renderer.php#L73 - that method and the three that come after it.

I am really, really hoping that I am misunderstanding the prototype. Please can you make some nicer examples wink

(In my experience of doing various sorts of development, which includes Java Swing, Borland builder C++, and Moodle 1.6, output code almost always ends up looking bloody ugly. The current Moodle 2.0 style is actually not too bad.)

Note, it is not just add-on developers who have to do this sort of thing. Theme designers who want to override renderers (e.g. to change which elements appear on the quiz view page) will have to write code like this.

Summary

Please make some nice examples, to sell to us Moodle feature developers how wonderful life will be when we have the element library available to build our UIs.

(Pseudo-code will do, and please feel free to use examples from the current quiz renderer as a basis of the examples.)

Thanks.

 
Average of ratings: -
Picture of Guy Thomas
Re: Element Library - how will this look to plugin developers
 

You won't be losing sleep worrying that you have duplicated an element (and added more css) for the tenth time that already exists in Moodle. 


Hopefully the core elements you use to build your UI will have had input from a UX expert which should in itself make your UI better. 


Of course the element library won't guarantee that developers don't make dog food out of caviar. 

To prevent this from happening I think Moodle developers need to get UX experts involved in their design process (or alternatively research UX themselves) 

 
Average of ratings: -
Picture of Cathal O'Riordan
Re: Element Library
Group Developers

Hi Sam & Damyon,

I was delighted to see that you're going to adopt the BEM notation for the Element Library. Excellent stuff!

I expanded a little more on the BEM description in the Element HTML and CSS guidelines document. Please feel free to change or discard anything I've included.

regards,

Cathal. 



 
Average of ratings: -
Picture of Danny Wahl
Re: Element Library
Group DevelopersGroup Particularly helpful Moodlers

I've just read the latest version of the Element HTML and CSS guidelines and here's my current thoughts:


  • The very first thing to mention is that all classes in Moodle must now be prefixed by *m-*. This instantly identifes a class as belonging to Moodle, it aids us in avoiding conflicts with any non-Moodle css that may be loaded, and it is part of our framework agnostic plan.

that truly seems like a good deal of overkill to me.  If we do a good job of creating grid renderers then this sholdn't be an issue.  I don't know, outside of a framework, how much non-moodle CSS there is in Moodle.  Namespacing makes sense for JS and for PHP, but this is the first time I've heard of it for CSS.

  • We need to adopt a single grid framework.  Personally I don't think we should use pure bootstrap or pure YUI, instead we should choose one of these and build it use our class name structures.

I don't think we should reinvent the wheel again.  a DIY grid is NOT the same as framework agnostic.  A good example of how this could/should be done in core_renderer() exists in course/management_renderer()

https://github.com/moodle/moodle/blob/master/course/classes/management_renderer.php#L875-L960

which includes YUI PURE and BS2 CSS output.  it could easily be modified by a theme using a different framework by overwriting the functions or extended to include BS3 like this:

https://github.com/bmbrands/theme_bootstrap/blob/master/renderers/course_management.php#L29-L58

then, as far as core and plugins is concerned its truly agnostic.

  • It is possible in Moodle to add CSS stylesheets to all plugins (including core plugins).
    Moodle always looks for a styles.css file within your plugins directory, and it also looks for a styles_themename.css where themename is the name of the currect theme being used.

    For instance the following could be added to the forum module:

  • mod/forum/styles.css: Used all the time.
  • mod/forum/styles_base.css : Used when the user is using the base theme.
  • mod/forum/styles_bootstrapbase.css : Used when the user is using the bootstrapbase theme.
  • mod/forum/styles_clean.css : Used when the user is using the clean theme

I'm sorry, but this frankly sounds like a terrible idea- but I'll assume I don't understand something.

First, I hope that the proposal is ONLY these 3 extra sheets and not creating a separate sheet for every conceivable theme out there.  What happens when someone's using the "More" theme?  instead of the necessary enahncements for bootstrapbase or clean being included they get nothing?

Second, I don't suppose that plugin developers are keen to test and maintain their plugins in multiple themes.

Third, if a plugin is developed using the new output methodology then the base styles for the elements and molecules should be included in the theme inheritly.  And if a theme is not, then styles.css should suffice.

Fourth, for an end user trying to track down the source of a display bug they get bounced back and forth now from the theme developer to the plugin developer.

Fifth, and finally, why hold plugins to a different standard than core plugins?  Especially if they're going to be distributed via the plugins database.  If you're developing for yourself, yeah, do whatever you want.  But if you want it in the plugins DB it needs to follow the core guidelines.  This also facilitates the adoption of plugins into (and out of) core.  Otherwise for a plugin to be included it might need to be entirely refactored from a CSS perspective.


Aside from all of that I think we're generally headed in the right direction smile  Looking at the breadth of this proposal and the amount of refactoring that needs to happen (every single renderer, and every single that that still hasn't been converted to a renderer *cough* /login/ *cough*) how long are we looking at having mixed soup?  2.13, 2.14?  When will the core elements be ready for plugin developers? 2.9?

 
Average of ratings:Useful (2)
Picture of Joseph Rézeau
Re: Element Library
Group DevelopersGroup Particularly helpful MoodlersGroup TestersGroup Translators

Danny: "I don't suppose that plugin developers are keen to test and maintain their plugins in multiple themes."

No they aren't, tongueout

Joseph

 
Average of ratings: -
Picture of Guy Thomas
Re: Element Library
 
Observations on the atom, molecule and organism classes in prototype 5:
The classes at the moment just extend the base element class which suggests that they are purely there for the purposes of taxonomy (that's not a bad thing).
There should be methods for adding atoms to molecules and both atoms and molecules to organisms.
These methods should register the atoms / molecules in a class property so that we can interrogate a molecule / organism to find out what it is made up from.
Note: according to Pattern Lab, organisms can consist of both molecules and atoms.

 
Average of ratings: -
Picture of Guy Thomas
Re: Element Library
 

Note: I noticed that the menu molecule does have methods for adding items. Is there anyway that this could work with methods for adding items in the base molecule class?

 
Average of ratings: -
Picture of Nadav Kavalerchik
Re: Element Library
Group DevelopersGroup Particularly helpful MoodlersGroup TestersGroup Translators

I am wondering... will this new element library help us reduce the CSS bloat and redundant CSS selectors the browser have to process?

(using: https://unused-css.com)

unused-css.com - moodle theme clean css

 
Average of ratings: -
Tim at Lone Pine Koala Sanctuary
Re: Element Library
Group DevelopersGroup Documentation writersGroup Particularly helpful Moodlers

Your forum post only used 0.01% of the English language. You ave obviously doing something wrong.

Well, no. Of course not, but your CSS test is about that meaningless.

The way Moodle CSS works is this:

All the CSS required for all pages in Moodle (in the current theme) is combined into a single file. This file is sent to the browser with headers that say "You can cache this forever". Therefore, when you visit a different page, you don't need to download any more CSS.

Now, if you downloaded the HTML of ever page in your Moodle site, and used this too, then you might find 5% or 10% of the CSS that is not used, and it would be worth removing that.

Also, it is a hope that the element library will give us a better understanding of what CSS is used where, and hence will make it easier to manage.

 
Average of ratings: -
Picture of Danny Wahl
Re: Element Library
Group DevelopersGroup Particularly helpful Moodlers

Tim,

While I generally agree with your point I think that if we optimize the CSS, via BEM or whatever they decide moodle will use now that the size of the file will drop drastically while the coverage will probably remain the same.

Meaning we have 5,000 lines of CSS and in Moodle 95% of those are used, but by being smarter with our HTML output and our specificity and class selectors we could use 2,500 lines of CSS and 99% of them would be used.  there's a lot of this type of stuff in Moodle (this isn't an actual example):

.blue { color: blue; }

.widget1 .blue { color: blue; }

.widget2 .blue { color: blue; }

.mywidget { color: blue; }

smashing magazine has a good article up now detailing their performance optimizations of their website and one of the things they were able to do is move from 91kb to 45kb of CSS.

and here's a couple from github:

github's css

github's css performance

so yeah, it's cached, but we're in no way optimized (yet)

 
Average of ratings:Useful (4)
Picture of Cathal O'Riordan
Re: Element Library
Group Developers

Tim,

You may not need to download anymore CSS as a result of browser caching, but the browser still needs to parse and apply the style rules, and this happens on each successive  page load.

 
Average of ratings: -
Picture of Guy Thomas
Re: Element Library
 

I've noticed that the element library specification has improved accessibility as a benefit but personally I think that this should be part of the project goals.

It would be great if the specification could detail how more usable and accessible design should be achieved.

 
Average of ratings: -
Picture of Urs Hunkler
Re: Element Library
Group Developers

The »element library« is not announced as part of Moodle 2.8. And Sam comments today that he will not continue to work on the »element library« - https://tracker.moodle.org/browse/MDL-36558

What does this mean? Is the project not interesting any more? Is it too complicated to implement? Have you set too high goals which are not possible to reach?

Is the »element library« dead? I was hoping to be able to work with it.

 
Average of ratings:Useful (2)
Dan at desk in Moodle HQ, Perth
Re: Element Library
Group DevelopersGroup Moodle Course Creator Certificate holdersGroup Moodle HQGroup Particularly helpful MoodlersGroup Testers

No its not dead, the message is because Sam is leaving Moodle HQ so he personally won't be working on it.

 
Average of ratings: -
Picture of Urs Hunkler
Re: Element Library
Group Developers

Thank you very much for the info Dan. Can you say anything about the project state?

 
Average of ratings: -
Me!
Re: Element Library
Group DevelopersGroup Moodle HQGroup Particularly helpful MoodlersGroup Testers
I can comment on where this is at:

There are a number of issues that are still not solved by prototype 5.

Re-using renderables for JS - right now we have 2 completely separate theme systems in moodle - anything created by JS is either not themeable, or is accepting a massive pre-rendered, escaped string as an argument. Both approaches suck.

Defining a renderer is complicated and based on strict rules rather than something that is natural to implement. This is the nature of OO I think - but I think maybe we should step back and try something else (I am thinking of using mustache for php/js templates, and replacing render methods completely).

No improvement on the adhoc approach to defining DOM hooks that JS can attach to (we say to use ID's for this - but this is not always the best way and we don't do it consistently). We are constantly creating things that can only exist one time on a page because of the use of IDs.

YUI - if we are making huge changes to the JS templates etc - it does not make sense any more to do it in YUI. We need to propose and move forward with something else (I'm not going to expand on this in this thread for fear of hijacking it).

Because once we add all this foundation work, there will be a huge task in updating existing code to use the new system - we only want to do this once - and it makes sense to hold of on implementing anything until we are sure it meets all our needs.

I have not spent much time on this recently but it's still on my (and Martins) radar. We are still planning what dev issues get prioritised for the next release - hopefully we get the time to do this properly.
 
Average of ratings:Useful (2)
Picture of Urs Hunkler
Re: Element Library
Group Developers

Thank you Damyon for your detailed answer.

One remark to support the mustache template approach - I have been using js/php mustache templates in some themes and to me as I am more a designer than a developer it is much more "natural" to create the repeating page parts in HTML in a template than to write a renderer which then outputs the HTML. When I work with templates I work somehow directly with the output which means I have less abstraction layers and can concentrate more on the details of the HTML page part. From my work experience the mustache approach is quite successful.

When I am working on PHP code I detected several times that writing renderers fits better into the workflow than switching between HTML and PHP all the time. So I understand that developers prefer the renderer approach. And I think working with renderers is much more consequent than echoing HTML strings mixed with PHP variables.

While I write this comment I understand that the "clean" approaches are renderers or templates - not mixing HTML and PHP.

Unfortunately few people in the Moodle field understand the advantage of front-end work with less abstraction - hopefully the mustache approach will be successful for MoodleHQ.

 
Average of ratings: -
Me!
Re: Element Library
Group DevelopersGroup Moodle HQGroup Particularly helpful MoodlersGroup Testers
Yup - my reasons for wanting to prototype mustache over other methods are:

* Generating HTML from php methods is not a clean design - much better for a theme designer to tweak some separate files that look like HTML
* The templates are devoid of logic - this enforces a clean design instead of relying on developers to "follow the rules"
* The templates can be pre-compiled into the localcachedir for speed
* mustache is a very commonly used template library for JS - so is familiar to a lot of front-end devs
* There are good stable mustache libraries for php and JS (we already use handlebars in yui) so we can share the same templates for AJAX or PHP created interfaces (with the data binding happening in the browser or on the server)

There are some other nice things about mustache too - we can pre-populate the template "context" with our common globals (USER, SITE, COURSE) etc, we can define default helpers for looking up strings translations.
 
Average of ratings:Useful (1)
Tim at Lone Pine Koala Sanctuary
Re: Element Library
Group DevelopersGroup Documentation writersGroup Particularly helpful Moodlers

Using templates might well be possible in Moodle now. However, there are some inaccuracies in your post:

  • In a PHP application, HTML will always involve a method call, even if the method is called reder_template(...). Templates add an extra layer.

OK, that is a bit pedantic. Slighly less pedantic

  • It is a fiction to say that templates are devoid of logic. Many templates will contain looks (e.g. forum thread, or any report). Also, many templates will have to contain if statements (e.g. displaying questions with or without feedback, depending on which options the teacher set). It is correct to minimise logic in renderes, and to only have simple display logic there, and many of the Moodle renderers already do that. It is correct that the syntactic constraints of using a templating system make it easier to separate things properly, but it is still perfectly possible to make a bloody mess with complex logic in the templates. It is not a magic bullet.

All that said, I hope you can come up with a good way to use templates in Moodle. For me the three requiresments are:

  1. The code must look nice, and be easy to implement and maintain for developers creating new plugins and functionality.
  2. The code must look nice and be easy to implement and maintain for designers creating Moodle Themes.
  3. The templating layer must not hurt performance too much (unless the other gains are big enough to justify it).
 
Average of ratings:Useful (1)
Me!
Re: Element Library
Group DevelopersGroup Moodle HQGroup Particularly helpful MoodlersGroup Testers
"Logic-less templates" is straight from http://mustache.github.io/

I do agree it's still going to be possible to make a mess. Hopefully it's hard to make a mess. I need to get a bit further in prototyping this before I will know myself.

Side note - this
https://tracker.moodle.org/browse/MDL-47036?focusedCommentId=325700
is great news for this issue, because that would block this progressing anyway (we want to get all the foundation stones properly in place so other people can build cool sky scrapers).

 
Average of ratings: -
Tim at Lone Pine Koala Sanctuary
Re: Element Library
Group DevelopersGroup Documentation writersGroup Particularly helpful Moodlers

OK, so logic-less is meaningless marketing hype on their part: https://github.com/bobthecow/mustache.php/wiki/Mustache-Tags#sections we have iteration, conditionals, and the ability to call function. That is necessary. It is also logic.

Given the limitations of the mustache syntax, it not clear to me it is going to be feasible to convert the question renderers without a huge amount of copying of data into temporary variables. I am hoping that you can prove me wrong about that.

 
Average of ratings: -
Me!
Re: Element Library
Group DevelopersGroup Moodle HQGroup Particularly helpful MoodlersGroup Testers
Note - you have convinced me to tackle some quiz renderers in my prototype - so I should find out how much of a pain it really is to do.

This will give us a nice before / after comparison.
 
Average of ratings:Useful (1)
Picture of Urs Hunkler
Re: Element Library
Group Developers

Yep - it will be nice to work with the element library with jQuery and Mustache wink

 
Average of ratings: -
Dan at desk in Moodle HQ, Perth
Re: Element Library
Group DevelopersGroup Moodle Course Creator Certificate holdersGroup Moodle HQGroup Particularly helpful MoodlersGroup Testers
The code must look nice, and be easy to implement and maintain for developers creating new plugins and functionality.
Given the limitations of the mustache syntax, it not clear to me it is going to be feasible to convert the question renderers without a huge amount of copying of data into temporary variable
To reiterate as I mentioned elsewhere in this thread - if it makes it much easier for designers at the cost of slightly more ugly/laborious code for developers, I still think that is a net win and a price worth paying.
 
Average of ratings: -
Tim at Lone Pine Koala Sanctuary
Re: Element Library
Group DevelopersGroup Documentation writersGroup Particularly helpful Moodlers

I am not sure that I agree.

Current output code, generating HTML strings using either concatenation, or html_writer, is not particularly nice. If you don't think you can do better than that, I think you are being insufficiently ambitious.

Also, life will only be better for designers if developers actually make the effort to covert their existing output code to whatever the new way of doing things is. Therefore, making it easy and pleasant for developers to do that becomes a key requirement. I don't believe doing this should compromise easy of use for designers. Rather, I think it is more likely that working hard to make things as easy as possible for developers too, will make the whole system easier to use for everyone then if we just focus on making something easy for designers.

 
Average of ratings:Useful (1)
Picture of Urs Hunkler
Re: Element Library
Group Developers

@Tim: »If you don't think you can do better than that, I think you are being insufficiently ambitious.«

My approach to outline the advantages in my reflection on your three point list shows a much better development workflow for everybody - I think.

Tim, much agreed that everybody should win at the end. Your statement »if developers actually make the effort to covert their existing output code to whatever the new way of doing things is.« is quite theoretical. Yesterday I tried to change the look of a not core Moodle module - which had been maintained by a person who worked at MoodleHQ - where no styles.css file is used to collect the module CSS but styling is mixed into the code via inline styles. 

Moodle practices a great deal of laize faire concerning following guides and best practice. So I think changes will be adopted when they are explained and the advantages become clear. It looks as if Moodle development will be confronted with some fundamental changes on the frontend side in the near future - the potential move from YUI to some other JavaScript framework and a new development workflow with the integration of an element library. The change process may be accompanied by explanations and examples about the advantages - that could convince more people to accept the need to change their code.

 
Average of ratings: -
Picture of Urs Hunkler
Re: Element Library
Group Developers

One addition related to a change process:

I think not the »ease of use« is primarily important - important is to understand the »why« and to see the advantages.

 
Average of ratings: -
Picture of Urs Hunkler
Re: Element Library
Group Developers

And not to forget the main task of all the effort - that the users can concentrate on the learning content supported by an overall consistent and easy to navigate environment.

 
Average of ratings: -
Picture of Urs Hunkler
Re: Element Library
Group Developers

As I understand templates for HTML web pages they are written as close to the final page output as possible. The HTML template skeleton is pure HTML.

To be able to display varying data in the HTML page HTML template engines offer structures to integrate the data into the page. And they offer loops/conditionals (logic) to enable primarily not known/repeating data to be shown. So the term »logic less« tries to communicate that there is no data generation logic in the template - only data rendering logic.

The process to work with templates is (simplified to focus on the basics):

  1. Generate and save logically structured all data/information that will be shown on the page
  2. Fill in the structured data into the HTML template

This two step process reflects nicely the organizational concept to work with backend and frontend teams.

I prefer to think and work in the language in which the page will be rendered in the browser - HTML - when I have my web designer hat on. It is much easier to see all aspects and work on the details. For me it is even easier to fine-tune the page output when the template and the page view in the browser's web inspector look similar. I can create better quality results in such an environment - and I can create the better results faster.

 
Average of ratings: -
Picture of Urs Hunkler
Re: Element Library
Group Developers

Reflecting on Tim's 3 point list:

1. The code must look nice, and be easy to implement and maintain for developers creating new plugins and functionality.

When developers work on the backend tasks they work on collecting data and structuring the generated data in a logical way. I think it is nice to be able to focus on the tasks how to get the needed data in an efficient way and how to structure it for later output. That is with the backend developer hat on. 

If the same person also creates the HTML page this person will change the hat from the backend to the frontend developer hat and create the HTML template for the plugin. 


2. The code must look nice and be easy to implement and maintain for designers creating Moodle Themes.

Templates are written in HTML with a mix of data placeholders and loop/conditional logic. The skeleton is HTML. It is always nice and easy to work in HTML for web designers wink


3. The templating layer must not hurt performance too much (unless the other gains are big enough to justify it).

Comparing the template rendering process with the renderable/renderer logic used in Moodle now and its several function calls I don't think that working with an optimized template engine will hurt performance more than the actual workflow.

 
Average of ratings:Useful (1)
Me!
Re: Element Library
Group DevelopersGroup Moodle HQGroup Particularly helpful MoodlersGroup Testers
I talked about this in the General Developers Meeting last night - here is an update on where we are up to.

The JS Framework needs to be in place before we implement this support for templates (because we should write the JS template renderer using the new JS framework).

Once the JS Framework is in place we can implement this support for php and js rendering of mustache templates. (There is a prototype here: https://github.com/damyon/moodle/tree/MUSTACHE).

The summary is that the render_thing(thing $thing) method in the renderer is replaced by a thing.mustache template in your components template folder.

Some benefits of these templates are:
Themers can work directly with these templates (they are HTML - not php).
The logic is forced out from the presentation (because mustache intentionally supports only a very limited set of logic operations).
The same templates can be rendered by user interfaces written in Javascript or PHP.
Fully backwards compatible.

Once the template support and the JS framework is in place we need to:

* Write lots of docs on how to use the new system to create renderables and templates.
* Create the element library tool (this was done previously it just needs updating)
* Start building a good set of default renderables to show in the element library
 
Average of ratings: -
Tim at Lone Pine Koala Sanctuary
Re: Element Library
Group DevelopersGroup Documentation writersGroup Particularly helpful Moodlers

One thought about Elements, in relation to the difficulty of getting HTML that requires JavaScript back form an Ajax call.

Here is one example, in the new quiz editing UI in Moodle 2.8: https://github.com/moodle/moodle/blob/master/mod/quiz/yui/src/quizquestionbank/js/quizquestionbank.js#L130

We have just updated the contents of the question-bank pop-up from an Ajax, call, and that content requires various js_init_calls to work. I could do find a way to do that properly, so I just duplicated all the necessary JS calls inline in my code.

Another case, where I just gave up on trying to make it work was in https://github.com/timhunt/moodle-quizaccess_offlinemode. At the moment that is limited to deferred feedback questions, because I could not think of a viable way to reload one question in a page via Ajax. We just don't know what initiation JavaScript each question type might need.

Getting to the point

What I am wondering is, should we try to define a consistent JavaScript API for Elements.

We might have some elements like mod_quiz-question_bank_view, or core_question-question. Perhaps we should say that the main JS module that relates to that Element has the same name, and it implements certain standard functions that you can rely on, like:

init() - this will be called after the HTML of the element is in the DOM of the page, and it is safe to initialise the element.

destroy() - this will be called just before an element is removed from the page (or is after better) so that the element can clean up any event handlers, etc, that will no longer be necessary.

Those may be all we need, or we might find others helpful, like shown/hidden/focus/... I guess we add what we need, when we find we need it.

I really don't know if this would be a good or bad idea, which is why I am raising it as a suggestion, so see what other more experienced JS developers think.

 
Average of ratings: -
Me!
Re: Element Library
Group DevelopersGroup Moodle HQGroup Particularly helpful MoodlersGroup Testers
There are actually several ways to do this and it depends what the javascript is that needs to run, and whether this is newly loaded javascript or existing javascript in the page that needs to be aware of the new thing.

Some more concrete examples:

Case 1:
I load my page and on init it sets up event handlers for 3 checkboxes with specific ids. I load a 4th checkbox into the page via and it needs the same event handlers attached.

Solution:
Use delegated events with a CSS selector that matches any existing or future checkboxes added to the page. Delegated events will automatically work with newly added nodes in the DOM, and will also not care if nodes are removed.

Case 2:
I load my page and on init I need to do something more complicated with 3 specific elements in the page (maybe I'm enhancing input fields to some sort of auto complete field). I load a 4th element to the page and I need the same JS to run on this new element.

Solution:
Because this is not about events, we need a more general solution. On page init we can run the JS code for the 3 existing elements - and set up an event listener to respond to a custom event. When we load the 4th element we can manually trigger the new custom event and then the initial JS can be run by the event listener on the new DOM nodes. We do this with MathJax in the help popups.

Case 3:
This is the most general case. I do not know in advance what JS might be needed (maybe it's from a plugin) I just want to render some new UI piece via AJAX and add it to the page and have any required JS that was generated by the renderer (or template) run automatically.

Solution:
We can support this with the new system. What it will require is a custom "ajax" renderer that collects any generated inline JS calls from the renderer and returns the generated HTML and the generated JS separately. Then the generated JS calls can be inserted into script tags and appended to the page HEAD (must be done after the new DOM elements are added to the page). This can be taken care of by the JS API for rendering. Note - if replacing parts of the UI the event listeners attached to the DOM nodes will automatically be cleaned up by the ".remove()" function in JQuery (or in YUI "Y.Node.remove(true);")

This would actually be really useful/powerful for updating parts of the page via ajax without re-rendering the entire page.
 
Average of ratings:Useful (1)
Tim at Lone Pine Koala Sanctuary
Re: Element Library
Group DevelopersGroup Documentation writersGroup Particularly helpful Moodlers

That's a really good summary of where we are now Damyon (Or in case 3, where we could be with a small incremental change from where we are now).

I suppose where my thinking is going is to say, should we standardise Case 2. Should all Elements that are JS-active fire standard events when they get added to the page (element_initialised???) and perhaps too when they are removed from the page? rather then each element doing it in a slightly different way?

(You are right, custom events are much better than particular methods in a module.)

Then, can we also use this for Case 3? If you need a sequence of complex initialisation calls when your elements is added to the page, well, just subscribe the your own element_initialised event, and call the sequence of functions you need to call?

(For passing data to JS, I am assuming we will prefer to use data attributes, rather than passing arguments to js_init_call functions like we tend to do now.)

(Oh, I suppose a new element may need to make new strings available through M.util.get_string. We need a nice way to handle that, but I am sure we can find one.)

 
Average of ratings: -
Me!
Re: Element Library
Group DevelopersGroup Moodle HQGroup Particularly helpful MoodlersGroup Testers
More details about how we implemented Case 2 for MathJax.

The custom event we created - we tried to make it generic so any of the filters could subscribe to it. It's in: lib/yui/src/event/js/event.js (in core - not in the filter) and it's called filter-content-updated.

We trigger it from various places in Moodle (the glossary auto-linker and the atto equation editor) - and any filter can subscribe to it and re-run and JS required for filtered text if they want to support that.

This is sort of a standard way to do it - but it's hard to call it a standard when you're the first smile

Re: get_string - case 3 would cover this as the JS to add the new strings would get automatically run. We could also fetch the missing strings on demand via AJAX if they were not present when required - but we haven't done that in the past because we didn't want anyone to get lazy about calling strings_for_js (performance).

 
Average of ratings:Useful (1)
Picture of Danny Wahl
Re: Element Library
Group DevelopersGroup Particularly helpful Moodlers

The logic is forced out from the presentation (because mustache intentionally supports only a very limited set of logic operations).

I don't know if we're talking about actually using mustache or a mustache-like implementation like handlebars.js but I just began playing with Ghost which uses handlebars.js and one of the things that I've seen there is that already they're finding they need to extend the mustache API to include more logical operators than before, and their output needs are much more limited than Moodle's.

So I would encourage that we look at all output page types (defined in a theme config) and really work to build a strong API for as many cases as possible out of the gate- or a dev doc saying 'here's the proper way to do it in the component'- instead of implementing new logic every update.

Here's examples of what I'm talking about @ ghost:

https://github.com/TryGhost/Ghost/issues/4799

https://github.com/TryGhost/Ghost/issues/4017

https://github.com/TryGhost/Ghost/issues/4798


I'd hate for our templates to either a) suck because the API isn't robust or b) suck because people are hacking solutions because the API isn't robust tongueout

 
Average of ratings: -
Me!
Re: Element Library
Group DevelopersGroup Moodle HQGroup Particularly helpful MoodlersGroup Testers
Yes we are talking about actually using mustache (not handlebars). Because:
a) The php implementation of mustache is much more robust and compliant to the standard than the handlebars one ( I tested the handlebars one and found it was buggy and incompatible with the JS version ).
b) Handlebars is less strict and so allows more logic to leak into the templates.

From one of your examples above:
{{#get "posts" id="current-post-id" include="next,prev"}}

This is an example where a developer who is also writing the template can understand it - but someone who knows nothing about the renderer cannot. What are the valid arguments ? How do I pass variables ? What permission checks do I need to add to see the next/prev posts ?

If this was in Moodle, next and prev should be pre-calculated public properties of the renderable - not fetched from the template.
 
Average of ratings: -
Picture of sam marshall
Rendering - theme customisation with PHP
Group DevelopersGroup Particularly helpful MoodlersGroup Testers

Overall this seems like a very good plan but I do have one potential serious issue that would affect us at the OU, and I know other institutions with very specific requirements do similar things.

Basically, in the new templated approach, will it still be possible for themes - or a suitable plugin - to override what happens when a renderer displays something, using PHP code and not only templates?

I'm not saying this should be the general approach, absolutely not. But it's really important that there is some way to do this because it's basically the solution of last resort for customising Moodle, and there are quite a lot of things you can't customise any other way without modifying core code, which is always bad for maintenance.

To give a simple example, we have logic about who should see the Settings block on certain pages. We can implement this without modifying the Settings block itself, by changing the theme renderer that displays blocks. So if it's displaying the settings block, and if the current page is x, and if the user does not have capability y, then we return blank instead of displaying the block.

There are other examples where we want to hide a certain link that is available in Moodle, but there is no way in Moodle settings to get rid of the link. What we do instead is, in the renderer for that part of the page, call the normal renderer then do a regex replace to remove the unwanted link and adjust the HTML as suitable. Again this may well depend on business logic such as the user's capability, or whether editing mode is turned on, or the current course shortname, or whether a particular type of module exists in the current course, or something.

In a sense this is not really a 'theme' type of thing, but the theme provides a really powerful mechanism in Moodle for configuring that type of detail, so removing it would be a big concern for us. As you can tell from the two examples I've given, these changes are usually kind of hacky and some of them are prone to break on Moodle upgrades - but it's still far less horrible than if we had to go and hack the core code every time we need a small change like that.

So anyhow what I'm wondering is, is there still some way for the theme (or a local plugin or whatever, I don't mind) to override this process at a low level? For example some kind of hook at the point where it would normally do the 'call the templating engine and return the results' bit.

If there isn't already, please could one be included? I wouldn't anticipate this hook being used by any core or plugin code, but strictly by third-party sites like ours which need to modify some parts of the default rendered output, based on arbitrary PHP code rather than just a template.

Thanks,

--sam



 
Average of ratings:Useful (2)
Me!
Re: Rendering - theme customisation with PHP
Group DevelopersGroup Moodle HQGroup Particularly helpful MoodlersGroup Testers
"will it still be possible for themes - or a suitable plugin - to override what happens when a renderer displays something, using PHP code and not only templates?"

- Yes absolutely. A template and a renderer method will be mostly interchangeable, and the rules for priority will still apply (in decreasing order theme -> theme parents -> plugin -> base). The only edge case to consider is when there is both a template and a renderer method for a theme/plugin - in this case we will choose the template.

But - this just means that any existing renderer method overrides will continue working even as we convert core renderers to templates - but the "nastiness" of that approach still remains (I understand that it is purely to avoid modifying core).

I think it is a good idea to add a new "hook" to the render system, so that the theme can manipulate the data before it is passed to the template. This would be pretty easy to add in, and addresses something Tim raised a while ago in relation to templates. Tims concern was that when he used templates in another system (I think they were for mediawiki) the template did not have all the data he needed to do his modification, so he first had to modify the calling code to add a lot more data to the template. If we add a hook (prerender) at this point, we can make it simpler to do these sorts of advanced modifications. This prerender hook could get called for either templates or renderer methods.







 
Average of ratings:Useful (1)
Picture of sam marshall
Re: Rendering - theme customisation with PHP
Group DevelopersGroup Particularly helpful MoodlersGroup Testers

Thanks for confirming that! That's really helpful - as long as we can still do our "nasty" approach in the theme, then it'll be fine. So one less thing for us to worry about.

The pre-render hook idea would be a really neat improvement. For instance in the example I gave about removing a link depending on a php check (we also have some that add links similarly), depending on how that renderer/template works, we could potentially change an input data structure to remove or add a link, and not need to alter the actual template at all.

--sam

 
Average of ratings: -
Me!
Re: Rendering - theme customisation with PHP
Group DevelopersGroup Moodle HQGroup Particularly helpful MoodlersGroup Testers
Progress report!

I have a chain of issues in an Epic for this new template work (and the JS Framework work) - and they are ready for more eyes.

The JS Framework issue (MDL-49046) has had a good peer review from Andrew and is up for integration already - the rest are up for peer review - but I also want external feedback, particularly for the templates.

There are draft developer docs explaining the new systems.

Epic: MDL-49045

New Javascript module support (including jquery).
Issue: MDL-49046
Dev Docs:https://docs.moodle.org/dev/User:Damyon_Wiese/Javascript_Modules

Templates
Issue: MDL-49152
Dev Docs:https://docs.moodle.org/dev/User:Damyon_Wiese/Templates
 
Average of ratings: -
Me!
Re: Rendering - theme customisation with PHP
Group DevelopersGroup Moodle HQGroup Particularly helpful MoodlersGroup Testers
And some more specific info about some changes to the template system design to make it more flexible and practical:

Initially I thought it was a good idea to implement templates as a replacement to renderer render methods. But I was wrong, that has too many negative consquences.
1. There have never been restrictions on renderable classes before (only recommendations), so some have logic, complex data types etc. Imposing new strict conditions on renderables would create a lot of refactoring work for everyone.
2. As sam pointed out, sometimes you want to override the HTML, but some times you want to override the data the HTML is using.

A more flexible approach is to still have render methods in the renderer, but those methods can choose to call "render_from_template" if they want to. They can also choose which template they want to render (e.g. to combine multiple things). There is still a step required to "flatten" the data for the template - to help standardise this I added an interface for templateable with a export_for_template function. This function should take the renderables data and return an stdClass containing only strings, ints, bool, float, stdClass and array properties.

Note that this is fully backwards compatible. If a theme has overridden the render method, their version will just not call the template. If they want to change the data fed to the template they can override the render method, but not override the template. Or the other way around.

And another benefit to the above approach is that it provides a way to pass this data to the javascript for client side rendering. The same export_for_template function can be exposed as a webservice, then (combined with MDL-49163) we can load or reload the data for the template at will.

 
Average of ratings: -
Me!
Re: Rendering - theme customisation with PHP
Group DevelopersGroup Moodle HQGroup Particularly helpful MoodlersGroup Testers
Me again.

Another thing to mention is that - right now JQuery UI is not a done deal.

It has incompatibilities with bootstrap. It's dom structure and theming system is alien to what we have used before. It's accessibility features are only "good" not great.

In the meantime, what I am proposing is to use AMD "wrappers" that still call our old YUI implementations. That way we can write new code in AMD without using YUI directly, and later when we have a good alternative we can replace those wrappers.

It would be terrible to have different looking/behaving UI widgets all over this place - so this approach at least keeps things consistent while we start transitioning.
 
Average of ratings:Useful (1)
Tim at Lone Pine Koala Sanctuary
Re: Rendering - theme customisation with PHP
Group DevelopersGroup Documentation writersGroup Particularly helpful Moodlers

Can I suggest we start trying to impose rules on renderers for newly written stuff at least. There was something implemented recently in core Moodle, which had a horribly about of logic in the renderers. I can't remember what now, it might have been the badges renderer, or the category editing UI renderer. Anyway, I am surprised that the integrators let it thought. Let me give a clue: if you refer to $DB in your renderer, you are doing it wrong.


Regarding 'A more flexible approach is to still have render methods in the renderer, but those methods can choose to call "render_from_template" if they want to.' - that was pretty much the plan for day 1 when the renderer concept was first raised. wink


To get to a more serious question, thinking about the whole element library thing. Some bits of the picture are now clear. We have elements, and generally an element is output by calling a renderer method that calls a template. But ...

  1. Ideally, output of larger elements will be made of up smaller elements. E.g. A forum thread is made up of a lot of forum posts. A forum post includes a user picture, and the user's name, and some buttons and links. How does the code for the outer template trigger the generation of the inner elements?
  2. And, don't just say {{> pacman }} as in the docs, because you have also just said that the marshal the data required to call a template, you need to go through a renderer method.
  3. This also relates to calling templates in JS. The necessary data-marshalling PHP code will not be available there, so how does it really work?

Unless it is easy for developers to output elements, no-one will ever user them, and we all want the benefits they bring. Please explain.

 
Average of ratings:Useful (1)
Picture of ryan sanders
Re: Rendering - theme customisation with PHP
Group Particularly helpful Moodlers

my head is spinning! from reading this entire thread.

  1. php hat = making code (functions, classes, database calls)
  2. javascript client side only hat = drag and drop, mouse pointers, tabs, menus, datepicker, html5/canvas/javascript games. 
  3. javascript ajax hat = without needing page to re-load, do something between user interface and server. 
  4. html hat = is declared in renderer.php (simple logic referring to php hat other files) mini amount of javascript, to call from "javascript client side only hat"
  5. mustache hat = ajaxrenderer.js.php  (short simple calls between client side and server side, it does what ever on server side, and sends back info to client side, and updates something on client side) this file just holds the template much like "html hat"
  6. mustache hat client side = ajaxrenderer.js ? or is included in "javascript client side only hat"

*looks confused*

 
Average of ratings: -
Me!
Re: Rendering - theme customisation with PHP
Group DevelopersGroup Moodle HQGroup Particularly helpful MoodlersGroup Testers
Thanks Tim

- re: "the plan for day 1" - initially the plan was to be able to override a renderer render method with a template completely, which would have meant that the properties of the renderable would need to be completely flattened (only string, int, array, stdClass, float, bool). Which would have meant refactoring most of our existing renderables.

To the more serious questions (ahem):

1. There are 2 ways (at least). The first is, if all the smaller elements are converted to templates already - the data-marshalling code for the "forum thread" calls the data-marshalling code for all the "forum posts". Then the "forum thread" template, can use {{> mod_forum/post }} to show the template for the posts in the right place.
2. OK - so you didn't like {{>}} - (or more likely, the smaller elements have not been converted to renderers). Here comes the second method... "$data->post = $output->render(post);". That is why the signature for the export_for_template() method requires a renderer ($output).
3. One of the other important changes in the epic is MDL-49163, a generic ajax script that exposes webservices. So if you want to expose the data-marshalling php code, you expose it as a webservice.

Some pointers to a working example of this:

Data marshalling exposed as an external function:
https://github.com/damyon/moodle/blob/LP/admin/tool/learningplan/classes/external.php#L491

Javascript to call a webservice function that changes data in the db, then reloads the data for the template, and finally updates the page with the re-rendered template.
https://github.com/damyon/moodle/blob/LP/admin/tool/learningplan/amd/src/frameworkdelete.js#L32
 
Average of ratings: -
Tim at Lone Pine Koala Sanctuary
Re: Rendering - theme customisation with PHP
Group DevelopersGroup Documentation writersGroup Particularly helpful Moodlers

"The first is, if all the smaller elements are converted to templates already" - As I think I have said before. I have serious performance concerns about this. If you don't know exactly what the outer template is going to do, you might have to speculatively flatten a lot of objects, just in case the template wants to output them.

I want an object to encapuslate the necessary work, like the lang_string class sets up everyhting necessary to call get_string, if you really output that thing later.

Presumably, that is doable if all the data-marshalling methods have a consistent enough API.

 
Average of ratings: -
Me!
Re: Rendering - theme customisation with PHP
Group DevelopersGroup Moodle HQGroup Particularly helpful MoodlersGroup Testers
Lets consider the reasons why you might not want to show something.

1. There is some "logic" that determines if you can/should/do see something

This logic should not be in the template - you can apply this logic when flattening, or when the renderable is constructed, or before passing data to the renderable in the first place. The template should only receive data that is acceptable to display. This is important because the flattened data could be exposed in the ajax requests.

Example - "show description after date X"

If the date is after X the description field is included in the flattened data, otherwise it is empty.

2. There is an aesthetic reason for not showing something. In this case it is better to include the thing in the template data anyway, because a theme designer might decide to show it.
 
Average of ratings: -
Tim at Lone Pine Koala Sanctuary
Re: Rendering - theme customisation with PHP
Group DevelopersGroup Documentation writersGroup Particularly helpful Moodlers

2. I still disagree.

Let us take as an example displaying the list of courses on the front page. The theme may, or may not, want to show the description of each one. It is hugely expensive to call format_string on each description (different context) and pointless to do so if they will not be displayed.

We have a model (lang_string) which we know works. We know we can apply it here if, as you define the APIs, thing are done in a sufficiently consistent way. If you don't do that now, we are screwed. I really hope you can think about this now and get it right.


In another part of the work (MDL-49163) you are saying Ajax calls from all JS should be handled in a consistent way. Good. Let's have similar consistency for data marshalling. That will also help our Ajax be consistent.

 
Average of ratings: -
Picture of ryan sanders
Re: Rendering - theme customisation with PHP
Group Particularly helpful Moodlers

  1. course -> teachers activity / resource 
    1. school district repository for various activities / resources shared throughout the school.
    2. only teachers have access to this course, and for quick access just for teachers it is placed high up on list. on front page.
    3. students never see this course
  2. when student goes to front page. courses are checked to see if they are visible to the student. via enrolments / registered user, etc...
    1. php function returns a sql statement that returns just the courses that the student sees.
      1. the list is pushed to the template (mustache)
    2. php function returns a sql statement that returns all courses, and then a php script that sorts what courses are and are not allowed for student to see. 
      1. the re defined list via php script is pushed to template (mustache)
    3. php function returns a sql statement that returns all courses,
      1. list is pushed to template (mustache) and the template decides what information should or should not be shown based on enrolment / permissions / registered user / etc....
  3. "Tim Hunt course page with or with out descriptions"
    1. php function returns a SQL statement that includes course names and course descriptions
      1. php script sorts the returned statement to check against permissions and spits out a redefined list
      2. the redefined list is pushed to template (mustache) 
        1. course name gets displayed
        2. check on description in template (mustache) for description display or not. (information already there for description)
    2. php function returns an SQL statement that includes course name, and a template option "show descriptions"
      1. php script sorts the returned statement to check against premssions and spits out a redefined list
      2. the redefined list is pushed to template
        1. course names get displayed
        2. a if(!course_description) is used to check for description information
        3. OR
        4. course names get displayed. 
          1. another template is required. due to this other template does not contain the "course description check"
    3. php function returns an sql statement that includes course name
      1. another php function returns an sql statement that includes course description
      2. course name is pushed to template (mustache)
      3. themer for template decides not to show descriptions so comment out "display description lines within the template"

=====================

Tim Hunt to me, you are asking for a themer to have options in the theme / template / mustache, that go all the way back to sql statements and basic php functions.

or are you trying to drive at.... that template (mustache) drives everything.  template loads first. and from the template if it sees {{thread=1595}} then mustache API looks up the thread variable, and then loads up moodle/mod/forum-> thread-> and then pulls up information for 1595 thread id.   other words instead of back end to front end...  you are wanting front end to drive what is happening in the back end? there is a difference. programmer and there php / javascript stuff building something to work within the front end. (providing another feature),    vs front end being able to mix and match different back end php/javascript. 

or are you asking that {{{thread,option_text_link,option_button,option_color}}} the options be additional considerations back end programmer needs to take into consideration?

 
Average of ratings: -
Tim at Lone Pine Koala Sanctuary
Re: Rendering - theme customisation with PHP
Group DevelopersGroup Documentation writersGroup Particularly helpful Moodlers

"Tim Hunt to me, you are asking for a themer to have options in the theme / template / mustache, that go all the way back to sql statements and basic php functions."

No, I am not.

In the template for displaying a list of courses, you will have an array of 'course' objects. And each course object will have a field description. If you output course.description (or whatever the syntax is), then the description will be output with all the expected filters applied, because it has passed through the format_text function.

The template does not need to know when format_string was called. It could be that course.description is a PHP string, which can just be output. Or it could be that course.description is a PHP object with a __toString method  that calls format_text with all the right arguments if the description is actually displayed, but if not, does not do any work. As far as the template is concerned, course.description is logically a string.

 
Average of ratings: -
Picture of ryan sanders
Re: Rendering - theme customisation with PHP
Group Particularly helpful Moodlers

now i am understanding "order of preference" in what gets called first in overall code.  and then what is called next.  or rather i should say...

function a(){} = permissions
function b(){} = template
function c(){} = filters


if description = null, then pass over "filter types"

if template / renderer was commented out for "description" of a course.  there is no reason to run "filter types" and or even checks for filter types. 

when i say "filters" i mean 

 you are wanting to hold the last pulling of information from these types. till template is almost completed or has completed and/or ran each time template actually pulls in data to be displayed. 


 
Average of ratings: -
Me!
Re: Rendering - theme customisation with PHP
Group DevelopersGroup Moodle HQGroup Particularly helpful MoodlersGroup Testers
I'll mock this up and then we can discuss the impacts of it. Right now my concerns are:
1. How to send this data to JS - and the performance of lots of individual ajax callbacks
2. Keeping the templates 100% compatible with php or JS (because of 1)
3. Adding feature creep into the Mustache implementation that makes the templates harder to understand for non-programmers
 
Average of ratings: -
Tim at Lone Pine Koala Sanctuary
Re: Rendering - theme customisation with PHP
Group DevelopersGroup Documentation writersGroup Particularly helpful Moodlers

3. I don't think there should be any impact on the templates. Providing Mustache is happy to take an object with a __toString method in place of a string.

1. Initally, at least, I would just do the [object with __toString] -> String conversion before sending back the JSON in response to the Ajax request.

2. Hence this should not be an issue.

 
Average of ratings: -
Me!
Re: Rendering - theme customisation with PHP
Group DevelopersGroup Moodle HQGroup Particularly helpful MoodlersGroup Testers
Hi Tim, I tested and that does work fine with mustache. So - as it adds no new features to the template language itself it seems perfectly fine (and useful).

 
Average of ratings:Useful (2)
Picture of ryan sanders
Re: Rendering - theme customisation with PHP
Group Particularly helpful Moodlers

taking a stab at your last post Damyon Wiese

  • <div templateid="thread"></div>
  • <div templateid="post"></div>
  • <div templateid="username"></div>
  • <div templateid="post_date_modified"></div>
  • <div templateid="post_date_created"></div>
  • <div templateid="forum_title"></div>

ajax needs a way to "identify" which template to call.

other words...

  1. loaded up in some course page with "editing turned on"
  2. drag and drop an activity/resource to re-order things
  3. ajax grabs ID number of activity and current sort order, and sends info off to server / moodle
  4. php at server does initial php / SQL updating.
  5. php at server then looks at rest of AJAX sent information for "templateid"
  6. template coding does it thing
  7. template creates a (xml/json) what ever case may be. and send it to client.
  8. AJAX at client side obtains a string of data (xml/json) 
  9. AJAX updates client side DOM (elements) along with adding/deleting javascript if any was included via AJAX send/receive. 

if AJAX was to update an entire thread, the ajax would need to send templateid="thread",   

if AJAX was used to submit an image to server for uploading, then AJAX would need to know "<div templateid="image_area"  or next <div></div> outside of that. example  

  • <div templateid="page">
    • <div templateid="forum>
      • <div templateid="thread">
        • <div templateid="post>
          • <div templateid="postnumber">
            • <div templateid="editing_post">
              • <div templateid="file_manager">
              • <div templateid="atto/tinymce_editor">
              • <div templateid="file_area>
                • <div templateid="image_area>

if in original page load there was no <div template="file_area"> then template would need to look at <div templateid="editing_post">   if no editing post, then post number...etc... working back to root of tree. 

it almost seems like you are trying to figure out how to "work backwards" for a generic "tree base menu" and finding what is needed. 

if you treat ajax calls, and javascript that goes along with the <div> statements above. so it is all a common tree base structure. such as DOM in a browser... ((most likely having a tree setup for each thing))  client side only js = tree 1,  <div> = tree 2, ajax = tree 3,  you might be able to condense each tree better? and some sort of common "id" between all trees, to link each thing together?

or am i missing your concerns Damyon wiese?




 
Average of ratings: -
Me!
Re: Rendering - theme customisation with PHP
Group DevelopersGroup Moodle HQGroup Particularly helpful MoodlersGroup Testers
Tims suggestion of using php classes with __toString() methods so that they are only evaluated if they are used in the template solves this issue - what I was asking before was if Tim was expecting the same "lazy" evaluation to occur in the javascript which would require a standard way of sending an object from php to javascript with enough info that the javascript could callback to the php if the data was needed. This would be complex and slow because of the increased number of ajax callbacks - so I'm glad we do not need to explore this path any further.

 
Average of ratings: -
Picture of ryan sanders
Re: Rendering - theme customisation with PHP
Group Particularly helpful Moodlers

thank you for the 2 links... more so second link.

<quote username="damyon wiese">

Data marshalling exposed as an external function:
https://github.com/damyon/moodle/blob/LP/admin/tool/learningplan/classes/external.php#L491

Javascript to call a webservice function that changes data in the db, then reloads the data for the template, and finally updates the page with the re-rendered template.
https://github.com/damyon/moodle/blob/LP/admin/tool/learningplan/amd/src/frameworkdelete.js#L32

</quote>

if i goto www.vbulletin.com they have similar "mustache" approach, to there code, for the overall forums.  i do believe www.phpbb.org also has something like "mustache" for there template setup. 

also starting to see connection between mustache and bootstrap. and then the backend (php,html,javascript,css) end of things. 

i am also see ability to push the "mustache" to client as javascript. so it is already there. and only needing to pull via "ajax" to fill in missing data within the mustache templates. 

==============

looking at <quote username="Tim hunt">As I think I have said before. I have serious performance concerns about this. If you don't know exactly what the outer template is going to do, you might have to speculatively flatten a lot of objects, just in case the template wants to output them.<quote> 

if i read you correctly, you are hinting at difference between creating a large file. with complete template mustache style. vs splitting things down to each individual element.  and needing to override entire template for just a single change in one template. vs just being able to update just a single element and not having that single template to pull from. 

to me, you are stating, someone is going to pull a "forum post" from a thread. and try and insert it into a "activity ->book" or (taking it into ridiculous) insert the "forum post" into a spot were there should be someone's name.   seems like to much IF's and But's.  vs reality most things stay in a given structure type, that is formed / created by the programmer of the given mod / plugin type. and in that a (known template can be found) and you are putting focus on performance, were every template will need to be loaded up into memory and sorted through on each page load and/or or ajax call. 

=================

just trying to make sense of it all. 

 
Average of ratings: -