first commit

This commit is contained in:
CHIEFSOFT\ameye
2024-09-30 18:11:26 -04:00
commit e592ca6823
27270 changed files with 5002257 additions and 0 deletions
@@ -0,0 +1,6 @@
---
title: "Moodle"
date: 2017-10-17T15:26:15Z
draft: false
weight: 1
---
@@ -0,0 +1,6 @@
---
title: "Accessibility"
date: 2020-02-03T15:26:15Z
draft: false
weight: 40
---
@@ -0,0 +1,63 @@
---
layout: docs
title: "Colour contrast"
description: "Colour contrast for Moodle UI components"
date: 2021-03-30T09:40:32+01:00
draft: false
tags:
- 3.9
---
## Accessibile colours
In WCAG 2, contrast is a measure of the difference in perceived "luminance" or brightness between two colors (the phrase "color contrast" is never used). This brightness difference is expressed as a ratio ranging from 1:1 (e.g. white on white) to 21:1 (e.g., black on a white).
## Common colour contrast issues
Most contrast issue, where the ratio is below 4.5:1 in Moodle are found on pages that using a background colour with text on top. For example a striped table with light text. Contrast issues should be qualified as bugs and reported on the Moodle tracker.
Moodle's colour set is designed to provide high contrast and maximum brightness. If the Moodle colours are changed using a custom theme make sure you test the contrast of pages like the enrolment table, reports and Moodle activities.
To test colour contrast you can use the inbuild functionality of your browser, my favourite extension is the "WCAG Colour contrast checker" for Chrome.
## Tables with links
This table with links should show no colour contrast issues.
{{< example show_markup="false" >}}
<table class="flexible table table-striped table-hover generaltable generalbox">
<thead>
<tr>
<th scope="col">#</th>
<th scope="col">Name</th>
<th scope="col">Email</th>
<th scope="col">Status</th>
</tr>
</thead>
<tbody>
<tr >
<th scope="row"><input type="checkbox" class="m-1" value="" data-action="toggle" data-toggle="master" data-togglegroup="participants-table" data-toggle-selectall="Select all" data-toggle-deselectall="Deselect all"></th>
<td><a href="#">Bas Brands</a></td>
<td>bas@example.com</td>
<td>
</td>
</tr>
<tr>
<th scope="row"><input type="checkbox" class="m-1" value="" data-action="toggle" data-toggle="master" data-togglegroup="participants-table" data-toggle-selectall="Select all" data-toggle-deselectall="Deselect all"></th>
<td><a href="#">Chris Cross</a></td>
<td>chris@example.com</td>
<td>
Active
</td>
</tr>
<tr >
<th scope="row"><input type="checkbox" class="m-1" value="" data-action="toggle" data-toggle="master" data-togglegroup="participants-table" data-toggle-selectall="Select all" data-toggle-deselectall="Deselect all"></th>
<td>
<a class="linktest-1" href="#">Irene Ipsum</a><br>
</td>
<td>irene@example.com</td>
<td>@blab</td>
</tr>
</tbody>
</table>
{{< /example >}}
@@ -0,0 +1,71 @@
---
layout: docs
title: "Keyboard access"
description: "Guidelines for create keyboard accessible User interfaces"
date: 2020-02-04T09:40:32+01:00
draft: false
tags:
- MDL-64494
- MDL-67874
- 3.9
---
## Keyboard navigation
Keyboard accessibility is one of the most important aspects of web accessibility. Many users with motor disabilities rely on a keyboard. Blind users also typically use a keyboard for navigation. Some people have tremors which don't allow for fine muscle control. Others have little or no use of their hands. Some people simply do not have hands, whether due to a birth defect, an accident, or amputation. In addition to traditional keyboards, some users may use modified keyboards or other hardware that mimics the functionality of a keyboard. For more info visit the [Keyboard Accessibility](https://webaim.org/techniques/keyboard/) page on WebAIM.
## Moodle focus outline
A keyboard user typically uses the Tab key to navigate through interactive elements on a web page—links, buttons, fields for inputting text, etc. When an item has keyboard "focus", it can be activated or manipulated with the keyboard. A sighted keyboard user must be provided with a visual indicator of the element that currently has keyboard focus.
The focus outline contrast must meet the WCAG colour contrast guidelines, to ensure focus visibility of buttons the standard Bootstrap button focus colours are used. For links the focus colour was changed in [MDL-67874](https://tracker.moodle.org/browse/MDL-67874)
## Link focus colours
The focus outlines colours in Moodle have been made more accessible in [MDL-67874](https://tracker.moodle.org/browse/MDL-67874). Typically your OS or browser has default values for the focus outline colours. In some cases the colour contrast of these outlines is not enough so the outline colours for links has changed to a darker shade.
## Example focus outlines
{{< example show_markup="false">}}
<div id="focusexamples">
<p> Normal buttons</p>
<div>
<span class="mr-2"><button class="btn btn-primary">Primary</button></span>
<span class="mr-2"><button class="btn btn-secondary">Secondary</button></span>
<span class="mr-2"><button class="btn btn-danger">Danger</button></span>
<span class="mr-2"><button class="btn btn-outline-secondary">Outline</button></span>
<span class=""><a href="#" class="aalink">clickable link</a></span>
</div>
<p class="mt-4"> keyboard focus</p>
<div>
<span class="mr-2"><button class="focusloop btn btn-primary">Primary</button></span>
<span class="mr-2"><button class="focusloop btn btn-secondary">Secondary</button></span>
<span class="mr-2"><button class="focusloop btn btn-danger">Danger</button></span>
<span class="mr-2"><button class="focusloop btn btn-outline-secondary">Outline</button></span>
<span class=""><a href="#" class="focusloop aalink">clickable link</a></span>
</div>
<button id="showfocus" class="btn btn-success btn-large mt-5" type="button">Show focus</button>
</div>
{{#js}}
var exampleContainer = document.querySelector('#focusexamples');
document.getElementById("showfocus").addEventListener('click', function(){
var elements = exampleContainer.querySelectorAll('.focusloop');
elements.forEach(function(item) {
item.focus();
item.classList.add('focus');
});
});
exampleContainer.querySelectorAll('.aalink').forEach(function (link) {
window.console.log(link);
link.addEventListener('click', function (e) {
e.preventDefault();
});
});
{{/js}}
{{< /example >}}
## Tab focus order.
The focus order when navigating a Moodle page needs to be logical.
An example of logical focus order would be starting at the main menu before then following through to the main content and finally the footer. To achieve this the navdrawer menu has been relocate in the DOM to be positioned right after the navdrawer in [MDL-67863](https://tracker.moodle.org/browse/MDL-67863).
Testing with a keyboard is essential when evaluating the accessibility of your compoment, You should never be able to tab to hidden items and there should always be a visual que to your current location in the page.
@@ -0,0 +1,70 @@
---
layout: docs
title: "Links"
description: "Designing links that lead to a change in context"
date: 2021-10-03T20:00:00+08:00
draft: false
---
## Links that open in a new window
Links that open in a new window or tab should indicate that they open in a new window or tab. This is especially helpful for screen reader users to let them know that clicking on the link will open a new window or tab. This helps eliminate confusion caused by changes in context such as opening a web page in a new window or tab.
There are several techniques that we can use when creating links that open in a new window.
### Using an image icon with alt text to indicate that the link opens in a new window
{{< example >}}
<a href="https://moodle.org" target="_blank">
Moodle.org <i class="fa fa-external-link" role="img" aria-label="Opens in new window" title="Opens in new window"></i>
</a>
{{< /example >}}
The core/userfeedback_footer_link is also good example for this one.
{{< mustache template="core/userfeedback_footer_link" >}}
{{< /mustache >}}
### Text that indicates that the link opens in a new window
This may be the most straightforward way of indicating that links open in a new window. The potential downside of this approach is that it can be quite distracting, especially when the page has a lot of links that open in a new window.
{{< example >}}
<a href="https://moodle.org" target="_blank">
Moodle.org (Opens in new window)
</a>
{{< /example >}}
## Links to a file
A link to a file such as a PDF file or Word document will usually open the relevant application associated to the file type and will cause a change in context. It would be helpful to let users know when a link will open a file.
### File type indicated in the link text
{{< example >}}
<a href="https://www.w3.org/WAI/WCAG20/versions/guidelines/wcag20-guidelines-20081211-a4.pdf">
PDF version of the Web Content Accessibility Guidelines (WCAG) 2.0
</a>
{{< /example >}}
### File type indicated via an icon/image's alt text
{{< example >}}
<a href="https://www.w3.org/WAI/WCAG20/versions/guidelines/wcag20-guidelines-20081211-a4.pdf">
Web Content Accessibility Guidelines (WCAG) 2.0 <i class="fa fa-file-pdf-o" role="img" aria-label="PDF document" title="PDF document"></i>
</a>
{{< /example >}}
## Links that lead to an external site
Similar to links that open in a new window, links that redirect to an external site may also have an indication that they lead to an external site to let users know that clicking on the link will take them away from Moodle.
The example link below opens in the same browser window and lets the user know that they will be redirected to Moodle.org, which is an external site.
{{< example >}}
<a href="https://moodle.org">
Moodle.org <i class="fa fa-external-link" role="img" aria-label="Link leads to external site" title="Link leads to external site"></i>
</a>
{{< /example >}}
## More information
* [Understanding Success Criterion 3.2.5](https://www.w3.org/TR/2016/NOTE-UNDERSTANDING-WCAG20-20161007/consistent-behavior-no-extreme-changes-context.html)
* [Opening new windows and tabs from a link only when necessary](https://www.w3.org/TR/WCAG20-TECHS/G200.html)
@@ -0,0 +1,6 @@
---
title: "Moodle Components"
date: 2020-02-03T15:26:15Z
draft: false
weight: 20
---
@@ -0,0 +1,212 @@
---
layout: docs
title: "Action menus"
description: "A reusable action menu component"
date: 2023-07-27T10:10:00+08:00
draft: false
tags:
- MDL-78665
- "4.3"
---
## How it works
Moodle action menus are a reusable component that can display a list of actions in a dropdown menu. They are used in many places in Moodle, including the user menu, the course administration menu, and the activity administration menu.
## Source files
- `lib/outputcomponents.php`: contains the main `action_menu`, `action_menu_link` and `pix_icon`.
- `lib/classes/output/local/action_menu/subpanel.php`: contains the `subpanel` menu item class.
- `lib/templates/action_menu.mustache`: contains the main template for the action menu.
- `lib/templates/action_menu_*`: location for the legacy auxliar mustache files.
- `lib/templates/local/action_menu/*`: location for any new auxiliar mustache files.
## Examples
<!-- markdownlint-disable-next-line MD033 -->
<iframe src="../../../../examples/actionmenu.php" style="overflow:hidden;height:400px;width:100%;border:0" title="Moodle action menus"></iframe>
## Usage
### Rendering an action menu
The component output classes can render an action menu entirely in PHP. The steps to do it are:
1. Create an action menu instance (with or without items)
2. (optional) Setup the action menu trigger
3. (optional) Add items to the menu (if they are not added on creation)
4. Render the menu.
The following code is a basic example of an action menu:
{{< php >}}
/** @var core_renderer $output*/
$output = $PAGE->get_renderer('core');
$menu = new action_menu();
// Add items.
$menu->add(new action_menu_link(
new moodle_url($PAGE->url, ['foo' => 'bar']),
new pix_icon('t/emptystar', ''),
'Action link example',
false
));
echo $output->render($menu);
{{< / php >}}
And this is the same example but passing the items in the creation:
{{< php >}}
/** @var core_renderer $output*/
$output = $PAGE->get_renderer('core');
$menu = new action_menu([
new action_menu_link(
new moodle_url($PAGE->url, ['foo' => 'bar']),
new pix_icon('t/emptystar', ''),
'Action link example',
false
),
]);
echo $output->render($menu);
{{< / php >}}
### Setup the menu trigger
By default, the action menu trigger is a cog icon. However, the class has methods to convert it to a kebab menu or even display any arbitrary content.
Example of a kebab menu:
{{< php >}}
/** @var core_renderer $output*/
$output = $PAGE->get_renderer('core');
$menu = new action_menu();
$menu->set_kebab_trigger(get_string('edit'), $output);
$menu->set_additional_classes('fields-actions');
{{< / php >}}
Example of a custom trigger:
{{< php >}}
/** @var core_renderer $output*/
$output = $PAGE->get_renderer('core');
$menu = new action_menu();
$menu->set_menu_trigger(get_string('edit'));
{{< / php >}}
### Add items
Items can be added as an array on creation or using the `add` method. Depending on the param passed to `add` the item can be displayed in two different locations:
Primary items: are displayed next to the trigger button as direct actions.
Secondary items: are displayed inside the action menu dropdown.
The item location must be configured before adding the element. The following example shows different ways to add primary and secondary menu items.
{{< php >}}
// Primary items examples.
$menu->add(new action_menu_link(
new moodle_url($PAGE->url),
new pix_icon('t/emptystar', ''),
'Action link example',
true
));
$menu->add(new action_menu_link_primary(
$PAGE->url,
new pix_icon('t/emptystar', ''),
'Action link example',
));
// Secondary items examples.
$menu->add(new action_menu_link(
new moodle_url($PAGE->url),
new pix_icon('t/emptystar', ''),
'Action link example',
false
));
$menu->add(new action_menu_link_secondary(
$PAGE->url,
new pix_icon('t/user', ''),
'Action link example',
));
{{< / php >}}
## Types of items
The `add` method accepts several item types.
### `action_menu_link`
The `action_menu_link` class is the generic class for link items. It has several construct params:
- `moodle_url $url`: the link URL.
- `pix_icon $icon`: an optional pix_icon. If none passed, the item will show the trigger icon or none if it is a kebab menu.
- `string $text`: the text to display.
- `bool $primary`: if the item is primary or secondary. By default, all items are primary.
- `array $attributes`: an optional array of HTML attributes.
Two convenience classes extend `action_menu_link`:
- `action_menu_link_primary`: will be added as a primary item.
- `action_menu_link_secondary`: will be added as a secondary item.
### `pix_icon`
The action menu can render `pix_icon` as primary actions. The `pix_icon` is a standard output class for generating icons in Moodle.
Construct params:
- `String $pix`: the internal icon location. For example, "t/user".
- `String $alt`: an optional alternative text
- `String $component`: the pix icon component. By default, only core icons from the `pix` folder will be used
- `Array $attributes`: optional HTML attributes.
### `core\output\local\action_menu\subpanel`
The `core\output\local\action_menu` allow the `action_menu` to add items that display subpanels when hovered or clicked.
Construct params:
- `string $text`: text to display in the menu item
- `renderable $subpanel`: the output to render inside the subpanel. This param should be renderable using the standard `output::render` method.
- `array $attributes` optional HTML attributes
The following example creates a subpanel using a renderable choicelist instance:
{{< php >}}
/** @var core_renderer $output*/
$output = $PAGE->get_renderer('core');
// A choice list is a renderable class to outpout a user choice.
$choice = new core\output\choicelist('Choice example');
$choice->add_option("statusa", "Status A", [
'url' => $PAGE->url,
'description' => 'Status A description',
'icon' => new pix_icon('t/user', '', ''),
]);
$choice->add_option("statusb", "Status B", [
'url' => $PAGE->url,
'description' => 'Status B description',
'icon' => new pix_icon('t/groupv', '', ''),
]);
$choice->set_selected_value('statusb');
$menu = new action_menu();
// Add subpanel item.
$menu->add(new core\output\local\action_menu\subpanel(
'Subpanel example',
$choice
));
echo $output->render($menu);
{{< / php >}}
### HTML string
If a plain string is added to an action_menu, the action_menu::add method will be printed as it is inside the dropdown menu (as a secondary item).
@@ -0,0 +1,213 @@
---
layout: docs
title: "Activity icons"
description: "Activity icons are used to quickly identify the activity types"
draft: false
weight: 5
toc: true
tags:
- Available
- '4.0'
- Updated
- '4.4'
---
## Activity icon types
Moodle activity icons are single black SVG icons that are stored in `mod/PLUGINNAME/pix/monologo.svg`.
### Minimal activity icons
When rendered in a page with limited space the icons will be shown in their original design, for example on the course gradebook where activity show in the grade table header.
> NOTE: The icon is using the ```.icon``` CSS class which limits the maximum width and height. It's recommended to define width and height into the SVG.
{{< example >}}
<div class="d-flex mb-3">
<div class="d-flex border align-items-center p-1">
{{< image "quiz/monologo.svg" "Quiz icon" "icon">}} Multiple choice quiz 1
</div>
</div>
{{< /example >}}
### Coloured activity icons
In places like the course page and the activity chooser icons have a more prominent role and they should be rendered outlined colored against a transparent background.
The CSS classes for these icons are ```activityiconcontainer``` wrapper class with the added activity name. And the ```activityicon``` class for the image. See the template ```course/format/templates/local/content/cm/title.mustache``` for more info.
<div class="media mb-3">
<div class="activityiconcontainer assessment mr-3">
{{< image "quiz/monologo.svg" "Quiz icon" "activityicon">}} </div>
<div class="media-body align-self-center">
<div class="text-uppercase small">quiz</div>
<div class="activityname"><a href="#">Multiple choice quiz 1</a></div>
</div>
</div>
### Activity purposes
In the HTML for the example above you might notice the ```assessment``` css class after ```.activityiconcontainer```. This class is the result of assigning a *purpose* to the quiz activity in ```/mod/quiz/lib.php```.
{{< php >}}
function quiz_supports($feature) {
switch($feature) {
..
case FEATURE_PLAGIARISM: return true;
case FEATURE_MOD_PURPOSE: return MOD_PURPOSE_ASSESSMENT;
..
}
}
{{< /php >}}
Since Moodle 4.4, the available activity purposes are:
* Administration (MOD_PURPOSE_ADMINISTRATION)
* Assessment (MOD_PURPOSE_ASSESSMENT)
* Collaboration (MOD_PURPOSE_COLLABORATION)
* Communication (MOD_PURPOSE_COMMUNICATION)
* Interactive content (MOD_PURPOSE_INTERACTIVECONTENT)
* Resource (MOD_PURPOSE_CONTENT)
* Other (MOD_PURPOSE_OTHER)
> NOTE: On Moodle 4.3 downwards, MOD_PURPOSE_INTERFACE was also available, but it has been deprecated, so it's not recommended to use it.
### Purpose colours
The activity icon colours can be customised using the theme Boost 'Raw initial SCSS' feature. Simply copy any of these scss variables that you want to customize, change the colour value, generate the filter using, for instance https://codepen.io/sosuke/pen/Pjoqqp and done! There is no background colour or filter for the 'Other' or the 'Interface' purposes.
{{< highlight scss >}}
$activity-icon-administration-bg: #da58ef !default;
$activity-icon-assessment-bg: #f90086 !default;
$activity-icon-collaboration-bg: #5b40ff !default;
$activity-icon-communication-bg: #eb6200 !default;
$activity-icon-content-bg: #0099ad !default;
$activity-icon-interactivecontent-bg: #8d3d1b !default;
$activity-icon-administration-filter:
invert(45%) sepia(46%) saturate(3819%) hue-rotate(260deg) brightness(101%) contrast(87%) !default;
$activity-icon-assessment-filter:
invert(36%) sepia(98%) saturate(6969%) hue-rotate(315deg) brightness(90%) contrast(119%) !default;
$activity-icon-collaboration-filter:
invert(25%) sepia(54%) saturate(6226%) hue-rotate(245deg) brightness(100%) contrast(102%) !default;
$activity-icon-communication-filter:
invert(48%) sepia(74%) saturate(4887%) hue-rotate(11deg) brightness(102%) contrast(101%) !default;
$activity-icon-content-filter:
invert(49%) sepia(52%) saturate(4675%) hue-rotate(156deg) brightness(89%) contrast(102%) !default;
$activity-icon-interactivecontent-filter:
invert(25%) sepia(63%) saturate(1152%) hue-rotate(344deg) brightness(94%) contrast(91%) !default;
{{</ highlight >}}
### Custom activity icons
Some activities allow icons to be customised. This can be done by implementing callback `XXX_get_coursemodule_info()` returning instance of object (for instance, `mod/lti/lib.php`).
{{< php >}}
$info = new cached_cm_info();
$info->iconurl = new moodle_url('https://moodle.org/theme/moodleorg/pix/moodle_logo_small.svg');
{{< /php >}}
To get this customised icon, use:
{{< php >}}
$iconurl = get_fast_modinfo($courseid)->get_cm($cmid)->get_icon_url()->out(false);
{{< /php >}}
<div class="media mb-3">
<div class="activityiconcontainer lti mr-3">
<img alt="lti icon" title="lti icon" src="https://moodle.org/theme/moodleorg/pix/moodle_logo_small.svg" class="activityicon "> </div>
<div class="media-body align-self-center">
<div class="text-uppercase small">external</div>
<div class="activityname"><a href="#">External tool module</a></div>
</div>
</div>
### Branded icons
Since Moodle 4.4, a new callback has been added to the modules. Branded icons are displayed with their original colours and they are not affected by the activity purpose colours.
{{< php >}}
/**
* Whether the activity is branded.
* This information is used, for instance, to decide if a filter should be applied to the icon or not.
*
* @return bool True if the activity is branded, false otherwise.
*/
function h5pactivity_is_branded(): bool {
return true;
}
{{< /php >}}
<div class="media mb-3">
<div class="activityiconcontainer mr-3">
{{< image "h5pactivity/monologo.svg" "H5P activity icon" "activityicon">}} </div>
<div class="media-body align-self-center">
<div class="text-uppercase small">h5pactivity</div>
<div class="activityname"><a href="#">H5P module</a></div>
</div>
</div>
## Examples
<div class="media mb-3">
<div class="activityiconcontainer administration mr-3">
{{< image "quiz/monologo.svg" "Admin icon" "activityicon">}} </div>
<div class="media-body align-self-center">
<div class="text-uppercase small">Administration</div>
<div class="activityname"><a href="#">Module name</a></div>
</div>
</div>
<div class="media mb-3">
<div class="activityiconcontainer assessment mr-3">
{{< image "quiz/monologo.svg" "Assessment icon" "activityicon">}} </div>
<div class="media-body align-self-center">
<div class="text-uppercase small">Assessment</div>
<div class="activityname"><a href="#">Module name</a></div>
</div>
</div>
<div class="media mb-3">
<div class="activityiconcontainer collaboration mr-3">
{{< image "wiki/monologo.svg" "Collaboration icon" "activityicon">}} </div>
<div class="media-body align-self-center">
<div class="text-uppercase small">Collaboration</div>
<div class="activityname"><a href="#">Module name</a></div>
</div>
</div>
<div class="media mb-3">
<div class="activityiconcontainer communication mr-3">
{{< image "choice/monologo.svg" "Communication icon" "activityicon">}} </div>
<div class="media-body align-self-center">
<div class="text-uppercase small">Communication</div>
<div class="activityname"><a href="#">Module name</a></div>
</div>
</div>
<div class="media mb-3">
<div class="activityiconcontainer interactivecontent mr-3">
{{< image "lesson/monologo.svg" "Interactive content icon" "activityicon">}} </div>
<div class="media-body align-self-center">
<div class="text-uppercase small">Interactive content</div>
<div class="activityname"><a href="#">Module name</a></div>
</div>
</div>
<div class="media mb-3">
<div class="activityiconcontainer content mr-3">
{{< image "book/monologo.svg" "Resource icon" "activityicon">}} </div>
<div class="media-body align-self-center">
<div class="text-uppercase small">Resource</div>
<div class="activityname"><a href="#">Module name</a></div>
</div>
</div>
<div class="media mb-3">
<div class="activityiconcontainer mr-3">
{{< image "lti/monologo.svg" "Other icon" "activityicon">}} </div>
<div class="media-body align-self-center">
<div class="text-uppercase small">Other</div>
<div class="activityname"><a href="#">Module name</a></div>
</div>
</div>
@@ -0,0 +1,167 @@
---
layout: docs
title: "Buttons"
description: "Button types used in Moodle"
date: 2020-01-14T16:32:24+01:00
draft: false
weight: 10
tags:
- Available
---
## How to use buttons
Button components are available as part of a Moodle form, as a single button functioning as a form submit or triggering a JavaScript action. Buttons used in Moodle are based on the [Bootstrap buttons]({{< docsref "/components/buttons" >}}).
The most used buttons types in Moodle are:
## Example
{{< example >}}
<button type="button" class="btn btn-primary">Primary Button</button>
<button type="button" class="btn btn-secondary">Secondary Button</button>
<button type="button" class="btn btn-danger">Danger Button</button>
<button type="button" class="btn btn-outline-secondary">Outline Button</button>
{{< /example >}}
### Primary buttons
{{< example show_markup="false">}}
<button type="button" class="btn btn-primary">Primary Button</button>
{{< /example >}}
For the primary/most used action on the page use a primary button.
For each for or UI component there should only be one primary button.
### Secondary buttons
{{< example show_markup="false">}}
<button type="button" class="btn btn-secondary">Primary Button</button>
{{< /example >}}
Secondary buttons are used for the the cancel options on a form or as a button that is always visible (blocks editing on)
### Danger buttons.
{{< example show_markup="false">}}
<button type="button" class="btn btn-danger">Primary Button</button>
{{< /example >}}
Use a danger button when the primary action is a potentially dangerous action, like deleting a contact in the messaging interface.
### Outline buttons
{{< example show_markup="false">}}
<button type="button" class="btn btn-outline-secondary">Primary Button</button>
{{< /example >}}
Outline buttons are used for buttons that controll part of the user interface, like filters on a table or the display type on the user dashboard. Outline buttons look more subtle than secondary buttons and do not distract the user from the main user interface too much.
## Adding buttons to a page
### Using the single_select renderer
The ```single_button()``` renderer allows you to quickly add a button with an action to a page without having to write a template for the page. Single select buttons are added as miniature forms that can pass custom form data.
{{< php >}}
$url = new moodle_url("$CFG->wwwroot/my/index.php", $params);
$button = $OUTPUT->single_button($url, $editstring);
$PAGE->set_button($resetbutton . $button);
{{< / php >}}
<iframe src="../../../../examples/singlebuttons.php" style="overflow:hidden;height:50px;width:100%;border:0" title="Single button examples"></iframe>
### Button links
Links can be style to look like buttons, the action for this button is to simply navigate to some other page
{{< example >}}
<a href="#next" class="btn btn-secondary">Next Page</a>
{{< /example >}}
### Action buttons
Action buttons have a data-action and are usually linked to a JavaScript eventlistener that will do something on button click.
{{< example >}}
<button data-action="show-fun-thing" class="btn btn-secondary">Click me</button>
{{< /example >}}
### UX tips
Primary buttons have a higher visual weight and attracts most attention it should be used for the default action on a page.
Use primary buttons for the positive action on the page, for example "Save" or "Submit" when working on an assignment
{{< example >}}
<div class="row">
<div class="col-5">
<div class="card mb-2">
<div class="card-body">
<strong>Save Changes?</strong>
<div class="d-flex">
<button type="button" class="btn btn-secondary mr-1">Cancel</button>
<button type="button" class="btn btn-primary mr-1">Save</button>
</div>
</div>
</div>
</div>
<div class="col-5">
<div class="card mb-2">
<div class="card-body">
<strong>Delete profile</strong>
<div class="d-flex">
<button type="button" class="btn btn-primary mr-1">Cancel</button>
<button type="button" class="btn btn-secondary">Delete</button>
</div>
</div>
</div>
</div>
</div>
{{< /example >}}
In case of more dangerous actions, like deleting something the having stiling the Cancel button as the primary button could be a good choice
Bootstrap classes are used to style Buttons, the most used styles are:
{{< example >}}
<button type="button" class="btn btn-primary">Primary buttons</button>
<button type="button" class="btn btn-secondary">Secondary buttons</button>
{{< /example >}}
### Button text
The meaning of buttons must be very clear.
{{< example show_markup="false">}}
<div class="row">
<div class="col-5">
<div class="card mb-2">
<div class="card-body">
<strong>Save Changes?</strong>
<p>Would you like to not save your changes before exiting?</p>
<div class="d-flex">
<button type="button" class="btn btn-primary mr-1">Yes</button>
<button type="button" class="btn btn-secondary">No</button>
</div>
</div>
</div>
<div class="alert alert-warning">Avoid generic 'OK' or 'Yes', avoid confusing phrases</div>
</div>
<div class="col-5">
<div class="card mb-2">
<div class="card-body">
<strong>Save Changes</strong>
<p>Would you like to save your changes before exiting?</p>
<div class="d-flex">
<button type="button" class="btn btn-primary mr-1">Save</button>
<button type="button" class="btn btn-secondary">Discard</button>
</div>
</div>
</div>
<div class="alert alert-success">Avoid generic 'OK' or 'Yes', avoid confusing phrases</div>
</div>
</div>
{{< /example >}}
@@ -0,0 +1,151 @@
---
layout: docs
title: "Course cards"
description: "Course cards are easy to access clickable components used in collections to navigate to the course home page."
date: 2020-01-14T16:32:24+01:00
draft: false
weight: 20
toc: true
tags:
- Available
---
## How to use course cards
Course cards are rendered using a shared template found in `course/templates/coursecard.mustache`. They are loaded throught JavaScript or PHP on pages like the user dashboard.
Course cards should always contain an image, if no image is provided by the backend a placeholder image is used. The card image and title should be clickable and should always link you to a course page.
Course cards should always show
* Course image
* Course full name
* Course category
* If a course is favourited
## Example
{{< mustache template="core_course/view-cards">}}
{
"courses": [
{
"viewurl": "https://moodlesite/course/view.php?id=2",
"courseimage": "https://placekitten.com/300/500",
"fullname": "Mathematics Year One",
"isfavourite": true,
"coursecategory": "Category 1",
"showcoursecategory": true,
"visible": true
}
]
}
{{< /mustache >}}
## Sources
A deck of course cards:
`core_course/view-cards.mustache`
A single card:
`course/templates/coursecard.mustache`
## Exporter
The data structure for course cards are provided by the exporter class:
`course/classes/external/course_summary_exporter.php`
## Usage
Course cards can be used in any place that lists courses, it helps users quickly scan the available content and find a course based on the remembered course image or the course name. Guidelines for using course cards are:
* Keep them simple
* Minimize the number of actions on a card
* Use images smartly
The example below show a deck of cards as used on the starred courses block
{{< mustache template="core_course/view-cards" >}}
{
"courses": [
{
"viewurl": "https://moodlesite/course/view.php?id=2",
"courseimage": "https://placekitten.com/300/500",
"fullname": "Mathematics Year One",
"isfavourite": true,
"coursecategory": "Category 1",
"showcoursecategory": true,
"visible": true
},
{
"viewurl": "https://moodlesite/course/view.php?id=3",
"courseimage": "https://placekitten.com/330/500",
"fullname": "Health and Safety",
"isfavourite": false,
"coursecategory": "Business",
"showcoursecategory": true,
"visible": true
},
{
"viewurl": "https://moodlesite/course/view.php?id=4",
"courseimage": "https://placekitten.com/360/500",
"fullname": "French Advanced",
"isfavourite": false,
"coursecategory": "Languages",
"showcoursecategory": true,
"visible": true
},
{
"viewurl": "https://moodlesite/course/view.php?id=4",
"courseimage": "https://placekitten.com/360/400",
"fullname": "French Year one",
"isfavourite": false,
"coursecategory": "Languages",
"showcoursecategory": true,
"visible": true
}
]
}
{{< /mustache >}}
## Placeholder images
Cards usually don't really look great without images. That's why we show a placeholder image when no course image is provided. Placeholder images are rendered in core using a library that generates a uniqueish svg's from idnumbers.
{{< php >}}
$OUTPUT->get_generated_image_for_id($id);
{{< /php >}}
{{< example show_markup="false">}}
<div class="card-deck">
{{< root.inline >}}
{{- $pl1 := readFile "admin/tool/componentlibrary/content/static/moodle/components/coursecards/placeholder-1.txt" -}}
{{- $pl2 := readFile "admin/tool/componentlibrary/content/static/moodle/components/coursecards/placeholder-2.txt" -}}
{{- $pl3 := readFile "admin/tool/componentlibrary/content/static/moodle/components/coursecards/placeholder-3.txt" -}}
{{- $pl4 := readFile "admin/tool/componentlibrary/content/static/moodle/components/coursecards/placeholder-4.txt" -}}
{{- $pl5 := readFile "admin/tool/componentlibrary/content/static/moodle/components/coursecards/placeholder-5.txt" -}}
{{- $pl6 := readFile "admin/tool/componentlibrary/content/static/moodle/components/coursecards/placeholder-6.txt" -}}
{{- $pl7 := readFile "admin/tool/componentlibrary/content/static/moodle/components/coursecards/placeholder-7.txt" -}}
{{- $pl8 := readFile "admin/tool/componentlibrary/content/static/moodle/components/coursecards/placeholder-8.txt" -}}
{{- $pl9 := readFile "admin/tool/componentlibrary/content/static/moodle/components/coursecards/placeholder-9.txt" -}}
<div class="card mb-2 justify-content-center align-items-center d-flex text-center" style="flex: 0 0 20%; height: 150px; background-image: url('{{- $pl1 -}}')">
</div>
<div class="card mb-2 justify-content-center align-items-center d-flex text-center" style="flex: 0 0 20%; height: 150px; background-image: url('{{- $pl2 -}}')">
</div>
<div class="card mb-2 justify-content-center align-items-center d-flex text-center" style="flex: 0 0 20%; height: 150px; background-image: url('{{- $pl3 -}}')">
</div>
<div class="card mb-2 justify-content-center align-items-center d-flex text-center" style="flex: 0 0 20%; height: 150px; background-image: url('{{- $pl4 -}}')">
</div>
<div class="card mb-2 justify-content-center align-items-center d-flex text-center" style="flex: 0 0 20%; height: 150px; background-image: url('{{- $pl5 -}}')">
</div>
<div class="card mb-2 justify-content-center align-items-center d-flex text-center" style="flex: 0 0 20%; height: 150px; background-image: url('{{- $pl6 -}}')">
</div>
<div class="card mb-2 justify-content-center align-items-center d-flex text-center" style="flex: 0 0 20%; height: 150px; background-image: url('{{- $pl7 -}}')">
</div>
<div class="card mb-2 justify-content-center align-items-center d-flex text-center" style="flex: 0 0 20%; height: 150px; background-image: url('{{- $pl8 -}}')">
</div>
<div class="card mb-2 justify-content-center align-items-center d-flex text-center" style="flex: 0 0 20%; height: 150px; background-image: url('{{- $pl9 -}}')">
</div>
{{< /root.inline >}}
</div>
{{< /example >}}
@@ -0,0 +1,134 @@
---
layout: docs
title: "HTML Modals"
description: "A reusable handled modal component"
date: 2021-12-09T14:48:00+08:00
draft: false
tags:
- MDL-71963
- MDL-72928
- "4.0"
---
## How it works
The core/utility module allows different modals to be displayed automatically when interacting with the page.
Modals are configured using a set of specific data-attributes.
## Source files
* `lib/amd/src/utility.js` ({{< jsdoc module="core/utility" >}})
* `lib/templates/modal.mustache`
## Usage
The confirmation AMD module is loaded automatically, so the only thing you need to do is to add some specific data attributes
to the target element.
To display a confirmation modal.
{{< highlight html >}}
<button type="button" class="btn btn-primary" data-modal="confirmation" data-modal-title-str='["delete", "core"]'
data-modal-content-str='["areyousure"]' data-modal-yes-button-str='["delete", "core"]'>Show confirmation modal</button>
{{< /highlight >}}
To display an alert modal.
{{< highlight html >}}
<button type="button" class="btn btn-primary" data-modal="alert" data-modal-title-str='["cookiesenabled", "core"]'
data-modal-content-str='["cookiesenabled_help_html", "core"]'>Show alert modal</button>
{{< /highlight >}}
You can also use it on PHP, you just need to set the attributes parameter to any moodle output component that takes attributes:
{{< php >}}
echo $OUTPUT->single_button('#', get_string('delete'), 'get', [
'data-modal' => 'modal',
'data-modal-title-str' => json_encode(['delete', 'core']),
'data-modal-content-str' => json_encode(['areyousure']),
'data-modal-yes-button-str' => json_encode(['delete', 'core'])
]);
{{< / php >}}
## Attributes
<table class="table">
<thead>
<tr>
<th style="width: 250px;">Data attribute</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>data-modal</td>
<td>One of either "confirmation", or "alert".</td>
</tr>
<tr>
<td>data-modal-title-str</td>
<td>The modal title language string identifier, must be provided in JSON encoded format.</td>
</tr>
<tr>
<td>data-modal-content-str</td>
<td>The modal content or content language string identifier, must be provided in JSON encoded format.</td>
</tr>
<tr>
<td>data-modal-yes-button-str</td>
<td>
The language string identifier for the "Yes" button, must be provided in JSON encoded format.
Confirmation modals only.
</td>
</tr>
<tr>
<td>data-modal-toast</td>
<td>
If set to "true" it will display a modal toast in the end.
Confirmation modals only.
</td>
</tr>
<tr>
<td>data-modal-toast-confirmation-str</td>
<td>
The confirmation toast language string identifier, must be provided in JSON encoded format.
Confirmation modals only.
</td>
</tr>
<tr>
<td>data-modal-destination</td>
<td>
An url to redirect the user to.
Confirmation modals only.
</td>
</tr>
</tbody>
</table>
## Examples
### Basic Alert modal
{{< example >}}
<button type="button" class="btn btn-primary" data-modal="alert" data-modal-title-str='["cookiesenabled", "core"]'
data-modal-content-str='["cookiesenabled_help_html", "core"]'>Show alert modal</button>
{{< /example >}}
### Basic confirmation modal
{{< example >}}
<button type="button" class="btn btn-primary" data-modal="confirmation" data-modal-title-str='["delete", "core"]'
data-modal-content-str='["areyousure"]' data-modal-yes-button-str='["delete", "core"]'>Show confirmation modal</button>
{{< /example >}}
### Confirmation modal with a toast
{{< example >}}
<button type="button" class="btn btn-primary" data-modal="confirmation" data-modal-title-str='["delete", "core"]'
data-modal-content-str='["areyousure"]' data-modal-yes-button-str='["delete", "core"]' data-modal-toast="true"
data-modal-toast-confirmation-str='["deleteblockinprogress", "block", "Online users"]'>Show confirmation modal</button>
{{< /example >}}
### Confirmation modal with redirect
{{< example >}}
<button type="button" class="btn btn-primary" data-modal="confirmation" data-modal-title-str='["delete", "core"]'
data-modal-content-str='["areyousure"]' data-modal-yes-button-str='["delete", "core"]'
data-modal-destination="http://moodle.com">Show confirmation modal</button>
{{< /example >}}
@@ -0,0 +1,379 @@
---
layout: docs
title: "Dropdowns"
description: "A reusable dropdown component"
date: 2023-06-13T10:10:00+08:00
draft: false
tags:
- MDL-78279
- "4.3"
---
## How it works
Moodle dropdowns are output components to generate elements that expand extra floating information when clicked.
Currently, the core comes with two prebuild dropdowns:
- Dropdown dialog: to display rich content inside the dropdown area.
- Dropdown status: to display a list of available statuses
## Source files
- `lib/classes/output/local/dialog.php`: to define a dropdown dialog.
- `lib/classes/output/local/dialog.php`: to define a dropdown dialog.
- `lib/classes/output/choicelist.php`: generic output class to define a user choice.
- `lib/templates/local/dropdown/dialog.mustache`
- `lib/templates/local/dropdown/status.mustache`
## Usage
### Dropdown dialog
The constructor for the dropdown dialog class only requires three parameters.
- The button content
- The dropdown content
- An array of additional definitions. However, the output public methods can override all the definition values once the instance is created. Check out the examples to learn how to use them
The following example is the most simple example of creating a dropdown:
{{< php >}}
$dialog = new core\output\local\dropdown\dialog('Open dialog button', 'Dialog content');
echo $OUTPUT->render($dialog);
{{< / php >}}
You have the option to include additional classes to the main component but also to the button itself.
{{< php >}}
$dialog = new core\output\local\dropdown\dialog(
'Open dialog',
'Dialog content',
[
'classes' => 'mb-4',
'buttonclasses' => 'btn btn-primary extraclass',
]
);
echo $OUTPUT->render($dialog);
{{< / php >}}
{{< mustache template="core/local/dropdown/dialog" >}}
{
"buttonid" : "example01",
"buttoncontent" : "Open dialog",
"dialogcontent" : "Dialog content",
"buttonclasses": "btn btn-primary extraclass"
}
{{< /mustache >}}
If a specific item is floating towards the end of the page, you might consider aligning the dropdown menu to the left rather than to the right. To achieve this, you can use the POSITION constant values to set the `dropdownposition` $definition attribute or input it into the `set_position` method.
{{< php >}}
$dialog = new core\output\local\dropdown\dialog('Open dialog', 'Dialog content');
$dialog->set_position(core\output\local\dropdown\dialog::POSITION['end']);
echo $OUTPUT->render($dialog);
{{< / php >}}
By default, the dropdown width will adapt to the content. However, for long texts, there may be better scenarios. You can use the WIDTH constant values to set the `dialogwidth` $definition attribute or input it into the `set_dialog_width` method.
{{< php >}}
// Big but fixed-width example.
$dialog = new core\output\local\dropdown\dialog('Big dialog', $content);
$dialog->set_dialog_width(core\output\local\dropdown\dialog::WIDTH['big']);
echo $OUTPUT->render($dialog);
// Small width example.
$dialog = new core\output\local\dropdown\dialog('Small dialog', $content);
$dialog->set_dialog_width(core\output\local\dropdown\dialog::WIDTH['small']);
echo $OUTPUT->render($dialog);
{{< / php >}}
{{< mustache template="core/local/dropdown/dialog" >}}
{
"buttonid" : "example02",
"buttoncontent" : "Big dialog",
"dialogcontent" : "This is a long content for a big dialog that will be displayed in a fixed-width container.",
"buttonclasses": "btn btn-primary extraclass",
"dialogclasses": "dialog-big"
}
{{< /mustache >}}
### Dropdown status
The dropdown status is a user-choice wrapper. To create it, first, you need to create an instance of `core\output\choicelist` that will be used to generate the dropdown content data.
{{< php >}}
$choice = new core\output\choicelist('Dialog content');
$choice->add_option('option1', 'Option 1');
$choice->add_option('option2', 'Option 2');
$choice->add_option('option3', 'Option 3');
$choice->set_selected_value('option2');
$dialog = new core\output\local\dropdown\status('Open dialog button', $choice);
echo $OUTPUT->render($dialog);
{{< / php >}}
{{< mustache template="core/local/dropdown/status" >}}
{
"buttonid" : "example04",
"buttoncontent" : "Open dialog button",
"dialogcontent" : "Dialog content",
"choices" : {
"hasoptions" : true,
"options" : [
{
"optionid" : "option1",
"value" : "option1",
"name" : "Option 1",
"hasicon" : false,
"first" : true,
"optionnumber" : 1,
"optionuniqid" : "option1uniqid"
},
{
"optionid" : "option2",
"value" : "option2",
"name" : "Option 2",
"hasicon" : false,
"selected" : true,
"optionnumber" : 2,
"optionuniqid" : "option2uniqid"
},
{
"optionid" : "option3",
"value" : "option3",
"name" : "Option 3",
"hasicon" : false,
"optionnumber" : 3,
"optionuniqid" : "option3uniqid"
}
]
}
}
{{< /mustache >}}
The status dropdown is an extension of the dropdown dialog, which means that all the definitions mentioned earlier can also be applied to it.
- The status dropdown is also compatible with all the `core\output\choicelist` extra features like:
- Adding additional icons and descriptions to the options
- Disable options
- Add links to options
The following example shows how to use the advanced features:
{{< php >}}
$choice = new core\output\choicelist('Dialog content');
// Option one is a link.
$choice->add_option('option1', 'Option 1', [
'url' => new moodle_url('/'),
]);
// Option two has an icon and description.
$choice->add_option('option2', 'Option 2', [
'description' => 'Option 2 description',
'icon' => new pix_icon('t/hide', 'Eye icon 2')
]);
// Option three is disabled.
$choice->add_option('option3', 'Option 3', [
'disabled' => true,
]);
$choice->set_selected_value('option2');
$dialog = new core\output\local\dropdown\status('Open dialog button', $choice);
echo $OUTPUT->render($dialog);
{{< / php >}}
#### Sync button text with selected status
The status dropdown can be configured to sync the button text with the selected status.
To do so, you need to set the `buttonsync` $definition attribute to `true`.
{{< php >}}
$choice = new core\output\choicelist();
$choice->add_option('option1', get_string('option1', YOURPLUGIN));
$choice->add_option('option2', get_string('option2', YOURPLUGIN));
$choice->set_selected_value('option2');
// Add some attribute to select through a query selector.
$dialog = new core\output\local\dropdown\status(
get_string('buttontext', YOURPLUGIN),
$choice,
[
'extras' => ['id' => 'mydropdown'],
'buttonsync' => true,
// With 'updatestatus' it will change the status when the user clicks an option
// See "Dropdown status in update mode" section for more information.
'updatestatus' => true,
]
);
echo $OUTPUT->render($dialog);
{{< / php >}}
## Javascript
### Controlling dropdowns
Both `core/local/dropdown/status` and `core/local/dropdown/status` AMD modules provide functions to:
- Open and close the dropdown.
- Change the button content.
- Get the main dropdown HTML element.
Both modules are object-oriented. To get the dropdown instance, the process is as follows:
1. Add id or data attributes to the main component to select it using a query selector.
2. Import `getDropdownDialog` from `core/local/dropdown/dialog`, or `getDropdownStatus` from `core/local/dropdown/status`, depending on whether you use a dialogue or a status dropdown.
3. Call `getDropdownDialog` or `getDropdownStatus` with the query selector to get the instance
Both classes provide the following methods:
- `setVisible(Boolean)` to open or close the dropdown.
- `isVisible()` to know if it is open or closed.
- `setButtonContent(String)` to replace the button content.
- `setButtonDisabled(Boolean)` to disable or enable the dropdown button.
- `getElement()`to get the main HTMLElement to add eventListeners.
The following example uses the module to open the dropdown when an extra button is preset:
```js
import {getDropdownDialog} from 'core/local/dropdown/';
const dialog = getDropdownDialog('[MYDROPDOWNSELECTOR]');
document.querySelector('[data-for="openDropdown"]').addEventListener('click', (event) => {
event.stopPropagation();
dialog.setVisible(true);
});
```
### Specific dropdown status methods
The `core/local/dropdown/status` provides extra controls for the status selector, such as:
- `getSelectedValue()` and `setSelectedValue(String)` to control the currently selected status.
- `isButtonSyncEnabled()` and `setButtonSyncEnabled(Boolean)` to synchronise the button text with the selected status.
- `isUpdateStatusEnabled()` and `setUpdateStatusEnabled(Boolean)` to control the auto-update status mode.
## Using dropdown status from the frontend
The dropdown status can operate in two different ways.
### Dropdown status in display only
The display-only is the default behaviour for any dropdown. In display-only mode, the component will show all the status values to the user, but it won't handle and click the event nor change the current status.
If a plugin wants to change the status value when the user clicks, it should code a custom module to:
1. Capture `click` event listeners to the choice items.
2. Send the new status to the backend (using an ad-hoc webservice).
3. If the webservice execution is ok, update the component value using the `setSelectedValue` instance method.
The following example shows how to render a display-only dropdown status in the backend:
{{< php >}}
$choice = new core\output\choicelist('Dialog content');
// Add some data attributes to the choices.
$choice->add_option(
'option1',
get_string('option1', YOURPLUGIN), [
extras' => ['data-action' => 'updateActionName']
]);
$choice->add_option(
'option2',
get_string('option2', YOURPLUGIN), [
extras' => ['data-action' => 'updateActionName']
]);
$choice->set_selected_value('option2');
// Add some attribute to select through a query selector.
$dialog = new core\output\local\dropdown\status(
get_string('buttontext', YOURPLUGIN),
$choice,
['extras' => ['id' => 'mydropdown']]
);
echo $OUTPUT->render($dialog);
{{< / php >}}
Having this PHP code, the AMD controller could be something like:
```js
import {getDropdownStatus} from 'core/local/dropdown/status';
import {sendValueToTheBackend} from 'YOURPLUGIN/example';
const status = getDropdownStatus('#mydropdown');
status.getElement().addEventListener('click', (event) => {
const option = event.target.closest("[data-action='updateActionName']");
if (!option) {
return;
}
try {
if(sendValueToTheBackend(option.dataset.value)) {
status.setSelectedValue(option.dataset.value);
}
} catch (error) {
// Do some error handling here.
}
});
```
### Dropdown status in update mode
The component will act more like an HTML radio button in update mode. It will store the current status value and will trigger `change` events when the value changes.
In this case, the plugin controller has to:
1. Capture the component element `change` event. Remember that, as in radio events, the `change` event won't bubble, so it cannot be delegated to a parent element.
2. Send the new status to the backend (using an ad-hoc webservice).
3. If the webservice execution fails, do a value rollback using the `setSelectedValue` instance method.
The following example shows how to render an update mode dropdown status in the backend:
{{< php >}}
$choice = new core\output\choicelist('Dialog content');
$choice->add_option('option1', get_string('option1', YOURPLUGIN));
$choice->add_option('option2', get_string('option2', YOURPLUGIN));
$choice->set_selected_value('option2');
// Add some attribute to select through a query selector.
$dialog = new core\output\local\dropdown\status(
get_string('buttontext', YOURPLUGIN),
$choice,
[
'extras' => ['id' => 'mydropdown'],
'updatestatus' => true,
]
);
echo $OUTPUT->render($dialog);
{{< / php >}}
Having this PHP code, the AMD controller could be something like:
```js
import {getDropdownStatus} from 'core/local/dropdown/status';
import {sendValueToTheBackend} from 'YOURPLUGIN/example';
const status = getDropdownStatus('#mydropdown');
let currentValue = status.getSelectedValue();
status.getElement().addEventListener('change', (event) => {
if (currentValue == status.getSelectedValue()) {
return;
}
try {
sendValueToTheBackend(status.getSelectedValue());
currentValue = status.getSelectedValue();
} catch (error) {
status.setSelectedValue(currentValue);
}
});
```
**Note**: the `event.target` is also the main element. You can also get the current value from `event.target.dataset.value` if you prefer.
## Examples
<!-- markdownlint-disable-next-line MD033 -->
<iframe src="../../../../examples/dropdowns.php" style="overflow:hidden;height:400px;width:100%;border:0" title="Moodle dynamic tabs"></iframe>
@@ -0,0 +1,100 @@
---
layout: docs
title: "Dynamic tabs"
date: 2021-10-02T09:40:32+01:00
draft: false
tags:
- MDL-71943
- 4.0
---
## How it works
Dynamic tabs are tabs that load content in AJAX requests. Once the user clicks on the tab heading, the page does not reload but the content of the respective tab loads in AJAX request.
## Source files
* `lib/amd/src/dynamic_tabs.js`
* `lib/amd/src/local/repository/dynamic_tabs.js`
* `lib/classes/external/dynamic_tabs_get_content.php`
* `lib/classes/output/dynamic_tabs.php`
* `lib/classes/output/dynamic_tabs/base.php`
* `lib/db/services.php`
* `lib/templates/dynamic_tabs.mustache`
## How to use dynamic tabs
First of all we need to create a tab class file for each tab that we need, extending `lib/classes/output/dynamic_tabs/base.php`.
These tab classes need to include these 4 methods in order to work:
* `export_for_template` returns the data we export to the template
* `get_tab_label` returns the tab title
* `is_available` checks the tab permission and returns true/false that will enable/disable the individual tab
* `get_template` returns the path to the tab template file
{{< php >}}
class tab1 extends base {
/**
* Export this for use in a mustache template context.
*
* @param renderer_base $output
*
* @return stdClass
*/
public function export_for_template(renderer_base $output) {
$content = (object)[];
$content->customtext = 'Tab 1 content example';
return $content;
}
/**
* The label to be displayed on the tab
*
* @return string
*/
public function get_tab_label(): string {
return 'Tab 1';
}
/**
* Check permission of the current user to access this tab
*
* @return bool
*/
public function is_available(): bool {
// Define the correct permissions here.
return true;
}
/**
* Template to use to display tab contents
*
* @return string
*/
public function get_template(): string {
return 'tool_componentlibrary/dynamictabs_tab1';
}
}
{{< / php >}}
Then we need to create the templates that each `get_template` method will call.
Finally, to add dynamic tabs to our page, we just need to call all the previously created tabs, and pass the attributes
needed in each tab.
These attributes will be stored as "data attributes" in the DOM and can be also used inside our tab classes
using `get_data` method (for example to check permissions in `is_available`).
{{< php >}}
$tabs = [
new tab1(['demotab' => 'Tab1', 'reportid' => $reportid]),
new tab2(['demotab' => 'Tab2']),
];
echo $OUTPUT->render_from_template('core/dynamic_tabs', (new dynamic_tabs($tabs))->export_for_template($OUTPUT));
{{< / php >}}
## Example
<iframe src="../../../../examples/dynamictabs.php" style="overflow:hidden;height:400px;width:100%;border:0" title="Moodle dynamic tabs"></iframe>
@@ -0,0 +1,57 @@
---
layout: docs
title: "Example"
description: "This is an example page describing the example component"
date: 2020-01-28T10:13:29+01:00
draft: true
weight: 30
---
## How it works
The EXAMPLE is used to [...] . It can be found in Moodle on pages where [...]
## Example
Show what the example looks like in Moodle, if your component includes and JavaScript backend please describe how it is initiated.
{{< example >}}
<div class="example w-25 border border-secondary p-3">
<button class="btn btn-primary btn-block" id="clickme">
Click me
<span id="waiting" class="spinner-grow-sm" role="status" aria-hidden="true"></span>
</button>
</div>
{{#js}}
require(['jquery'], function($) {
$('#clickme').on('click', function() {
$('#waiting').toggleClass('spinner-grow');
});
});
{{/js}}
{{< /example >}}
## Example explained
How can you use this example?
Are there any example pages in Moodle?
What are the different options you have for different contexts (places in Moodle)?
What colours can be used?
Can it be called from PHP and JavaScript
## JavaScript behavior
Showcase the different ways this buttons can behave:
Does it trigger any events, does it listen to events?
Does it require any core AMD modules?
Is there a webservice backend required?
## Accessibility
Descripbe the `aria-something` parts of the element. Are there any possible accessibility issues using this example?
What are the considerations for keyboard navigation?
What accessibile colors can be used?
How to test its accessibility?
@@ -0,0 +1,43 @@
---
layout: docs
title: "Footer"
description: Moodle footer HTML and required code injected in the page footer
date: 2020-03-02T16:32:24+01:00
draft: false
weight: 40
tags:
- available
- needs review
---
## How are footers implemented in Moodle?
The page footer is shown at the bottom of every page in Moodle, typically a Moodle footer contains links to:
* A link to the Moodle docs for the current page
* resetting user tours
* user login information
* a link to the Moodle homepage
When the setting ```perfdebug``` is turned on (Site Administration > Development > Debugging) additional performance info is shown in the page footer.
## Footer styling
Since footers are repeated on all pages they are styled distinctly using a dark background colour and light fonts. Links need to be underlined and use light fonts too.
The page footer should always stick to the bottom of the page and never overlap any page content.
### Minimal footer requirements
The page footer is required to inject the page JavaScript, show the reset user tours link and show user info and (if avaliable) the contents of the user configure theme custom menu.
{{< example >}}
<footer id="page-footer" class="py-3 bg-dark text-light">
<div class="container">
<p class="helplink"><a href="#">Moodle docs for this page</a></p>
You are logged in as <a href="#">Test User</a> (<a href="#">logout</a>)
<a href="#">Home</a>
<div class="tool_usertours-resettourcontainer"></div>
</div>
</footer>
{{< /example >}}
@@ -0,0 +1,29 @@
---
layout: docs
title: "Form elements"
description: "Custom form elements for Moodle"
date: 2020-01-14T16:32:24+01:00
draft: false
weight: 30
tags:
- In development
---
## How to use moodle forms
Forms are constructed using lib/formslib.php. Using the addElement methods in php a set of different form element types can be added to a form. For more info visit the [Moodledocs](https://moodledev.io/docs/apis/subsystems/form) page for forms
{{< php >}}
$mform->addElement('button', 'intro', get_string("buttonlabel"));
{{< / php >}}
Form elements are styled using Moodle templates which are rendered through PHP. Themes can override these templates.
Form elements are styled using the .form-control class, see the [Bootstrap](/bootstrap-4.3/forms/input-group/) docs for more info.
## Example form elements
The example form below is showing an iframe with an actual Moodle form. Use the toggle options to display the different states for the form.
<iframe src="../../../../examples/formfields.php" style="overflow:hidden;height:4000px;width:100%;border:0" title="Moodle form fields"></iframe>
@@ -0,0 +1,61 @@
---
layout: docs
title: "Icons"
description: "Moodle icons are rendered with Font Awesome or as small images"
weight: 40
date: 2020-02-04T09:40:32+01:00
draft: false
tags:
- available
---
## Description
Most Moodle icons are rendered using the 6.5.1 versions of [Fontawesome](https://fontawesome.com/v6/search). Iconnames are mapped from the Moodle icon name to the Font Awesome icon names in `/lib/classes/output/icon_system_fontawesome.php`
If needed a theme can override this map and provide its own mapping.
## Rendering icons in Mustache Templates
Icons can be rendered in moodle templates using this notation:
```{{#pix}} i/edit, core {{/pix}}```
## Rendering icons in Php
Use the pix_icon method to retreive the HTML for an icon.
{{< php >}}
$icon = $OUTPUT->pix_icon('i/edit', 'Edit me', 'moodle');
{{< / php >}}
Options:
## Stacking Font Awesome icons
{{< example >}}
<span class="fa-stack fa-lg">
<i class="fa-solid fa-comment fa-stack-2x"></i>
<i class="fa-solid fa-thumbs-up fa-stack-1x fa-inverse"></i>
</span>
<span class="fa-stack fa-2x">
<i class="fa-solid fa-camera fa-stack-1x"></i>
<i class="fa-solid fa-ban fa-stack-2x" style="color:Tomato"></i>
</span>
<span class="fa-stack fa-2x">
<i class="fa-solid fa-square fa-stack-2x"></i>
<i class="fa-solid fa-terminal fa-stack-1x fa-inverse"></i>
</span>
<span class="fa-stack fa-4x">
<i class="fa-solid fa-square fa-stack-2x"></i>
<i class="fa-solid fa-terminal fa-stack-1x fa-inverse"></i>
</span>
{{< /example >}}
## List of mapped Font Awesome icons
The top title of each cards displays the name of the icon. The icon shown left is the Font Awesome icons. The icon shown on the right is the old image base icon.
{{< moodleicons >}}
@@ -0,0 +1,110 @@
---
layout: docs
title: "Notifications"
description: "Moodle notifications"
date: 2020-02-04T09:40:32+01:00
draft: false
weight: 50
tags:
- Available
- Needs review
---
## How it works
Notifications are coupled with actions and provide instant feedback to the action results. Moodle notifications are shown right above the actionable content or overlaying the user interface for JavaScript related actions.
## Example
{{< example show_markup="false">}}
<div class="alert alert-info alert-block fade in foo bar" role="alert" data-aria-autofocus="true" id="yui_3_17_2_1_1599746674354_24">
<button type="button" class="close" data-dismiss="alert">×</button>
Hello
</div>
{{< /example >}}
## Source files
* `lib/amd/src/notification.js`
* `lib/templates/notification_info.mustache`
* `lib/templates/notification_success.mustache`
* `lib/templates/notification_warning.mustache`
* `lib/templates/notification_error.mustache`
## Core renderer
Notifications can be added in PHP using the core renderer notification method
{{< php >}}
$OUTPUT->notification('message', 'info');
{{< / php >}}
## Notification templates
{{< mustache template="core/notification_info" >}}
{{< /mustache >}}
{{< mustache template="core/notification_success" >}}
{
"message": "Your pants are on awesome!",
"closebutton": 1,
"announce": 1,
"extraclasses": "foo bar"
}
{{< /mustache >}}
{{< mustache template="core/notification_warning" >}}
{
"message": "Your pants are on down!",
"closebutton": 1,
"announce": 1,
"extraclasses": "foo bar"
}
{{< /mustache >}}
{{< mustache template="core/notification_error" >}}
{
"message": "Your pants are on fire!",
"closebutton": 1,
"announce": 1,
"extraclasses": "foo bar"
}
{{< /mustache >}}
## JavaScript Notifications
{{< example >}}
<button class="btn btn-secondary" data-action="shownotification">Show JS Notification</button>
{{#js}}
require(
[
'core/notification'
],
function(
Notification
) {
document.querySelector('[data-action="shownotification"]').addEventListener('click', function() {
Notification.alert('Notification message', 'Extra content for notification message');
});
});
{{/js}}
{{< /example >}}
## Toast Notifications
{{< example >}}
<button class="btn btn-secondary" data-action="showtoastnotification">Show Toast Notification</button>
{{#js}}
require(
[
'core/toast'
],
function(
Toast
) {
document.querySelector('[data-action="showtoastnotification"]').addEventListener('click', function() {
Toast.add('Toast message');
});
});
{{/js}}
{{< /example >}}
@@ -0,0 +1,124 @@
---
layout: docs
title: "Search input"
description: "find items in a collection of data"
date: 2020-08-26T16:32:24+01:00
draft: false
weight: 60
tags:
- Introduced in Moodle 3.10
- MDL-69454
---
## How it works
Single searches allow the user the quickly search a collection of data. A search is input in the search field and the results are shown immediately (using JS) or after the search has been posted to Moodle.
Searches are used in the page navbar, blocks, module pages, settings, the contentbank etc.
## Example
<div class="small">
Default search input.
</div>
{{< mustache template="core/search_input" >}}
{
"action": "https://moodle.local/admin/search.php",
"extraclasses": "my-2",
"inputname": "search",
"inform": false,
"searchstring": "Search something",
"hiddenfields": [
{
"name": "context",
"value": "11"
}
]
}
{{< /mustache >}}
<div class="mt-3 small">
Emphasized search input using .btn-primary
</div>
{{< mustache template="core/search_input" >}}
{
"action": "https://moodle.local/admin/search.php",
"extraclasses": "my-2",
"uniqid": "Unique string",
"inputname": "search",
"inform": false,
"btnclass": "btn-primary",
"searchstring": "Search something",
"hiddenfields": [
{
"name": "context",
"value": "11"
}
]
}
{{< /mustache >}}
**Use**
Use a default search input when searching is not expected to be the primary action on this page. Use the emphasized search when it is the default action AND the only search input found on the page. (except the navbar search).
**Variables**
* action: used to specify the form (get) action
* extraclasses: add these css classes to the search wrapper
* uniqid: Unique string
* inputname: form field name for search input
* inform: search is part of a larger form
* query: current search value from user input
* btnclass: use a btn class for the btn design, (btn-secondary, btn-primary)
* searchstring: string describing current search for placeholder and aria-label
* hiddenfields: array with name valua pairs for extra hidden form fields
<div class="my-5"></div>
### Auto search input with clear option
{{< mustache template="core/search_input_auto" >}}
{
"placeholder": "Search settings",
"uniqid": "45"
}
{{< /mustache >}}
**Use**
This search option is used when the search imput immediately triggers updating data displayed below the search, for example: a table of usernames. It includes a clear button that clears the input on typeing.
**Variables**
* uniqid: Unique string
* placeholder: search placeholder
<div class="my-5"></div>
### Navbar search form
{{< mustache template="core/search_input_navbar" >}}
{
"action": "https://moodle.local/admin/search.php",
"inputname": "search",
"searchstring": "Search",
"hiddenfields": [
{
"name": "cmid",
"value": "11"
}
]
}
{{< /mustache >}}
**Use**
This search should be used once on the page and triggers a global site search. It uses a minimal amount of space to prevent breakage on mobile use.
**Features**
* click search button to start typing
* click close button to hide search
* click enter after input to post the form
* uses very little space
* overlaps navbar when viewed on mobile.
@@ -0,0 +1,40 @@
---
layout: docs
title: "Show more"
date: 2023-06-12T00:00:00+01:00
draft: false
weight: 70
tags:
- MDL-78204
- 4.3
---
## How to use
The show more component is used to show and hide content. It is useful for showing a preview of content and then allowing the user to expand it to see more.
The parameters for the template context are:
* collapsedcontent: The content to show when collapsed.
* expandedcontent: The content to show when expanded.
* extraclasses: Any extra classes added to the showmore outer container.
* buttonextraclasses: Any extra classes added to the button.
* collapsedextraclasses: Any extra classes added to the collapsed content container.
* expandedextraclasses: Any extra classes added to the expanded content container.
## Example
{{< mustache template="core/showmore" >}}
{
"collapsedcontent": "Hello...",
"expandedcontent": "Hello<br>Is it me you're looking for? I can see it in your eyes",
"extraclasses": "rounded p-2 border",
"buttonextraclasses": "font-weight-bold"
}
{{< /mustache >}}
## Example used as a template block
{{< mustache template="tool_componentlibrary/examples/showmore/example" >}}
{
}
{{< /mustache >}}
@@ -0,0 +1,84 @@
---
layout: docs
title: "Toggle input"
date: 2022-01-17T00:00:00+01:00
draft: false
weight: 60
tags:
- MDL-73470
- 4.0
---
## How to use
Toggle input is rendered using a template found in lib/templates/toggle.mustache.
The parameters for the template context are:
* id: Unique id for the toggle input.
* extraclasses: Any extra classes added to the toggle input outer container.
* checked: If the initial status is checked.
* disabled: If toggle input is disabled.
* dataattributes: Array of name/value elements added as data-attributes.
* title: Title text.
* label: Label text.
* labelclasses: Any extra classes added to the label container.
## Examples
<div class="small">
Checked toggle and with "sr-only" label.
</div>
{{< mustache template="core/toggle" >}}
{
"id": "example-toggle-1",
"checked": true,
"dataattributes": [{
"name": "action",
"value": "toggle-status"
}],
"title": "Toggle Enabled",
"label": "Enable/disable status",
"labelclasses": "sr-only"
}
{{< /mustache >}}
<div class="mt-3 small">
Disabled toggle with extra classes.
</div>
{{< mustache template="core/toggle" >}}
{
"id": "example-toggle-2",
"disabled": true,
"extraclasses": "mt-2 ml-2",
"dataattributes": [{
"name": "action",
"value": "toggle-status"
}],
"title": "Toggle Disabled",
"label": "Enable/disable status"
}
{{< /mustache >}}
## Use toggle as a template block
It is also possible to include *core/toggle* in any other template using [blocks](https://moodledev.io/docs/guides/templates#blocks), instead of rendering it with a context.
The parameters that you can define are:
* id: Unique id for the toggle input.
* extraclasses: Any extra classes added to the toggle input outer container.
* attributes: Any attributes added to the toggle input.
* data-attributes
* checked
* disabled
* labelmarkup: Label element code block.
* Should include *class="custom-control-label"*.
* title: Title text.
* label: Label text.
* labelclasses: Any extra classes added to the label container.
<div class="small">
Example of template using toggle as a block.
</div>
{{< mustache template="tool_componentlibrary/examples/toggle/example" >}}
{
}
{{< /mustache >}}
@@ -0,0 +1,6 @@
---
title: "JavaScript"
date: 2020-02-03T15:26:15Z
draft: false
weight: 30
---
@@ -0,0 +1,86 @@
---
layout: docs
title: "Moodle Charts"
date: 2020-01-14T16:32:24+01:00
draft: false
---
## How it works
The core chart_builder interface for the ChartJS library that allows you to create a nice visual presentation of your data.
## Source files
* `lib/amd/src/chart_builder.js`
* `lib/amd/src/chart_*.js`
* `lib/templates/chart.mustache`
## Core api
Create a new instance of your required chart type
{{< php >}}
$chart1 = new chart_bar();
$series1 = new chart_series('Data type', $data);
$chart1->add_series($series1);
$OUTPUT->render($chart1);
{{< / php >}}
### JavaScript
{{< mustache template="core/chart" >}}
{
"chartdata": "{\u0022type\u0022:\u0022pie\u0022,\u0022series\u0022:[{\u0022label\u0022:\u0022Sales\u0022,\u0022labels\u0022:null,\u0022type\u0022:null,\u0022values\u0022:[1000,1170,660,1030],\u0022colors\u0022:[],\u0022axes\u0022:{\u0022x\u0022:null,\u0022y\u0022:null},\u0022smooth\u0022:null}],\u0022labels\u0022:[\u00222004\u0022,\u00222005\u0022,\u00222006\u0022,\u00222007\u0022],\u0022title\u0022:\u0022PIE CHART\u0022,\u0022axes\u0022:{\u0022x\u0022:[],\u0022y\u0022:[]},\u0022config_colorset\u0022:null,\u0022doughnut\u0022:null}",
"withtable": true
}
{{< /mustache >}}
{{< mustache template="core/chart" >}}
{
"chartdata": "{\u0022type\u0022:\u0022pie\u0022,\u0022series\u0022:[{\u0022label\u0022:\u0022Sales\u0022,\u0022labels\u0022:null,\u0022type\u0022:null,\u0022values\u0022:[1000,1170,660,1030],\u0022colors\u0022:[],\u0022axes\u0022:{\u0022x\u0022:null,\u0022y\u0022:null},\u0022smooth\u0022:null}],\u0022labels\u0022:[\u00222004\u0022,\u00222005\u0022,\u00222006\u0022,\u00222007\u0022],\u0022title\u0022:\u0022DOUGHNUT CHART\u0022,\u0022axes\u0022:{\u0022x\u0022:[],\u0022y\u0022:[]},\u0022config_colorset\u0022:null,\u0022doughnut\u0022:true}",
"withtable": true
}
{{< /mustache >}}
{{< mustache template="core/chart" >}}
{
"chartdata": "{\u0022type\u0022:\u0022line\u0022,\u0022series\u0022:[{\u0022label\u0022:\u0022Sales\u0022,\u0022labels\u0022:null,\u0022type\u0022:null,\u0022values\u0022:[1000,1170,660,1030],\u0022colors\u0022:[],\u0022axes\u0022:{\u0022x\u0022:null,\u0022y\u0022:null},\u0022smooth\u0022:null},{\u0022label\u0022:\u0022Expenses\u0022,\u0022labels\u0022:null,\u0022type\u0022:null,\u0022values\u0022:[400,460,1120,540],\u0022colors\u0022:[],\u0022axes\u0022:{\u0022x\u0022:null,\u0022y\u0022:null},\u0022smooth\u0022:null}],\u0022labels\u0022:[\u00222004\u0022,\u00222005\u0022,\u00222006\u0022,\u00222007\u0022],\u0022title\u0022:\u0022TENSIONED LINES CHART\u0022,\u0022axes\u0022:{\u0022x\u0022:[],\u0022y\u0022:[]},\u0022config_colorset\u0022:null,\u0022smooth\u0022:false}",
"withtable": true
}
{{< /mustache >}}
{{< mustache template="core/chart" >}}
{
"chartdata": "{\u0022type\u0022:\u0022line\u0022,\u0022series\u0022:[{\u0022label\u0022:\u0022Sales\u0022,\u0022labels\u0022:null,\u0022type\u0022:null,\u0022values\u0022:[1000,1170,660,1030],\u0022colors\u0022:[],\u0022axes\u0022:{\u0022x\u0022:null,\u0022y\u0022:null},\u0022smooth\u0022:null},{\u0022label\u0022:\u0022Expenses\u0022,\u0022labels\u0022:null,\u0022type\u0022:null,\u0022values\u0022:[400,460,1120,540],\u0022colors\u0022:[],\u0022axes\u0022:{\u0022x\u0022:null,\u0022y\u0022:null},\u0022smooth\u0022:null}],\u0022labels\u0022:[\u00222004\u0022,\u00222005\u0022,\u00222006\u0022,\u00222007\u0022],\u0022title\u0022:\u0022SMOOTH LINES CHART\u0022,\u0022axes\u0022:{\u0022x\u0022:[],\u0022y\u0022:[]},\u0022config_colorset\u0022:null,\u0022smooth\u0022:true}",
"withtable": true
}
{{< /mustache >}}
{{< mustache template="core/chart" >}}
{
"chartdata": "{\u0022type\u0022:\u0022bar\u0022,\u0022series\u0022:[{\u0022label\u0022:\u0022Sales\u0022,\u0022labels\u0022:null,\u0022type\u0022:null,\u0022values\u0022:[1000,1170,660,1030],\u0022colors\u0022:[],\u0022axes\u0022:{\u0022x\u0022:null,\u0022y\u0022:null},\u0022smooth\u0022:null},{\u0022label\u0022:\u0022Expenses\u0022,\u0022labels\u0022:null,\u0022type\u0022:null,\u0022values\u0022:[400,460,1120,540],\u0022colors\u0022:[],\u0022axes\u0022:{\u0022x\u0022:null,\u0022y\u0022:null},\u0022smooth\u0022:null}],\u0022labels\u0022:[\u00222004\u0022,\u00222005\u0022,\u00222006\u0022,\u00222007\u0022],\u0022title\u0022:\u0022BAR CHART\u0022,\u0022axes\u0022:{\u0022x\u0022:[],\u0022y\u0022:[{\u0022label\u0022:null,\u0022labels\u0022:null,\u0022max\u0022:null,\u0022min\u0022:0,\u0022position\u0022:null,\u0022stepSize\u0022:null}]},\u0022config_colorset\u0022:null,\u0022horizontal\u0022:false,\u0022stacked\u0022:null}",
"withtable": true
}
{{< /mustache >}}
{{< mustache template="core/chart" >}}
{
"chartdata": "{\u0022type\u0022:\u0022bar\u0022,\u0022series\u0022:[{\u0022label\u0022:\u0022Sales\u0022,\u0022labels\u0022:null,\u0022type\u0022:null,\u0022values\u0022:[1000,1170,660,1030],\u0022colors\u0022:[],\u0022axes\u0022:{\u0022x\u0022:null,\u0022y\u0022:null},\u0022smooth\u0022:null},{\u0022label\u0022:\u0022Expenses\u0022,\u0022labels\u0022:null,\u0022type\u0022:null,\u0022values\u0022:[400,460,1120,540],\u0022colors\u0022:[],\u0022axes\u0022:{\u0022x\u0022:null,\u0022y\u0022:null},\u0022smooth\u0022:null}],\u0022labels\u0022:[\u00222004\u0022,\u00222005\u0022,\u00222006\u0022,\u00222007\u0022],\u0022title\u0022:\u0022HORIZONTAL BAR CHART\u0022,\u0022axes\u0022:{\u0022x\u0022:[],\u0022y\u0022:[{\u0022label\u0022:null,\u0022labels\u0022:null,\u0022max\u0022:null,\u0022min\u0022:0,\u0022position\u0022:null,\u0022stepSize\u0022:null}]},\u0022config_colorset\u0022:null,\u0022horizontal\u0022:true,\u0022stacked\u0022:null}",
"withtable": true
}
{{< /mustache >}}
{{< mustache template="core/chart" >}}
{
"chartdata": "{\u0022type\u0022:\u0022bar\u0022,\u0022series\u0022:[{\u0022label\u0022:\u0022Sales\u0022,\u0022labels\u0022:null,\u0022type\u0022:null,\u0022values\u0022:[1000,1170,660,1030],\u0022colors\u0022:[],\u0022axes\u0022:{\u0022x\u0022:null,\u0022y\u0022:null},\u0022smooth\u0022:null},{\u0022label\u0022:\u0022Expenses\u0022,\u0022labels\u0022:null,\u0022type\u0022:null,\u0022values\u0022:[400,460,1120,540],\u0022colors\u0022:[],\u0022axes\u0022:{\u0022x\u0022:null,\u0022y\u0022:null},\u0022smooth\u0022:null}],\u0022labels\u0022:[\u00222004\u0022,\u00222005\u0022,\u00222006\u0022,\u00222007\u0022],\u0022title\u0022:\u0022STACKED BAR CHART\u0022,\u0022axes\u0022:{\u0022x\u0022:[],\u0022y\u0022:[{\u0022label\u0022:null,\u0022labels\u0022:null,\u0022max\u0022:null,\u0022min\u0022:0,\u0022position\u0022:null,\u0022stepSize\u0022:null}]},\u0022config_colorset\u0022:null,\u0022horizontal\u0022:false,\u0022stacked\u0022:true}",
"withtable": true
}
{{< /mustache >}}
{{< mustache template="core/chart" >}}
{
"chartdata": "{\u0022type\u0022:\u0022bar\u0022,\u0022series\u0022:[{\u0022label\u0022:\u0022Expenses\u0022,\u0022labels\u0022:null,\u0022type\u0022:\u0022line\u0022,\u0022values\u0022:[400,460,1120,540],\u0022colors\u0022:[],\u0022axes\u0022:{\u0022x\u0022:null,\u0022y\u0022:null},\u0022smooth\u0022:null},{\u0022label\u0022:\u0022Sales\u0022,\u0022labels\u0022:null,\u0022type\u0022:null,\u0022values\u0022:[1000,1170,660,1030],\u0022colors\u0022:[],\u0022axes\u0022:{\u0022x\u0022:null,\u0022y\u0022:null},\u0022smooth\u0022:null}],\u0022labels\u0022:[\u00222004\u0022,\u00222005\u0022,\u00222006\u0022,\u00222007\u0022],\u0022title\u0022:\u0022BAR CHART COMBINED WITH LINE CHART\u0022,\u0022axes\u0022:{\u0022x\u0022:[],\u0022y\u0022:[{\u0022label\u0022:null,\u0022labels\u0022:null,\u0022max\u0022:null,\u0022min\u0022:0,\u0022position\u0022:null,\u0022stepSize\u0022:null}]},\u0022config_colorset\u0022:null,\u0022horizontal\u0022:false,\u0022stacked\u0022:null}",
"withtable": true
}
{{< /mustache >}}
@@ -0,0 +1,114 @@
---
layout: docs
title: "Confirm"
description: "A reusable confirmation modal component"
date: 2021-12-09T14:48:00+08:00
draft: false
tags:
- MDL-71963
- "4.0"
---
## How it works
The confirm module is automatically invoked on page load, you just need to add some specific data attributes
to the element that will trigger the confirmation modal.
## Source files
* `lib/amd/src/utility.js` ({{< jsdoc module="core/utility" >}})
* `lib/templates/modal.mustache`
## Usage
The confirmation AMD module is loaded automatically, so the only thing you need to do is to add some specific data attributes
to the target element:
{{< highlight html >}}
<button type="button" class="btn btn-primary" data-confirmation="modal" data-confirmation-title-str='["delete", "core"]'
data-confirmation-content-str='["areyousure"]' data-confirmation-yes-button-str='["delete", "core"]'>Show confirmation modal</button>
{{< /highlight >}}
You can also use it on PHP, you just need to set the attributes parameter to any moodle output component that takes attributes:
{{< php >}}
echo $OUTPUT->single_button('#', get_string('delete'), 'get', [
'data-confirmation' => 'modal',
'data-confirmation-title-str' => json_encode(['delete', 'core']),
'data-confirmation-content-str' => json_encode(['areyousure']),
'data-confirmation-yes-button-str' => json_encode(['delete', 'core'])
]);
{{< / php >}}
## Attributes
<table class="table">
<thead>
<tr>
<th style="width: 250px;">Data attribute</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>data-confirmation</td>
<td>The identifier value must be "modal" so the module can find and register an event listener for that element.</td>
</tr>
<tr>
<td>data-confirmation-title-str</td>
<td>The modal title language string identifier, must be provided in JSON encoded format.</td>
</tr>
<tr>
<td>data-confirmation-content-str</td>
<td>The modal main content language string identifier, must be provided in JSON encoded format.</td>
</tr>
<tr>
<td>data-confirmation-yes-button-str</td>
<td>The language string identifier for the "Yes" button, must be provided in JSON encoded format.</td>
</tr>
<tr>
<td>data-confirmation-toast</td>
<td>If set to "true" it will display a confirmation toast in the end.</td>
</tr>
<tr>
<td>data-confirmation-toast-confirmation-str</td>
<td>The confirmation toast language string identifier, must be provided in JSON encoded format.</td>
</tr>
<tr>
<td>data-confirmation-destination</td>
<td>An url to redirect the user to.</td>
</tr>
</tbody>
</table>
## Examples
### Basic confirmation modal
#### Simple Modal
{{< example >}}
<button type="button" class="btn btn-primary" data-confirmation="modal" data-confirmation-title-str='["ok", "core"]'
data-confirmation-content-str='["areyousure"]' data-confirmation-yes-button-str='["ok", "core"]'>Show confirmation modal</button>
{{< /example >}}
#### Delete Modal
{{< example >}}
<button type="button" class="btn btn-primary" data-confirmation="modal" data-confirmation-type="delete" data-confirmation-title-str='["delete", "core"]'
data-confirmation-content-str='["areyousure"]' data-confirmation-yes-button-str='["delete", "core"]'>Show delete modal</button>
{{< /example >}}
### Confirmation modal with a toast
{{< example >}}
<button type="button" class="btn btn-primary" data-confirmation="modal" data-confirmation-title-str='["save", "core"]'
data-confirmation-content-str='["areyousure"]' data-confirmation-yes-button-str='["save", "core"]' data-confirmation-toast="true"
data-confirmation-toast-confirmation-str='["saved", "core_question", "My question"]'>Show confirmation modal</button>
{{< /example >}}
### Confirmation modal with redirect
{{< example >}}
<button type="button" class="btn btn-primary" data-confirmation="modal" data-confirmation-title-str='["save", "core"]'
data-confirmation-content-str='["areyousure"]' data-confirmation-yes-button-str='["save", "core"]'
data-confirmation-destination="http://moodle.com">Show confirmation modal</button>
{{< /example >}}
@@ -0,0 +1,63 @@
---
layout: docs
title: "Emojipicker"
date: 2020-02-04T09:40:32+01:00
draft: false
tags:
- MDL-65896
- 3.8
---
## How it works
The emoji picker is used in the Moodle messaging interface and in Atto. It allows you to select an emoji which then is returned for use in your input element.
## Source files
* `lib/amd/src/emoji/picker.js`
* `lib/templates/emoji/picker.mustache`
## Examples
{{< example >}}
<div class="row">
<div data-region="emojipickertest" class="col-md-9">
</div>
<div class="col-md-3">
<h4>Emoji picker result:<h4>
<div data-region="emojivalue" style="font-size: 3rem"></div>
</div>
{{#js}}
require(
[
'jquery',
'core/templates',
'core/emoji/picker'
],
function(
$,
templates,
emojiPicker
) {
var emojiCallback = function(emoji) {
$('[data-region="emojivalue"]').html(emoji);
}
var testArea = $('[data-region="emojipickertest"]');
templates.render('core/emoji/picker', {}).done(function(html, js) {
templates.replaceNodeContents(testArea, html, js);
emojiPicker(testArea[0], emojiCallback);
});
});
{{/js}}
{{< /example >}}
## Usage
Fetch / render the core template ```core/emoji/picker.mustache``` and load the ```core/emoji/picker.js```. Render the template and run the js on the new domnode.
{{< highlight js >}}
emojiPicker(domNode, callback);
{{< /highlight >}}
@@ -0,0 +1,124 @@
---
layout: docs
title: "Sortable list"
description: "A reusable list component for sorting"
date: 2020-02-04T09:40:32+01:00
draft: false
tags:
- MDL-51803
- 3.7
---
## How it works
The sortable lists can be used for horizontal and vertical ordering of list elements. The key element of using a sortable list is to provide drag handles to list items. These can be included using the core drag_handle template.
## Source files
* `/lib/amd/src/sortable_lists.js`
* `/lib/templates/drag_handle.mustache`
## Usage
The sortable list AMD module can be loaded in your template or via a amd init call. The list to be sorted is passed as the first argument to
{{< highlight js >}}
// Default config, this variable is optional.
var config = {
targetListSelector: null,
moveHandlerSelector: '[data-drag-type=move]',
isHorizontal: false,
autoScroll: true
};
new SortableList(domElement, config);
{{< /highlight >}}
The events listed below can be used to connect the sortable list to a webserver handling changed positions of your sortable list items.
## Events
<table class="table">
<thead>
<tr>
<th style="width: 150px;">Event type</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>SortableList.EVENTS.DRAGSTART</td>
<td>This event fires immediately when user started dragging a list element.</td>
</tr>
<tr>
<td>SortableList.EVENTS.DRAG</td>
<td>This event is fired when user dragged a list element to a new position.</td>
</tr>
<tr>
<td>SortableList.EVENTS.DROP</td>
<td>This event is fired when user dropped a list element</td>
</tr>
<tr>
<td>SortableList.EVENTS.DROPEND</td>
<td>This event is fired when user finished dragging - either fired right after dropping or if "Esc" was pressed during dragging</td>
</tr>
</tbody>
</table>
## Examples
{{< example>}}
<div class="row w-50">
<div class="col-md-6">
<ul class="list-group my-draggable-list-ex">
<li class="list-group-item">
<span tabindex="0" role="button" aria-haspopup="true" data-drag-type="move" title="1. Cras justo odio">
<i class="fa fa-arrows"></i>
</span>
1. Cras justo odio
</li>
<li class="list-group-item">
<span tabindex="0" role="button" aria-haspopup="true" data-drag-type="move" title="2. Dapibus ac facilisis in">
<i class="fa fa-arrows"></i>
</span>
2. Dapibus ac facilisis in
</li>
<li class="list-group-item">
<span tabindex="0" role="button" aria-haspopup="true" data-drag-type="move" title="3. Morbi leo risus">
<i class="fa fa-arrows"></i>
</span>
3. Morbi leo risus
</li>
<li class="list-group-item">
<span tabindex="0" role="button" aria-haspopup="true" data-drag-type="move" title="4. Porta ac consectetur ac">
<i class="fa fa-arrows"></i>
</span>
4. Porta ac consectetur ac
</li>
<li class="list-group-item">
<span tabindex="0" role="button" aria-haspopup="true" data-drag-type="move" title="5. Vestibulum at eros">
<i class="fa fa-arrows"></i>
</span>
5. Vestibulum at eros
</li>
</ul>
</div>
</div>
{{#js}}
require(
[
'jquery',
'core/sortable_list',
],
function(
$,
SortableList
) {
new SortableList('ul.my-draggable-list-ex');
$('ul.my-draggable-list-ex > *').on(SortableList.EVENTS.DROP, function(evt, info) {
console.log(info);
});
});
{{/js}}
{{< /example >}}
@@ -0,0 +1,120 @@
---
layout: docs
title: "Toast"
date: 2021-12-09T14:48:00+08:00
draft: false
tags:
- MDL-66828
- MDL-67074
- MDL-72544
- 3.8
---
## How it works
Toasts are lightweight notifications designed to mimic push notifications.
Moodle toasts are based upon core the Bootstrap notification feature, but with a Moodle Javascript module wrapper.
## Source files
* `lib/amd/src/toast.js` ({{< jsdoc module="core/toast" >}})
* `lib/templates/local/toast/message.mustache`
## Examples
Toasts can only be applied from JavaScript, and the most basic form just takes the message to be displayed.
### Displaying a simple message
{{< example >}}
<button type="button" class="btn btn-info" data-example-name="basic">Basic example</button>
{{#js}}
require(['core/toast'], Toast => {
const button = document.querySelector("[data-example-name='basic']")
button.addEventListener('click', () => {
Toast.add('This is the message for the toast');
});
});
{{/js}}
{{< /example >}}
### Applying semantic styles
The standard semantic Bootstrap styles can be applied.
{{< example >}}
<button type="button" class="btn btn-success" data-example-name="semantic" data-type="success">Success</button>
<button type="button" class="btn btn-danger" data-example-name="semantic" data-type="danger">Danger</button>
<button type="button" class="btn btn-warning" data-example-name="semantic" data-type="warning">Warning</button>
<button type="button" class="btn btn-info" data-example-name="semantic" data-type="info">Info</button>
{{#js}}
require(['core/toast'], Toast => {
const container = document.querySelector("[data-example-name='semantic']").parentNode;
container.addEventListener('click', e => {
if (!e.target.closest('[data-type]')) {
return;
}
Toast.add(`This toast will be displayed with the ${e.target.dataset.type} type.`, {
type: e.target.dataset.type,
});
});
});
{{/js}}
{{< /example >}}
### Auto-hide, and close buttons
The standard behaviour of the toast is to auto-hide after a short period which
can be configured or disabled. A close button can also be displayed, which is
recommended when a longer period is used.
| Name | Description |
| ------------- | ----------------------------------------------------------------------------- |
| `delay` | An auto-hide delay can be configured by providing a millisecond setting |
| `autohide` | The auto-hide can be entirely disabled using this boolean setting |
| `closeButton` | The presence of the close button can be controlled using this boolean setting |
{{< example >}}
<button type="button" class="btn btn-primary" data-example-name="autohide-long">Auto-hide long</button>
<button type="button" class="btn btn-primary" data-example-name="autohide-disabled">Auto-hide disabled</button>
{{#js}}
require(['core/toast'], Toast => {
document.querySelector("[data-example-name='autohide-long']").addEventListener('click', e => {
Toast.add('This message will be displayed for 30 seconds with a closeButton', {
delay: 30000,
closeButton: true,
});
});
document.querySelector("[data-example-name='autohide-disabled']").addEventListener('click', e => {
Toast.add('This message will be displayed until closed using the closeButton.', {
autohide: false,
closeButton: true,
});
});
});
{{/js}}
{{< /example >}}
### Using a Language String
The standard behaviour of the toast is to auto-hide after a short period which
can be configured or disabled. A close button can also be displayed, which is
recommended when a longer period is used.
{{< example >}}
<button type="button" class="btn btn-primary" data-example-name="langstring">Language string</button>
{{#js}}
require(['core/toast', 'core/str'], (Toast, Str) => {
document.querySelector("[data-example-name='langstring']").addEventListener('click', e => {
Toast.add(Str.get_string('ok'));
});
});
{{/js}}
{{< /example >}}
@@ -0,0 +1,6 @@
---
title: "Themes"
date: 2020-02-03T15:26:15Z
draft: false
weight: 40
---
@@ -0,0 +1,77 @@
---
layout: docs
title: "Colours"
date: 2020-02-04T09:40:32+01:00
draft: false
weight: 1
---
## The Moodle colour scheme:
Moodle colours are slighty different from standard Bootstrap colours. Custom moodle colours are usually defined in a theme preset. For example `theme/boost/scss/preset/default.scss`
{{< example show_markup=false >}}
<div class="card-deck">
{{< colors.inline >}}
{{- range (index $.Site.Data "colors") }}
<div class="card mb-2 justify-content-center align-items-center d-flex" style="flex: 0 0 20%; height: 150px">
<div class="card-body bg-{{ .name }} w-100" style="height: 100px">
</div>
<div class="card-footer w-100">
<span>{{ .name }}</span>
</div>
</div>
{{- end -}}
{{< /colors.inline >}}
</div>
{{< /example >}}
## The standard Bootstrap colour scheme:
{{< example show_markup=false >}}
<div class="card-deck">
{{< colors.inline >}}
{{- range (index $.Site.Data "colors") }}
<div class="card mb-2 justify-content-center align-items-center d-flex" style="flex: 0 0 20%; height: 150px">
<div class="card-body w-100" style="height: 100px; background-color: {{ .hex }}">
</div>
<div class="card-footer w-100">
<span>{{ .name }}</span>
</div>
</div>
{{- end -}}
{{< /colors.inline >}}
</div>
{{< /example >}}
These colours are used throughout Moodle in text, buttons
{{< example show_markup=false >}}
<p>
<span class="badge badge-success">Badges</span>
</p>
<p>
<button class="btn btn-success">Buttons</button>
</p>
<p>
<div class="border border-success">Borders</div>
</p>
{{< /example >}}
## Customizing moodle colours
Use the $theme-colours Scss array to customize colours in theme/boost/scss/preset/default.scss.
{{< highlight scss >}}
$theme-colors: map-merge((
primary: #1177d1,
secondary: #ced4da,
success: #398439,
info: #5bc0de,
warning: #f0ad4e,
danger: #d43f3a,
light: #f8f9fa,
dark: #373a3c
), $theme-colors);
{{< /highlight >}}
@@ -0,0 +1,75 @@
---
layout: docs
title: "Grids"
descriptions: Using grids in Moodle
date: 2020-02-04T09:40:32+01:00
draft: false
weight: 1
---
Use the bootstrap grid column classes to create responsive grids. Rules to follow:
* Always wrap rows in a container
* Combine column classes to create responsive grids
* Keep the context in mind, modals behave different from #region-main
* Don't add to much styles to the grid container, us an inner div
{{< example>}}
<div class="container-fluid">
<div class="row">
<div class="col-6 col-md-4 col-lg-3 col-xl-2 mb-3">
<div class="inner h-100 border p-1">
Lorem ipsum dolor sit amet
</div>
</div>
<div class="col-6 col-md-4 col-lg-3 col-xl-2 mb-3">
<div class="inner h-100 border p-1">
Lonsectetuer adipiscing elit. Aenean commodo ligula eget dolor.
</div>
</div>
<div class="col-6 col-md-4 col-lg-3 col-xl-2 mb-3">
<div class="inner h-100 border p-1">
Donec quam felis, ultricies nec, pellentesque eu, pretium quis, sem. Nulla consequat massa quis enim.
</div>
</div>
<div class="col-6 col-md-4 col-lg-3 col-xl-2 mb-3">
<div class="inner h-100 border p-1">
ascetur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu.
</div>
</div>
<div class="col-6 col-md-4 col-lg-3 col-xl-2 mb-3">
<div class="inner h-100 border p-1">
Lretium quis, sem. Nulla consequat massa quis enim.
</div>
</div>
<div class="col-6 col-md-4 col-lg-3 col-xl-2 mb-3">
<div class="inner h-100 border p-1">
Aenean commodo massa quis enim.
</div>
</div>
<div class="col-6 col-md-4 col-lg-3 col-xl-2 mb-3">
<div class="inner h-100 border p-1">
Donec quam felis, ultricies nec, pellentesque eu, pretium quis, sem.
</div>
</div>
<div class="col-6 col-md-4 col-lg-3 col-xl-2 mb-3">
<div class="inner h-100 border p-1">
Aenean commodo ligula eget dolor. Aenean massa. Cu quis enim.
</div>
</div>
<div class="col-6 col-md-4 col-lg-3 col-xl-2 mb-3">
<div class="inner h-100 border p-1">
Loltricies nec, pellentesque eu, quis enim.
</div>
</div>
<div class="col-6 col-md-4 col-lg-3 col-xl-2 mb-3">
<div class="inner h-100 border p-1">
Ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis.
</div>
</div>
</div>
</div>
{{< /example >}}
If needed
@@ -0,0 +1,76 @@
---
layout: docs
title: "Icon Sizes"
date: 2020-04-27T09:40:32+01:00
draft: false
weight: 5
---
Moodle icons are usually rendered using the template ```{{pix}}``` helper.
For example:
```{{#pix}}t/up, moodle, {{#str}} up, moodle {{/str}}{{/pix}}```
which results in
{{< example show_preview=true >}}
<i class="icon fa fa-arrow-up fa-fw " title="Up" aria-label="Up"></i>
{{< /example >}}
## Controlling the icon size
Use the ```icon-size-x``` classes to control the icon sizes.
{{< example show_markup=false >}}
<div class="d-flex">
<div class="icon-size-1 card bg-light mr-2">
<div class="card-body d-flex justify-content-center align-items-center">
<i class="fa fa-arrow-up icon"></i>
</div>
<div class="card-footer">
icon-size-1<br>4px
</div>
</div>
<div class="icon-size-2 card bg-light mr-2">
<div class="card-body d-flex justify-content-center align-items-center">
<i class="fa fa-arrow-up icon"></i>
</div>
<div class="card-footer">
icon-size-2<br>8px
</div>
</div>
<div class="icon-size-3 card bg-light mr-2">
<div class="card-body d-flex justify-content-center align-items-center">
<i class="fa fa-arrow-up icon"></i>
</div>
<div class="card-footer">
icon-size-3<br>16px (default)
</div>
</div>
<div class="icon-size-4 card bg-light mr-2">
<div class="card-body d-flex justify-content-center align-items-center">
<i class="fa fa-arrow-up icon"></i>
</div>
<div class="card-footer">
icon-size-4<br>24px
</div>
</div>
<div class="icon-size-5 card bg-light mr-2">
<div class="card-body d-flex justify-content-center align-items-center">
<i class="fa fa-arrow-up icon"></i>
</div>
<div class="card-footer">
icon-size-5<br>32px
</div>
</div>
<div class="icon-size-6 card bg-light mr-2">
<div class="card-body d-flex justify-content-center align-items-center">
<i class="fa fa-arrow-up icon"></i>
</div>
<div class="card-footer">
icon-size-6<br>40px
</div>
</div>
</div>
{{< /example >}}
@@ -0,0 +1,31 @@
---
layout: docs
title: "Layout"
description: "Moodle page layouts for themes"
date: 2019-12-10T13:53:41+01:00
draft: false
---
## High level templates
Theme layouts are the highest level templates found in Moodle. They construct the Moodle Page users see when interacting with Moodle.
Layout files define the location of page elements like the primary and secondary navigation, the main content, Moodle blocks and the footer.
Theme layouts are defined in a themes config.php and themes can serve different layout files depending on the page type, example layouts are
* frontpage
* course page
* activity page
* secure page
* login page
## Accessibility considerations
When interacting with a theme the layout needs to be constructed with a logical DOM order: First render the primary navigation, then the secondary navigation then the page content, then the footer.
## Responsiveness
Use [Bootstrap grids]({{< docsref "/layout/grid" >}}) to create a responsive design. Make sure the primary and secondary navigation can be found easily on a mobile device.
Always try themes on all different theme layouts and ensure font-sizes, paddings and margins are used correctly. Especially for frequently used pages like courses and activities.
@@ -0,0 +1,55 @@
---
layout: docs
title: "Positioning"
description: The use of Bootstraps flexbox utilities to position items on the screen.
date: 2020-02-04T09:40:32+01:00
draft: false
weight: 3
---
##
## Position an single item at the right
Use the ```.justify-content-end``` class to position on item in a ```.d-flex``` container to the right
{{< example >}}
<div class="d-flex justify-content-end">
<button class="btn btn-success">OK</button>
</div>
{{< /example >}}
## Position on item in a group of items to the right
Use the ```.ml-auto``` to move the last item in ad ```.d-flex``` container to the right.
{{< example >}}
<div class="d-flex">
<button class="btn btn-secondary mr-1">Ha!</button>
<button class="btn btn-secondary mr-1">Jay</button>
<button class="btn btn-secondary mr-1">Wow</button>
<button class="ml-auto btn btn-success">OK</button>
</div>
{{< /example >}}
### Center items
Use the ```align-items-center``` class to align items horizontally in a container.
{{< example >}}
<div class="d-flex align-items-center p-2 bg-light">
<div class="bg-success mr-2" style="width: 35px; height: 35px;"></div>
<div class="bg-warning mr-2" style="width: 48px; height: 48px;"></div>
<div class="bg-info mr-2" style="width: 20px; height: 20px;"></div>
</div>
{{< /example >}}
### Middle of the container
Combine the ```align-items-center``` with the ```justify-content-center``` class to position an element in the middle of a container.
{{< example >}}
<div class="d-flex align-items-center justify-content-center p-3 bg-light" style="height:100px;">
<div class="bg-warning mr-2" style="width: 48px; height: 48px;"></div>
</div>
{{< /example >}}
@@ -0,0 +1,59 @@
---
layout: docs
title: "Spacing"
description: Moodle spacing
date: 2020-02-04T09:40:32+01:00
draft: false
weight: 4
---
## How it works
Moodle's spacing classes build on Bootstrap spacing classes which can be set for margins and paddings on different screen breakpoints. Using these classes is preferred over setting custom spacing on UI elements using CSS.
### example class pt-3
class: ```pt-3:```
result: padding-top-three
css:
{{< highlight css >}}
.pt-3 {
padding-top: 1rem; /** 16px **/
}
{{< /highlight >}}
The classes are named using the format `{property}{sides}-{size}` for `xs` and `{property}{sides}-{breakpoint}-{size}` for `sm`, `md`, `lg`, and `xl`.
### Moodle spacing values
Moodle add's a 6th spacing value on top of the Bootstrap default spacing.
* `0` - for classes that eliminate the `margin` or `padding` by setting it to `0`
* `1` - (by default) for classes that set the `margin` or `padding` to `$spacer * .25`
* `2` - (by default) for classes that set the `margin` or `padding` to `$spacer * .5`
* `3` - (by default) for classes that set the `margin` or `padding` to `$spacer`
* `4` - (by default) for classes that set the `margin` or `padding` to `$spacer * 1.5`
* `5` - (by default) for classes that set the `margin` or `padding` to `$spacer * 2`
* `6` - (by default) for classes that set the `margin` or `padding` to `$spacer * 3`
* `auto` - for classes that set the `margin` to auto
### Example of paddings
{{< example>}}
<div class="d-flex align-items-center justify-content-center">
<div class="p-6 bg-dark">
<div class="p-5 bg-white">
<div class="p-4 bg-info">
<div class="p-3 bg-success">
<div class="p-2 bg-warning">
<div class="p-1 bg-danger">
</div>
</div>
</div>
</div>
</div>
</div>
</div>
{{< /example >}}
@@ -0,0 +1,76 @@
---
layout: docs
title: "Text"
description: "Moodle text utility classes"
date: 2019-12-10T13:53:41+01:00
draft: false
---
## Heading sizes with native heading tags
{{< example >}}
<h1>h1 heading</h1>
<h2>h2 heading</h2>
<h3>h3 heading</h3>
<h4>h4 heading</h4>
<h5>h5 heading</h5>
<h6>h6 heading</h6>
{{< /example >}}
## Heading sizes with heading classes
tip: you can use heading classes to style a native heading tag differently.
{{< example >}}
<p class="h1">h1 heading</p>
<p class="h2">h2 heading</p>
<h1 class="h3">h3 heading</h1>
<p class="h4">h4 heading</p>
<p class="h5">h5 heading</p>
<p class="h6">h6 heading</p>
{{< /example >}}
## Native text tags
{{< example >}}
<p>You can use the mark tag to <mark>highlight</mark> text.</p>
<p><del>This line of text is meant to be treated as deleted text.</del></p>
<p><s>This line of text is meant to be treated as no longer accurate.</s></p>
<p><ins>This line of text is meant to be treated as an addition to the document.</ins></p>
<p><u>This line of text will render as underlined</u></p>
<p><small>This line of text is meant to be treated as fine print.</small></p>
<p><strong>This line rendered as bold text.</strong></p>
<p><em>This line rendered as italicized text.</em></p>
{{< /example >}}
## Custom text tags
{{< example >}}
<p class="text-lowercase">Lowercased text.</p>
<p class="text-uppercase">Uppercased text.</p>
<p class="font-weight-bold">Bold text.</p>
<p class="font-weight-normal">Normal weight text.</p>
<p class="font-italic">Italic text.</p>
<p class="text-muted">
Muted text with a <a href="#" class="text-reset">reset link</a>.
</p>
{{< /example >}}
## For screenreaders
<h2 class="sr-only">Title for screen readers</h2>
<a class="sr-only-focusable" href="#content">Skip to main content</a>
## Text truncation
<!-- Block level -->
<div class="row">
<div class="col-2 text-truncate">
Praeterea iter est quasdam res quas ex communi.
</div>
</div>
<!-- Inline level -->
<span class="d-inline-block text-truncate" style="max-width: 150px;">
Praeterea iter est quasdam res quas ex communi.
</span>