Note:

If you want to create a new page for developers, you should create it on the Moodle Developer Resource site.

Renderer consistency
Project state Specification
Tracker issue https://tracker.moodle.org/browse/MDL-45829
Discussion https://moodle.org/mod/forum/discuss.php?d=261202
Assignee Damyon, Sam

Note: This page is a work-in-progress. Feedback and suggested improvements are welcome. Please join the discussion on moodle.org or use the talk.

This page documents the proposed core elements, variations of them, what we expect they will contain, and the core_renderer block.

The user action

An action in this sense is a collection of data that all pertains to one action that can be taken by the user. The action, once populated with data can be rendered as is required for the job it is going to fulfil, usually with some relation to the frontend framework in use. In this way the action could be a link, or a button; it could even be interpreted into a more complex structure.

An action has the following properties:

content [string]
text content for the link or button.
url [moodle_url]
the url for the action to take when the user interacts with this action.
description
a description of the action. Typically used within a title or alt attribute.
active
True if this is the action the user is current performing.
enabled
True if the action is possible, false if it is not possible and should be shown as disabled.
dimmed
True if the action should be shown as dimmed, usually used to the action is hidden to other users.
method
The preferred method of submitting this action, typically GET but can be set to POST.

It is also possible to add JavaScript actions (component_action objects) to an action. These attach a JS listener to the action that gets executed when the user interacts with the action. Attached JavaScript actions get initialised when the properties for the action are retrieved so any events must be attached BEFORE the action is rendered, and all renderers must ensure they use the get_attributes() call.

Grids

We need to come up with some way to include grids in core, it is desirable to keep it framework agnostic so perhaps a grid object that allows for items to be added and a "width" specified when that occurs. The width would be either a fixed number or a percentage. Steps of 12 seems pretty common.

Design requirements

The following concepts need to be accounted for in core, or decisions made on how we choose to support these and where.

Clearfix

We have this in core already, bootstrap has it, pretty much every front end framework has it. Clearfix is more of a design decision, should only be used when require, and only ever applied by a renderer. This gets special mention as being important, support is already 100%.

Floats

Pull left, pull right etc. These are a design decisions and should be implemented by the renderer. Bootstrap caters for these and as such they will be easily catered for in bootstrapbase, however work may be required to get them operational in base.

Discarded ideas

The following things are ideas that came up during discussions on what elements are, and what elements we want in core that have being discarded.

Core atoms, molecules, and organisms

Action {atom}

See the section above about #The user action

Actions are special atoms the represent an action the user can make. They can be rendered by a theme as a link, a button or I suppose anything else. There should be a default for when it is not specified and the renderer in change of producing the current thing can decide whether to use the default and just call render or if it requires something specific render_link or render_button as required.

Block {atom}

Unique to Moodle. This represents a block on the page, and is displayed within a #Block region. It accepts two arguments, the first is a block_contents object instance, and the second is the region name the block instance is being shown within.

At present a block is rendered using the core_render::block method. Internally this calls several renderer methods to produce the different parts of a block.

  • core_renderer::block_header - Produces a header
    • core_renderer::block_controls - Produces controls to display within the header.
  • core_renderer::block_content - Produces the actual content of the block.
    • core_renderer::block_controls - Used to check if block controls were rendered. PUKE!!!
    • core_renderer::block_footer - Produces a footer that actually resides within the content.
  • core_renderer::block_annotation - Produces an annotation, used VERY rarely.

Current structure

The following is the output when called for a navigation block with a bit of extra added to show how a footer is displayed and an annotation. <a href="#sb-1" class="skip-block">Skip Navigation</a>

Block region {molecule}

Unique to Moodle, the block region is a contain for all of the blocks in one location. We currently have two methods that produce a block region within Moodle, the first is core_renderer::blocks_for_region which adds no surrounding content. The preferred method core_renderer::blocks adds some embedded information to a common structure.

Current structure

The following is the structure of the core_renderer::blocks() method. public function blocks($region, $classes = array(), $tag = 'aside');

The following is the html output is $region was pre and the default tag and classes were used. <aside id="block-region-pre" class="block-region" data-blockregion="pre" data-droptarget="1"> </aside>

Thoughts on this

The blocks method is a convenience method and serves an important purpose. However it should not take classes and tag as arguments.
These should certainly only settable within the renderer itself, and if themes wish to change this without wrapping the call they should override the renderer.

Both the data attributes relate to servicing JavaScript functionality. Perhaps they should be moved to a component_action or somehow else integrated with JS rather than with the renderer directly.

Internally it is calling blocks for region, however this should change it should request a array of blocks, convert the array to #Block elements and call render on each.

Proposed HTML structure

Much like the current structure but with the data attributes coming through a JS mechanism.

<aside id="block-region-pre" class="block-region"> </aside>

Breadcrumb {molecule}

Currently called the navbar within Moodle, controlled by the navbar class located in lib/navigationlib.php and rendered by core_renderer::navbar().
Internally it calls moodle_page->navbar->get_items() to get an array containing navigation node items to display in the navigation bar.
It produces a bit of surrounding structure before calling render on each item.

Current structure

The following shows the structure for two items in the navigation bar presently within Moodle.

Page path <nav class="breadcrumb-nav">

</nav>

Notice the excessive amount of markup to make the separator accessible.

Markup in various frontend frameworks

Bootstrap 2.3.2

Bootstrap 3

Zurb foundation

Design considerations

  • The currently active page should be marked with a class.
  • The current item should probably not be a link MDL-46037
  • wia-aria breadcrumb role
  • The divider perhaps could come through CSS with these changes to avoid markup necessary to make it accessible (in combination with the above).

Implementation thoughts

  • Owns an array of [#Action {atoms}]

Buttons {atom}

This will be both an element and a representation of a [#Action {atom}].
Obviously buttons can serve different purposes and roles so have several easily reachable customisations is probably a wise idea.

Current structure None, presently you produce a button when you need it so there are several throughout Moodle.

Markup in various frontend frameworks

Bootstrap 2.3.2 and Bootstrap 3 <button type="button" class="btn btn-default">Default</button> <a href="#" class="btn btn-default btn-lg active" role="button">Link</a> <input class="btn btn-default" type="button" value="Input">

Customisations available through Bootstrap:

  • Purposes: default, primary, success, info, warning, danger, link
  • Sizes: large, default, small, extra-small
  • Block level (wider)
  • States: Active, disabled.

Zurb foundation <a href="#" class="button">Default Button</a>

Customisations available through Zurb Foundation:

  • Purposes: default, secondary, success, alert
  • Sizes: large, default, small, tiny
  • Corner style: radius, round
  • Expanded (wider)
  • States: disabled

Calendar {organism}

A simple idea really, apparently not already covered by the frontend frameworks being referenced during the creation of the doc. The display of the calendar is fixed, but it can contain content for each day shown.

The calendar should have several views, perhaps these are separate organisms, perhaps not.

  • Compact month
  • Month
  • Week
  • Day

Each day could:

  • Contain an action with an icon for events, and link to the fullday display.
  • Have an associated action to load and display the events in a tooltip.

Collapsible region {molecule}

We use these in several places within Moodle. I could not find a reference to this concept in any of the frontend frameworks I looked at. The concept is simple - you have a heading and an icon with content. By default the content is hidden, when the user clicks the heading and/or the icon the content is revealed.

As noted we do this in several places within Moodle, it would be good to have a single way of displaying this idea of a collapsible region.

Design thoughts

  • It should support an optional collapse/expand all trigger action.
  • We want to be able to use it both inside and outside of forms.
  • It should be usable in situations like the combo list frontpage component as well.
  • Will obviously have a JS component as without JS it would not work.

Confirmation {molecule}

A simple concept used regularly in Moodle to confirm a users intention to perform an actions. Most commonly seeing when deleting content. The structure is relatively basic in Moodle at present.

  • A message
  • A forwards button
  • A back button

Current structure

The method core_renderer::confirm does the rendering at present. Its signature is as follows: public function confirm($message, $continue, $cancel);

The output it produces is like:

The message goes here

Continue

Choice

Not sure about this one quite yet. A description with 2 or more actions allowing the user to select the next step. Think of it like when editing a module you get: Cancel, Save and return to course, Save and display

Divider

Think horizontal rule.

Dropdowns

  • From button
  • From link
  • From icon

Forms {organism}

This is an advanced organism and would be quite a bit of work to create in Moodle as we'd need to translate from QuickForms to elements for rendering. It would be worthwhile doing this however, and would be a good way of quickly showing our new work.

Frontend framework structures

All of those are quite in-depth and offer a range of configurations. We should carefully consider these when analysing our work here.

Headings {atom}

Currently handled by core_renderer::heading.

  • h1 - h6
  • Optional icon
  • Optional help icon

Current structure

The render method is currently: public function heading($text, $level = 2, $classes = null, $id = null);

The output generated by this is, assuming we use the default level, classes, and id.

I am a heading

Whats worth noting is that the render method should not accept level and classes as arguments. These should only be set by the render method and should not be directly influenced.

Image {atom}

There are really two types of images to focus on here, or really two ways to display an image to focus on here.

  1. Standard images
  2. Thumbnail images

Each of these would share some common properties:

  • Image
  • Description (alt/title)
  • Size
  • Action (making it a link) - This would actually make it a molecule, we would have to consider this and either have a new element, drop the ability to wrap in an action, or simply ignore this inconsistency.

Image - Icon {element}

This covers the display of an icon. Should be a separate element from image as really they should be treated individually. Within Moodle there are a few classifications of icons to consider:

  • Standard icons
  • Help icon (popup, tooltip)
  • Loading icon (really regular icon but worth showing separately as its only seen when required)

Image - Profile picture {molecule}

We already have a user_picture component within Moodle. It can be found in lib/outputcomponents.php.
It has two render methods, core_renderer::user_picture and core_renderer::render_user_picture.

Current structure

The following is the output structure for the user picture: <a href="#" id="userpicture_randomid">

   <img src="#" alt="Picture of Joe" title="Picture of Joe" class="userpicture" width="[35, 100, XX]" height="[35, 100, XX]" />

</a>

What you'll notice about this is that the link has no attributes marking it as a user picture link.

The PHP code for the user_picture object itself is really quite in depth and complex. The component serves the user profile fields required to render a user picture. This is good in the scope of the component but would be bad within the scope of an element.
Don't you wish we had a proper user object!

Links

Lists

  • Ordered list
  • Unordered list
  • Presentation list (currently our unlist)

Menu

  • Orientation (Horizontal, Vertical)
  • Nesting

Navigation

Navigation is a collection of actions.

Notification {atom}

  • Info
  • Success
  • Warning
  • Danger

Menu

Action group

Icon menu

Navigation bar

Formerly navbar, can't be called that because the render method would conflict.

Tabs

Page header {molecule}

Currently being produced by core_renderer::page_heading this is simply a header for the page, by default the only h1 element on the page.

Current structure

The render method has the following signature: public function page_heading($tag = 'h1');

The output from the above method is:

The page heading (from moodle_page::heading)

The core_renderer method should not allow the tag to be set. The page heading should always be H1. If its not an H1 then page header should not be used.

Frontend framework examples

Bootstrap 2.3.2

Heading

Tagline

<a class="btn btn-primary btn-large"> Learn more </a>

Bootstrap 3

Foundation doesn't appear to have a page header component.

Design thoughts

  • In Moodle all page headings are set as a single string, we won't be changing this.
  • Usually just a plain string sometimes an icon is used, and sometimes a help icon is used.

Progress bars {molecule}

A pretty simple concept, we already have a couple of ways of producing progress bars within Moodle.

Markup in various frontend frameworks

Bootstrap 2.3.2

The following options are offered by Bootstrap 2.3.2:

  • Striped
  • Striped + Animated
  • Stacked (multiple bars forming a single)
  • Colours: default (blue), info (light blue), success (green), warning (orange), danger (red)

Bootstrap 3

       60% Complete
       60%

The following options are offered by Bootstrap 3:

  • Striped
  • Striped + Animated
  • Stacked (multiple bars forming a single)
  • Colours: default (blue), info (light blue), success (green), warning (orange), danger (red)

Zurb foundation

   

The following options are offered by Zurb foundation:

  • Width
  • Colours: default (blue), secondary (grey), success (green), alert (red)
  • Corner style: default (square), radius (slight rounding), round

Search

  • Text input + button.
  • Optional collapsible region with more content.

Timer

Tree

User badge

User content

Think of this like the forum post. We need a common structure in which to display content entered by the user along with information on the user. The users name, picture, date perhaps, title, content, footer (attachments, badges, what ever). It could be applied to things like forum posts, calendar events etc.

At present we have no abstraction for this.

Existing renderables and what they will become

Existing renderable Description Future renderable Convenience method (if different)
action_menu UI component for a drop down edit menu menu
action_menu_link UI component for a menu item in an action menu action
action_menu_filler UI component for a filler menu item in an action menu action
action_menu_link_primary UI component for a primary menu item in an action menu action
action_menu_link_secondary UI component for a secondary menu item in an action menu action
action_link Link with alt text, and an icon action
single_button A form with a single button button (action with post method)
confirm A form with a message and cancel/confirm buttons confirmation
single_select A form with a single drop down list that submits on change
url_select A navigation element consisting of a single drop down list of urls that navigates on change
doc_link A link to the Moodle docs
pix_icon A small icon icon
emoticon_icon A small emoticon
heading_with_help A page heading with a link to help docs heading
help_icon A help icon that opens a help popup when clicked icon_help
help_icon_scale A help icon that opens a help popup when clicked
user_picture A user profile picture which links to their profile
container A block level element used to surround something. Can have a class to allow specific targeting with CSS.
error_text An error to show to the user.
notification A message for the user
continue_button A message and a button to continue to the next page
paging_bar A list of next previous and specific page links
skip_link_to A link to a section on the page
skip_link_target A target for a matching skip_link_to call
heading A page heading heading
box A page section with a border
rarrow A right arrow
larrow A left arrow
tabtree A list of tabs menu
tabobject A single tab panel action

See also