This change allows form elements to be overridden with a mustache template.
The template can even listen for form validation errors and supply the JS to
change the look of the form element when there is/isn't a validation error.
Initial support is for all core form elements including:
text, select, selectyesno and checkboxes, groups, dateselector, datetimeselector,
autocomplete, modvisible, advcheckbox, button, duration, filemanager, filepicker, editor, static, grading,
warning, textarea, password, url, submit, questioncategory, recaptcha.
Part of MDL-55071
$options = array();
- $mform->addElement('selectwithlink', 'scaleid', get_string('scale'), $options, null,
- array('link' => $CFG->wwwroot.'/grade/edit/scale/edit.php?courseid='.$COURSE->id, 'label' => get_string('scalescustomcreate')));
+ $mform->addElement('select', 'scaleid', get_string('scale'), $options);
+
+ $url = new moodle_url('/grade/edit/scale/edit.php', array('courseid' => $COURSE->id));
+ $label = get_string('scalescustomcreate');
+ $mform->addElement('static', 'scaleidlink', '', html_writer::link($url, $label));
+
$mform->addHelpButton('scaleid', 'typescale', 'grades');
$mform->addRule('scaleid', get_string('required'), 'required');
$options[$outcome->id] = $outcome->get_name();
}
}
- $mform->addElement('selectwithlink', 'outcomeid', get_string('outcome', 'grades'), $options, null,
- array('link' => $CFG->wwwroot.'/grade/edit/outcome/course.php?id='.$COURSE->id, 'label' => get_string('outcomeassigntocourse', 'grades')));
+ $url = new moodle_url('/grade/edit/outcome/course.php', array('id' => $COURSE->id));
+ $label = get_string('outcomeassigntocourse', 'grades');
+
+ $mform->addElement('select', 'outcomeid', get_string('outcome', 'grades'), $options);
+ $mform->addElement('static', 'outcomeidlink', '', html_writer::link($url, $label));
$mform->addHelpButton('outcomeid', 'outcome', 'grades');
$mform->addRule('outcomeid', get_string('required'), 'required');
function($, Y) {
return /** @alias module:core/event */ {
+
+
// Public variables and functions.
+ // These are AMD only events - no backwards compatibility for new things.
+ Events: {
+ FORM_FIELD_VALIDATION: "core_form-field-validation"
+ },
+
/**
* Trigger an event using both JQuery and YUI
*
*/
require_once('HTML/QuickForm/advcheckbox.php');
+require_once(__DIR__ . '/../outputcomponents.php');
/**
* HTML class for an advcheckbox type element
* @copyright 2007 Jamie Pratt <me@jamiep.org>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
-class MoodleQuickForm_advcheckbox extends HTML_QuickForm_advcheckbox{
+class MoodleQuickForm_advcheckbox extends HTML_QuickForm_advcheckbox implements templatable {
/** @var string html for help button, if empty then no help will icon will be dispalyed. */
var $_helpbutton='';
}
return $output;
}
+
+ public function export_for_template(renderer_base $output) {
+ $context = [];
+ $context['frozen'] = $this->_flagFrozen;
+ foreach ($this->getAttributes() as $name => $value) {
+ $context[$name] = $value;
+ }
+ return $context;
+ }
}
}
return parent::onQuickFormEvent($event, $arg, $caller);
}
+
+ public function export_for_template(renderer_base $output) {
+ global $PAGE;
+
+ $this->_generateId();
+ $id = $this->getAttribute('id');
+ $PAGE->requires->js_call_amd('core/form-autocomplete', 'enhance', $params = array('#' . $id, $this->tags, $this->ajax,
+ $this->placeholder, $this->casesensitive, $this->showsuggestions, $this->noselectionstring));
+
+ $context = parent::export_for_template($output);
+ $context['tags'] = $this->tags;
+ $context['ajax'] = $this->ajax;
+ $context['placeholder'] = $this->placeholder;
+ $context['casesensitive'] = $this->casesensitive;
+ $context['showsuggestions'] = $this->showsuggestions;
+ $context['noselectionstring'] = $this->noselectionstring;
+
+ return $context;
+ }
}
*/
require_once("HTML/QuickForm/button.php");
+require_once(__DIR__ . '/../outputcomponents.php');
/**
* HTML class for a button type element
* @copyright 2007 Jamie Pratt <me@jamiep.org>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
-class MoodleQuickForm_button extends HTML_QuickForm_button
+class MoodleQuickForm_button extends HTML_QuickForm_button implements templatable
{
/** @var string html for help button, if empty then no help */
var $_helpbutton='';
return 'default';
}
}
+
+ public function export_for_template(renderer_base $output) {
+ $context = [];
+ $context['frozen'] = $this->_flagFrozen;
+ foreach ($this->getAttributes() as $name => $value) {
+ $context[$name] = $value;
+ }
+ return $context;
+ }
}
*/
require_once('HTML/QuickForm/checkbox.php');
+require_once(__DIR__ . '/../outputcomponents.php');
/**
* HTML class for a checkbox type element
* @copyright 2007 Jamie Pratt <me@jamiep.org>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
-class MoodleQuickForm_checkbox extends HTML_QuickForm_checkbox{
+class MoodleQuickForm_checkbox extends HTML_QuickForm_checkbox implements templatable {
/** @var string html for help button, if empty then no help */
var $_helpbutton='';
}
return $output;
}
+
+ public function export_for_template(renderer_base $output) {
+ $context = [];
+ $context['frozen'] = $this->_flagFrozen;
+ foreach ($this->getAttributes() as $name => $value) {
+ $context[$name] = $value;
+ }
+ return $context;
+ }
}
require_once('HTML/QuickForm/element.php');
require_once($CFG->dirroot.'/lib/filelib.php');
require_once($CFG->dirroot.'/repository/lib.php');
+require_once($CFG->libdir.'/outputcomponents.php');
/**
* Editor element
* @todo MDL-29421 element Freezing
* @todo MDL-29426 ajax format conversion
*/
-class MoodleQuickForm_editor extends HTML_QuickForm_element {
+class MoodleQuickForm_editor extends HTML_QuickForm_element implements templatable {
/** @var string html for help button, if empty then no help will icon will be dispalyed. */
public $_helpbutton = '';
* @return string
*/
function toHtml() {
- global $CFG, $PAGE;
+ global $CFG, $PAGE, $OUTPUT;
require_once($CFG->dirroot.'/repository/lib.php');
if ($this->_flagFrozen) {
$cols = empty($this->_attributes['cols']) ? 80 : $this->_attributes['cols'];
//Apply editor validation if required field
- $editorrules = '';
- if (!is_null($this->getAttribute('onblur')) && !is_null($this->getAttribute('onchange'))) {
- $editorrules = ' onblur="'.htmlspecialchars($this->getAttribute('onblur')).'" onchange="'.htmlspecialchars($this->getAttribute('onchange')).'"';
+ $context = [];
+ $context['rows'] = $rows;
+ $context['cols'] = $cols;
+ $context['frozen'] = $this->_flagFrozen;
+ foreach ($this->getAttributes() as $name => $value) {
+ $context[$name] = $value;
+ }
+ $context['hasformats'] = count($formats) > 1;
+ $context['formats'] = [];
+ foreach ($formats as $value => $text) {
+ $context['formats'][] = ['value' => $value, 'text' => $text, 'selected' => ($value == $format)];
}
- $str .= '<div><textarea id="'.$id.'" name="'.$elname.'[text]" rows="'.$rows.'" cols="'.$cols.'" spellcheck="true"'.$editorrules.'>';
- $str .= s($text);
- $str .= '</textarea></div>';
+ $context['id'] = $id;
+ $context['value'] = $text;
+ $context['format'] = $format;
- $str .= '<div>';
- if (count($formats)>1) {
- $str .= html_writer::label(get_string('format'), 'menu'. $elname. 'format', false, array('class' => 'accesshide'));
- $str .= html_writer::select($formats, $elname.'[format]', $format, false, array('id' => 'menu'. $elname. 'format'));
- } else {
- $keys = array_keys($formats);
- $str .= html_writer::empty_tag('input',
- array('name'=>$elname.'[format]', 'type'=> 'hidden', 'value' => array_pop($keys)));
+ $str .= $OUTPUT->render_from_template('core_form/editor_textarea', $context);
+
+ if (!is_null($this->getAttribute('onblur')) && !is_null($this->getAttribute('onchange'))) {
+ $context['changelistener'] = true;
}
- $str .= '</div>';
// during moodle installation, user area doesn't exist
// so we need to disable filepicker here.
return $str;
}
+ public function export_for_template(renderer_base $output) {
+ $context = [];
+ $context['frozen'] = $this->_flagFrozen;
+ foreach ($this->getAttributes() as $name => $value) {
+ $context[$name] = $value;
+ }
+ $context['html'] = $this->toHtml();
+ return $context;
+ }
+
/**
* What to display when element is frozen.
*
require_once('HTML/QuickForm/element.php');
require_once($CFG->dirroot.'/lib/filelib.php');
require_once($CFG->dirroot.'/repository/lib.php');
+require_once($CFG->libdir.'/outputcomponents.php');
/**
* Filemanager form element
* @copyright 2009 Dongsheng Cai <dongsheng@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
-class MoodleQuickForm_filemanager extends HTML_QuickForm_element {
+class MoodleQuickForm_filemanager extends HTML_QuickForm_element implements templatable {
/** @var string html for help button, if empty then no help will icon will be dispalyed. */
public $_helpbutton = '';
return $html;
}
+
+ public function export_for_template(renderer_base $output) {
+ $context = [];
+ $context['frozen'] = $this->_flagFrozen;
+ foreach ($this->getAttributes() as $name => $value) {
+ $context[$name] = $value;
+ }
+ $context['html'] = $this->toHtml();
+ return $context;
+ }
}
/**
require_once("HTML/QuickForm/button.php");
require_once($CFG->dirroot.'/repository/lib.php');
+require_once($CFG->libdir.'/outputcomponents.php');
/**
* Filepicker form element
* @copyright 2009 Dongsheng Cai <dongsheng@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
-class MoodleQuickForm_filepicker extends HTML_QuickForm_input {
+class MoodleQuickForm_filepicker extends HTML_QuickForm_input implements templatable {
/** @var string html for help button, if empty then no help will icon will be dispalyed. */
public $_helpbutton = '';
return $this->_prepareValue($draftitemid, true);
}
+
+ public function export_for_template(renderer_base $output) {
+ $context = [];
+ $context['frozen'] = $this->_flagFrozen;
+ foreach ($this->getAttributes() as $name => $value) {
+ $context[$name] = $value;
+ }
+ $context['html'] = $this->toHtml();
+ return $context;
+ }
}
global $CFG;
require_once("HTML/QuickForm/element.php");
require_once($CFG->dirroot.'/grade/grading/form/lib.php');
+require_once($CFG->libdir.'/outputcomponents.php');
if (class_exists('HTML_QuickForm')) {
HTML_QuickForm::registerRule('gradingvalidated', 'callback', '_validate', 'MoodleQuickForm_grading');
* @copyright 2011 Marina Glancy
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
-class MoodleQuickForm_grading extends HTML_QuickForm_input{
+class MoodleQuickForm_grading extends HTML_QuickForm_input implements templatable {
/** @var string html for help button, if empty then no help */
var $_helpbutton='';
*/
public function __construct($elementName=null, $elementLabel=null, $attributes=null) {
parent::__construct($elementName, $elementLabel, $attributes);
+ $this->_type = 'grading';
$this->gradingattributes = $attributes;
}
}
return true;
}
+
+ public function export_for_template(renderer_base $output) {
+ return $this->toHtml();
+ }
}
*/
require_once("HTML/QuickForm/group.php");
+require_once(__DIR__ . '/../outputcomponents.php');
/**
* HTML class for a form element group
* @copyright 2007 Jamie Pratt <me@jamiep.org>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
-class MoodleQuickForm_group extends HTML_QuickForm_group{
+class MoodleQuickForm_group extends HTML_QuickForm_group implements templatable {
/** @var string html for help button, if empty then no help */
var $_helpbutton='';
/** @var MoodleQuickForm */
protected $_mform = null;
+ var $_renderedfromtemplate = false;
+
/**
* constructor
*
}
return call_user_func_array([$this->_mform, 'createElement'], func_get_args());
}
+
+ public function export_for_template(renderer_base $output) {
+ global $OUTPUT;
+ $this->_renderedfromtemplate = true;
+
+ include_once('HTML/QuickForm/Renderer/Default.php');
+
+ $context = [];
+ $context['frozen'] = $this->_flagFrozen;
+ foreach ($this->getAttributes() as $name => $value) {
+ $context[$name] = $value;
+ }
+ $elements = [];
+ foreach ($this->_elements as $key => $element) {
+ $element->_generateId();
+ $name = $this->getName();
+ $elementname = '';
+ if ($this->_appendName) {
+ $elementname = $element->getName();
+ if (isset($elementname)) {
+ $element->setName($name . '['. (strlen($elementname) ? $elementname : $key) .']');
+ } else {
+ $element->setName($name);
+ }
+ }
+
+ $out = $OUTPUT->mform_element($element, false, '', true);
+
+ if (empty($out)) {
+ $renderer = new HTML_QuickForm_Renderer_Default();
+ $renderer->setElementTemplate('{element}');
+ $element->accept($renderer);
+ $out = $renderer->toHtml();
+ }
+ $elements[] = $out;
+ // Restore the element's name.
+ if ($this->_appendName) {
+ $element->setName($elementname);
+ }
+
+ }
+
+ $context['elements'] = $elements;
+ return $context;
+ }
+
+ /**
+ * Accepts a renderer
+ *
+ * @param object An HTML_QuickForm_Renderer object
+ * @param bool Whether a group is required
+ * @param string An error message associated with a group
+ * @access public
+ * @return void
+ */
+ function accept(&$renderer, $required = false, $error = null) {
+ $this->_createElementsIfNotExist();
+ $renderer->startGroup($this, $required, $error);
+ if (!$this->_renderedfromtemplate) {
+ // Backwards compatible path - only do this if we didn't render the sub-elements already.
+ $name = $this->getName();
+ foreach (array_keys($this->_elements) as $key) {
+ $element =& $this->_elements[$key];
+
+ if ($this->_appendName) {
+ $elementName = $element->getName();
+ if (isset($elementName)) {
+ $element->setName($name . '['. (strlen($elementName)? $elementName: $key) .']');
+ } else {
+ $element->setName($name);
+ }
+ }
+
+ $required = !$element->isFrozen() && in_array($element->getName(), $this->_required);
+
+ $element->accept($renderer, $required);
+
+ // restore the element's name
+ if ($this->_appendName) {
+ $element->setName($elementName);
+ }
+ }
+ }
+ $renderer->finishGroup($this);
+ }
}
$langscale = get_string('modgradetypescale', 'grades');
$this->scaleformelement = $this->createFormElement('select', 'modgrade_scale', $langscale,
$scales, $attributes);
- $this->scaleformelement->setHiddenLabel = false;
+ $this->scaleformelement->setHiddenLabel(true);
$scaleformelementid = $this->generate_modgrade_subelement_id('modgrade_scale');
$this->scaleformelement->updateAttributes(array('id' => $scaleformelementid));
// Maximum grade textbox.
$langmaxgrade = get_string('modgrademaxgrade', 'grades');
$this->maxgradeformelement = $this->createFormElement('text', 'modgrade_point', $langmaxgrade, array());
- $this->maxgradeformelement->setHiddenLabel = false;
+ $this->maxgradeformelement->setHiddenLabel(true);
$maxgradeformelementid = $this->generate_modgrade_subelement_id('modgrade_point');
$this->maxgradeformelement->updateAttributes(array('id' => $maxgradeformelementid));
$langtype = get_string('modgradetype', 'grades');
$this->gradetypeformelement = $this->createFormElement('select', 'modgrade_type', $langtype, $gradetype,
$attributes, true);
- $this->gradetypeformelement->setHiddenLabel = false;
+ $this->gradetypeformelement->setHiddenLabel(true);
$gradetypeformelementid = $this->generate_modgrade_subelement_id('modgrade_type');
$this->gradetypeformelement->updateAttributes(array('id' => $gradetypeformelementid));
'modgrade_rescalegrades',
$langrescalegrades,
$choices);
- $rescalegradesselect->setHiddenLabel = false;
+ $rescalegradesselect->setHiddenLabel(true);
$rescalegradesselectid = $this->generate_modgrade_subelement_id('modgrade_rescalegrades');
$rescalegradesselect->updateAttributes(array('id' => $rescalegradesselectid));
}
*/
require_once('HTML/QuickForm/password.php');
+require_once(__DIR__ . '/../outputcomponents.php');
/**
* Password type form element
* @copyright 2006 Jamie Pratt <me@jamiep.org>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
-class MoodleQuickForm_password extends HTML_QuickForm_password{
+class MoodleQuickForm_password extends HTML_QuickForm_password implements templatable {
/** @var string, html for help button, if empty then no help */
var $_helpbutton='';
function getHelpButton(){
return $this->_helpbutton;
}
+
+ public function export_for_template(renderer_base $output) {
+ $context = [];
+ $context['frozen'] = $this->_flagFrozen;
+ foreach ($this->getAttributes() as $name => $value) {
+ $context[$name] = $value;
+ }
+ return $context;
+ }
}
*/
require_once('HTML/QuickForm/input.php');
+require_once(__DIR__ . '/../outputcomponents.php');
/**
* recaptcha type form element
* @copyright 2008 Nicolas Connault <nicolasconnault@gmail.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
-class MoodleQuickForm_recaptcha extends HTML_QuickForm_input {
+class MoodleQuickForm_recaptcha extends HTML_QuickForm_input implements templatable {
/** @var string html for help button, if empty then no help */
var $_helpbutton='';
}
return true;
}
+
+ public function export_for_template(renderer_base $output) {
+ $context = [];
+ $context['frozen'] = $this->_flagFrozen;
+ foreach ($this->getAttributes() as $name => $value) {
+ $context[$name] = $value;
+ }
+ $context['html'] = $this->toHtml();
+ return $context;
+ }
}
*/
require_once('HTML/QuickForm/select.php');
+require_once(__DIR__ . '/../outputcomponents.php');
/**
* select type form element
* @copyright 2006 Jamie Pratt <me@jamiep.org>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
-class MoodleQuickForm_select extends HTML_QuickForm_select{
+class MoodleQuickForm_select extends HTML_QuickForm_select implements templatable {
/** @var string html for help button, if empty then no help */
var $_helpbutton='';
return $this->_prepareValue($cleaned[0], $assoc);
}
}
+
+ public function export_for_template(renderer_base $output) {
+ $context = [];
+ $context['frozen'] = $this->_flagFrozen;
+ $context['attributes'] = [];
+ foreach ($this->getAttributes() as $name => $value) {
+ $context[$name] = $value;
+ if (!in_array($name, ['id', 'name', 'multiple'])) {
+ $context['attributes'][] = ['name' => $name, 'value' => $value];
+ }
+ }
+
+ $options = [];
+ foreach ($this->_options as $option) {
+ if (is_array($this->_values) && in_array( (string) $option['attr']['value'], $this->_values)) {
+ $this->_updateAttrArray($option['attr'], ['selected' => 'selected']);
+ }
+ $o = [
+ 'text' => $option['text'],
+ 'value' => $option['attr']['value'],
+ 'selected' => !empty($option['attr']['selected'])
+ ];
+ $options[] = $o;
+ }
+ $context['options'] = $options;
+ $context['hideLabel'] = $this->_hiddenLabel;
+
+ return $context;
+ }
}
*/
require_once('HTML/QuickForm/element.php');
+require_once(__DIR__ . '/../outputcomponents.php');
/**
* select type form element
* @copyright 2007 Jamie Pratt <me@jamiep.org>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
-class MoodleQuickForm_selectgroups extends HTML_QuickForm_element {
+class MoodleQuickForm_selectgroups extends HTML_QuickForm_element implements templatable {
/** @var bool add choose option */
var $showchoose = false;
return 'default';
}
}
+
+ public function export_for_template(renderer_base $output) {
+ $context = [];
+ $context['frozen'] = $this->_flagFrozen;
+ $context['attributes'] = [];
+ foreach ($this->getAttributes() as $name => $value) {
+ $context[$name] = $value;
+ if (!in_array($name, ['id', 'name', 'multiple'])) {
+ $context['attributes'][] = ['name' => $name, 'value' => $value];
+ }
+ }
+ $optiongroups = [];
+ if ($this->showchoose) {
+ $optionsgroups[] = [
+ 'text' => get_string('choosedots')
+ ];
+ }
+
+ foreach ($this->_optGroups as $group) {
+ $options = [];
+
+ foreach ($group['options'] as $option) {
+ $o = [];
+ if (is_array($this->_values) && in_array((string)$option['attr']['value'], $this->_values)) {
+ $o['selected'] = true;
+ } else {
+ $o['selected'] = false;
+ }
+ $o['text'] = $option['text'];
+ $options[] = $o;
+ }
+
+ $og = [
+ 'text' => $group['attr']['label'],
+ 'options' => $options
+ ];
+
+ $optiongroups[] = $og;
+ }
+ $context['optiongroups'] = $optiongroups;
+ $context['hideLabel'] = $this->_hiddenLabel;
+
+ return $context;
+ }
}
*
* HTML class for a select type element with options containing link
*
+ * @deprecated since 3.2
* @package core_form
* @category form
* @copyright 2008 Nicolas Connault <nicolasconnault@gmail.com>
* @param bool $linkdata data to be posted
*/
public function __construct($elementName=null, $elementLabel=null, $options=null, $attributes=null, $linkdata=null) {
+ debugging('Element type selectwithlink is deprecated. Use 2 elements.', DEBUG_DEVELOPER);
if (!empty($linkdata['link']) && !empty($linkdata['label'])) {
$this->_link = $linkdata['link'];
$this->_linklabel = $linkdata['label'];
*/
require_once("HTML/QuickForm/static.php");
+require_once(__DIR__ . '/../outputcomponents.php');
/**
* Text type element
* @copyright 2006 Jamie Pratt <me@jamiep.org>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
-class MoodleQuickForm_static extends HTML_QuickForm_static{
+class MoodleQuickForm_static extends HTML_QuickForm_static implements templatable {
/** @var string Form element type */
var $_elementTemplateType='static';
function getElementTemplateType(){
return $this->_elementTemplateType;
}
+
+ public function export_for_template(renderer_base $output) {
+ $context = [];
+ $context['frozen'] = $this->_flagFrozen;
+ foreach ($this->getAttributes() as $name => $value) {
+ $context[$name] = $value;
+ }
+ $context['html'] = $this->toHtml();
+ return $context;
+ }
}
*/
require_once("HTML/QuickForm/submit.php");
+require_once(__DIR__ . '/../outputcomponents.php');
/**
* submit type form element
* @copyright 2006 Jamie Pratt <me@jamiep.org>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
-class MoodleQuickForm_submit extends HTML_QuickForm_submit {
+class MoodleQuickForm_submit extends HTML_QuickForm_submit implements templatable {
/**
* constructor
*
$this->_flagFrozen = true;
}
+ public function export_for_template(renderer_base $output) {
+ $context = [];
+ $context['frozen'] = $this->_flagFrozen;
+ foreach ($this->getAttributes() as $name => $value) {
+ $context[$name] = $value;
+ }
+ if ($this->getName() == 'cancel') {
+ $context['iscancel'] = true;
+ }
+ return $context;
+ }
}
*
* Contains HTML class for a submitting to link
*
+ * @deprecated since 3.2
* @package core_form
* @copyright 2006 Jamie Pratt <me@jamiep.org>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @param string $attributes (optional) Either a typical HTML attribute string or an associative array
*/
public function __construct($elementName=null, $value=null, $attributes=null) {
+ debugging('Element type submitlink is deprecated.', DEBUG_DEVELOPER);
parent::__construct($elementName, $value, $attributes);
}
--- /dev/null
+<div>
+<textarea id="{{id}}" name="{{name}}[text]" rows="{{rows}}" cols="{{cols}}" spellcheck="true" {{#changelistener}} onblur="{{onblur}}"
+ onchange="{{onchange}}" {{/changelistener}}>{{text}}</textarea>
+</div>
+<div>
+ {{^onlyoneformat}}
+ <select name="{{name}}[format]" id="menu{{name}}format">
+ {{#formats}}
+ <option value="{{value}}" {{#selected}}selected{{/selected}}>{{text}}</option>
+ {{/formats}}
+ </select>
+ {{/onlyoneformat}}
+ {{#onlyoneformat}}
+ <input name="{{name}}[format]" type="hidden" value="{{format}}"/>
+ {{/onlyoneformat}}
+</div>
\ No newline at end of file
*/
require_once("HTML/QuickForm/text.php");
+require_once(__DIR__ . '/../outputcomponents.php');
/**
* Text type form element
* @copyright 2006 Jamie Pratt <me@jamiep.org>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
-class MoodleQuickForm_text extends HTML_QuickForm_text{
+class MoodleQuickForm_text extends HTML_QuickForm_text implements templatable {
+
/** @var string html for help button, if empty then no help */
var $_helpbutton='';
function getHelpButton(){
return $this->_helpbutton;
}
+
+ public function export_for_template(renderer_base $output) {
+ $context = [];
+ $context['frozen'] = $this->_flagFrozen;
+ foreach ($this->getAttributes() as $name => $value) {
+ $context[$name] = $value;
+ }
+ $context['hideLabel'] = $this->_hiddenLabel;
+ return $context;
+ }
}
*/
require_once('HTML/QuickForm/textarea.php');
+require_once(__DIR__ . '/../outputcomponents.php');
/**
* Textarea type form element
* @copyright 2006 Jamie Pratt <me@jamiep.org>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
-class MoodleQuickForm_textarea extends HTML_QuickForm_textarea{
+class MoodleQuickForm_textarea extends HTML_QuickForm_textarea implements templatable {
/** @var string Need to store id of form as we may need it for helpbutton */
var $_formid = '';
return 'default';
}
}
+
+ public function export_for_template(renderer_base $output) {
+ $context = [];
+ $context['frozen'] = $this->_flagFrozen;
+ foreach ($this->getAttributes() as $name => $value) {
+ $context[$name] = $value;
+ }
+ $context['hideLabel'] = $this->_hiddenLabel;
+ return $context;
+ }
}
*/
require_once("HTML/QuickForm/text.php");
+require_once(__DIR__ . '/../outputcomponents.php');
/**
* url type form element
* @copyright 2009 Dongsheng Cai <dongsheng@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
-class MoodleQuickForm_url extends HTML_QuickForm_text{
+class MoodleQuickForm_url extends HTML_QuickForm_text implements templatable {
/** @var string html for help button, if empty then no help */
var $_helpbutton='';
if (!isset($this->_options['usefilepicker'])) {
$this->_options['usefilepicker'] = true;
}
+
parent::__construct($elementName, $elementLabel, $attributes);
+ $this->_type = 'url';
}
/**
* @return string
*/
function toHtml(){
- global $PAGE, $OUTPUT;
+
$id = $this->_attributes['id'];
$elname = $this->_attributes['name'];
return $str;
}
+ // print out file picker
+ $str .= $this->getFilePickerHTML();
+
+ return $str;
+ }
+
+ function getFilePickerHTML() {
+ global $PAGE, $OUTPUT;
+
+ $str = '';
$client_id = uniqid();
$args = new stdClass();
if (count($options->repositories) > 0) {
$straddlink = get_string('choosealink', 'repository');
$str .= <<<EOD
-<button id="filepicker-button-js-{$client_id}" class="visibleifjs">
+<button id="filepicker-button-js-{$client_id}" class="visibleifjs btn btn-secondary">
$straddlink
</button>
EOD;
return 'default';
}
}
+
+ public function export_for_template(renderer_base $output) {
+ $context = [];
+ $context['frozen'] = $this->_flagFrozen;
+ foreach ($this->getAttributes() as $name => $value) {
+ $context[$name] = $value;
+ }
+ $context['filepickerhtml'] = $this->getFilePickerHTML();
+ return $context;
+ }
}
*/
function getValidationScript()
{
+ global $PAGE;
+
if (empty($this->_rules) || $this->clientvalidation === false) {
return '';
}
unset($element);
$js = '
-<script type="text/javascript">
-//<![CDATA[
var skipClientValidation = false;
-(function() {
-
- function qf_errorHandler(element, _qfMsg, escapedName) {
- div = element.parentNode;
- if ((div == undefined) || (element.name == undefined)) {
- //no checking can be done for undefined elements so let server handle it.
- return true;
- }
+require(["core/event", "jquery"], function(Event, $) {
- if (_qfMsg != \'\') {
- var errorSpan = document.getElementById(\'id_error_\' + escapedName);
- if (!errorSpan) {
- errorSpan = document.createElement("span");
- errorSpan.id = \'id_error_\' + escapedName;
- errorSpan.className = "error";
- element.parentNode.insertBefore(errorSpan, element.parentNode.firstChild);
- document.getElementById(errorSpan.id).setAttribute(\'TabIndex\', \'0\');
- document.getElementById(errorSpan.id).focus();
- }
+ function qf_errorHandler(element, _qfMsg, escapedName) {
+ var event = $.Event(Event.Events.FORM_FIELD_VALIDATION);
+ $(element).trigger(event, _qfMsg);
+ if (event.isDefaultPrevented()) {
+ return _qfMsg == \'\';
+ } else {
+ // Legacy mforms.
+ var div = element.parentNode;
+
+ if ((div == undefined) || (element.name == undefined)) {
+ // No checking can be done for undefined elements so let server handle it.
+ return true;
+ }
+
+ if (_qfMsg != \'\') {
+ var errorSpan = document.getElementById(\'id_error_\' + escapedName);
+ if (!errorSpan) {
+ errorSpan = document.createElement("span");
+ errorSpan.id = \'id_error_\' + escapedName;
+ errorSpan.className = "error";
+ element.parentNode.insertBefore(errorSpan, element.parentNode.firstChild);
+ document.getElementById(errorSpan.id).setAttribute(\'TabIndex\', \'0\');
+ document.getElementById(errorSpan.id).focus();
+ }
- while (errorSpan.firstChild) {
- errorSpan.removeChild(errorSpan.firstChild);
- }
+ while (errorSpan.firstChild) {
+ errorSpan.removeChild(errorSpan.firstChild);
+ }
- errorSpan.appendChild(document.createTextNode(_qfMsg.substring(3)));
+ errorSpan.appendChild(document.createTextNode(_qfMsg.substring(3)));
- if (div.className.substr(div.className.length - 6, 6) != " error"
- && div.className != "error") {
- div.className += " error";
- linebreak = document.createElement("br");
- linebreak.className = "error";
- linebreak.id = \'id_error_break_\' + escapedName;
- errorSpan.parentNode.insertBefore(linebreak, errorSpan.nextSibling);
- }
+ if (div.className.substr(div.className.length - 6, 6) != " error"
+ && div.className != "error") {
+ div.className += " error";
+ linebreak = document.createElement("br");
+ linebreak.className = "error";
+ linebreak.id = \'id_error_break_\' + escapedName;
+ errorSpan.parentNode.insertBefore(linebreak, errorSpan.nextSibling);
+ }
- return false;
- } else {
- var errorSpan = document.getElementById(\'id_error_\' + escapedName);
- if (errorSpan) {
- errorSpan.parentNode.removeChild(errorSpan);
- }
- var linebreak = document.getElementById(\'id_error_break_\' + escapedName);
- if (linebreak) {
- linebreak.parentNode.removeChild(linebreak);
- }
+ return false;
+ } else {
+ var errorSpan = document.getElementById(\'id_error_\' + escapedName);
+ if (errorSpan) {
+ errorSpan.parentNode.removeChild(errorSpan);
+ }
+ var linebreak = document.getElementById(\'id_error_break_\' + escapedName);
+ if (linebreak) {
+ linebreak.parentNode.removeChild(linebreak);
+ }
- if (div.className.substr(div.className.length - 6, 6) == " error") {
- div.className = div.className.substr(0, div.className.length - 6);
- } else if (div.className == "error") {
- div.className = "";
- }
+ if (div.className.substr(div.className.length - 6, 6) == " error") {
+ div.className = div.className.substr(0, div.className.length - 6);
+ } else if (div.className == "error") {
+ div.className = "";
+ }
- return true;
- }
- }';
+ return true;
+ } // End if.
+ } // End if.
+ } // End function.
+ ';
$validateJS = '';
foreach ($test as $elementName => $jsandelement) {
// Fix for bug displaying errors for elements in a group
ev.preventDefault();
}
});
-})();
-//]]>
-</script>';
- return $js;
+
+});
+';
+
+ $PAGE->requires->js_amd_inline($js);
+ return '';
} // end func getValidationScript
/**
* @param string $error error message to display
*/
function startGroup(&$group, $required, $error){
+ global $OUTPUT;
+
// Make sure the element has an id.
$group->_generateId();
// Update the ID.
$group->updateAttributes(array('id' => $groupid));
- if (method_exists($group, 'getElementTemplateType')){
- $html = $this->_elementTemplates[$group->getElementTemplateType()];
- }else{
- $html = $this->_elementTemplates['default'];
+ $html = $OUTPUT->mform_element($group, $required, $error, false);
+ $fromtemplate = !empty($html);
+ if (!$fromtemplate) {
+ if (method_exists($group, 'getElementTemplateType')) {
+ $html = $this->_elementTemplates[$group->getElementTemplateType()];
+ } else {
+ $html = $this->_elementTemplates['default'];
+ }
+ if (isset($this->_advancedElements[$group->getName()])) {
+ $html = str_replace(' {advanced}', ' advanced', $html);
+ $html = str_replace('{advancedimg}', $this->_advancedHTML, $html);
+ } else {
+ $html = str_replace(' {advanced}', '', $html);
+ $html = str_replace('{advancedimg}', '', $html);
+ }
+ if (method_exists($group, 'getHelpButton')) {
+ $html = str_replace('{help}', $group->getHelpButton(), $html);
+ } else {
+ $html = str_replace('{help}', '', $html);
+ }
+ $html = str_replace('{id}', $group->getAttribute('id'), $html);
+ $html = str_replace('{name}', $group->getName(), $html);
+ $html = str_replace('{type}', 'fgroup', $html);
+ $html = str_replace('{class}', $group->getAttribute('class'), $html);
+ $emptylabel = '';
+ if ($group->getLabel() == '') {
+ $emptylabel = 'femptylabel';
+ }
+ $html = str_replace('{emptylabel}', $emptylabel, $html);
}
-
- if (isset($this->_advancedElements[$group->getName()])){
- $html =str_replace(' {advanced}', ' advanced', $html);
- $html =str_replace('{advancedimg}', $this->_advancedHTML, $html);
- } else {
- $html =str_replace(' {advanced}', '', $html);
- $html =str_replace('{advancedimg}', '', $html);
- }
- if (method_exists($group, 'getHelpButton')){
- $html =str_replace('{help}', $group->getHelpButton(), $html);
- }else{
- $html =str_replace('{help}', '', $html);
- }
- $html = str_replace('{id}', $group->getAttribute('id'), $html);
- $html =str_replace('{name}', $group->getName(), $html);
- $html =str_replace('{type}', 'fgroup', $html);
- $html =str_replace('{fieldtype}', 'group', $html);
- $html =str_replace('{class}', $group->getAttribute('class'), $html);
- $emptylabel = '';
- if ($group->getLabel() == '') {
- $emptylabel = 'femptylabel';
- }
- $html = str_replace('{emptylabel}', $emptylabel, $html);
-
- $this->_templates[$group->getName()]=$html;
+ $this->_templates[$group->getName()] = $html;
// Fix for bug in tableless quickforms that didn't allow you to stop a
// fieldset before a group of elements.
// if the element name indicates the end of a fieldset, close the fieldset
- if ( in_array($group->getName(), $this->_stopFieldsetElements)
- && $this->_fieldsetsOpen > 0
- ) {
+ if (in_array($group->getName(), $this->_stopFieldsetElements) && $this->_fieldsetsOpen > 0) {
$this->_html .= $this->_closeFieldsetTemplate;
$this->_fieldsetsOpen--;
}
- parent::startGroup($group, $required, $error);
+ if (!$fromtemplate) {
+ parent::startGroup($group, $required, $error);
+ } else {
+ $this->_html .= $html;
+ }
}
/**
* @param string $error error message to display
*/
function renderElement(&$element, $required, $error){
+ global $OUTPUT;
+
// Make sure the element has an id.
$element->_generateId();
- //adding stuff to place holders in template
- //check if this is a group element first
- if (($this->_inGroup) and !empty($this->_groupElementTemplate)) {
- // so it gets substitutions for *each* element
- $html = $this->_groupElementTemplate;
- }
- elseif (method_exists($element, 'getElementTemplateType')){
- $html = $this->_elementTemplates[$element->getElementTemplateType()];
- }else{
- $html = $this->_elementTemplates['default'];
- }
- if (isset($this->_advancedElements[$element->getName()])){
- $html = str_replace(' {advanced}', ' advanced', $html);
- $html = str_replace(' {aria-live}', ' aria-live="polite"', $html);
- } else {
- $html = str_replace(' {advanced}', '', $html);
- $html = str_replace(' {aria-live}', '', $html);
- }
- if (isset($this->_advancedElements[$element->getName()])||$element->getName() == 'mform_showadvanced'){
- $html =str_replace('{advancedimg}', $this->_advancedHTML, $html);
+ $html = $OUTPUT->mform_element($element, $required, $error, false);
+ $fromtemplate = !empty($html);
+ if (!$fromtemplate) {
+ // Adding stuff to place holders in template
+ // check if this is a group element first.
+ if (($this->_inGroup) and !empty($this->_groupElementTemplate)) {
+ // So it gets substitutions for *each* element.
+ $html = $this->_groupElementTemplate;
+ } else if (method_exists($element, 'getElementTemplateType')){
+ $html = $this->_elementTemplates[$element->getElementTemplateType()];
+ } else {
+ $html = $this->_elementTemplates['default'];
+ }
+ if (isset($this->_advancedElements[$element->getName()])){
+ $html = str_replace(' {advanced}', ' advanced', $html);
+ $html = str_replace(' {aria-live}', ' aria-live="polite"', $html);
+ } else {
+ $html = str_replace(' {advanced}', '', $html);
+ $html = str_replace(' {aria-live}', '', $html);
+ }
+ if (isset($this->_advancedElements[$element->getName()]) || $element->getName() == 'mform_showadvanced'){
+ $html = str_replace('{advancedimg}', $this->_advancedHTML, $html);
+ } else {
+ $html = str_replace('{advancedimg}', '', $html);
+ }
+ $html = str_replace('{id}', 'fitem_' . $element->getAttribute('id'), $html);
+ $html = str_replace('{type}', 'f' . $element->getType(), $html);
+ $html = str_replace('{name}', $element->getName(), $html);
+ $html = str_replace('{class}', $element->getAttribute('class'), $html);
+ $emptylabel = '';
+ if ($element->getLabel() == '') {
+ $emptylabel = 'femptylabel';
+ }
+ $html = str_replace('{emptylabel}', $emptylabel, $html);
+ if (method_exists($element, 'getHelpButton')) {
+ $html = str_replace('{help}', $element->getHelpButton(), $html);
+ } else {
+ $html = str_replace('{help}', '', $html);
+ }
} else {
- $html =str_replace('{advancedimg}', '', $html);
- }
- $html =str_replace('{id}', 'fitem_' . $element->getAttribute('id'), $html);
- $html =str_replace('{type}', 'f'.$element->getType(), $html);
- $html =str_replace('{fieldtype}', $element->getType(), $html);
- $html =str_replace('{name}', $element->getName(), $html);
- $html =str_replace('{class}', $element->getAttribute('class'), $html);
- $emptylabel = '';
- if ($element->getLabel() == '') {
- $emptylabel = 'femptylabel';
- }
- $html = str_replace('{emptylabel}', $emptylabel, $html);
- if (method_exists($element, 'getHelpButton')){
- $html = str_replace('{help}', $element->getHelpButton(), $html);
- }else{
- $html = str_replace('{help}', '', $html);
-
+ if ($this->_inGroup) {
+ $this->_groupElementTemplate = $html;
+ }
}
if (($this->_inGroup) and !empty($this->_groupElementTemplate)) {
$this->_groupElementTemplate = $html;
- }
- elseif (!isset($this->_templates[$element->getName()])) {
+ } else if (!isset($this->_templates[$element->getName()])) {
$this->_templates[$element->getName()] = $html;
}
- parent::renderElement($element, $required, $error);
+ if (!$fromtemplate) {
+ parent::renderElement($element, $required, $error);
+ } else { // CRAZZY!
+ $this->_html .= $html;
+ }
}
/**
return $this->render_from_template('core/login', $context);
}
+ /**
+ * Renders an mform element from a template.
+ *
+ * @param HTML_QuickForm_element $element element
+ * @param bool $required if input is required field
+ * @param string $error error message to display
+ * @param bool $ingroup True if this element is rendered as part of a group
+ * @return mixed string|bool
+ */
+ public function mform_element($element, $required, $error, $ingroup) {
+ $templatename = 'core_form/element-' . $element->getType();
+ if ($ingroup) {
+ $templatename .= "-inline";
+ }
+ try {
+ // We call this to generate a file not found exception if there is no template.
+ // We don't want to call export_for_template if there is no template.
+ core\output\mustache_template_finder::get_template_filepath($templatename);
+
+ if ($element instanceof templatable) {
+ $elementcontext = $element->export_for_template($this);
+
+ $helpbutton = '';
+ if (method_exists($element, 'getHelpButton')) {
+ $helpbutton = $element->getHelpButton();
+ }
+ $label = $element->getLabel();
+ if (method_exists($element, 'getText')) {
+ $label .= ' ' . $element->getText();
+ }
+
+ $context = array(
+ 'element' => $elementcontext,
+ 'label' => $label,
+ 'required' => $required,
+ 'helpbutton' => $helpbutton,
+ 'error' => $error
+ );
+ return $this->render_from_template($templatename, $context);
+ }
+ } catch (Exception $e) {
+ // No template for this element.
+ return false;
+ }
+ }
}
/**
.pagingbar .thispage {
font-weight: bold;
}
+img.userpicture {
+ margin-right: 0.5rem;
+}
img.resize {
height: 1em;
width: 1em;
}
+.action-menu .dropdown-toggle {
+ margin-right: 0.5rem;
+ text-decoration: none;
+}
.action-menu {
white-space: nowrap;
}
width: 16px;
height: 16px;
box-sizing: content-box;
+}
+.action-menu .dropdown-menu img {
padding-right: 0.5rem;
}
.action-menu .userpicture {
/* course.less */
/* COURSE CONTENT */
+.section-modchooser-link img {
+ margin-right: 0.5rem;
+ width: 16px;
+ height: 16px;
+}
.section_add_menus {
text-align: right;
clear: both;
*
*/
-form {
- margin: 0;
-}
-.mform fieldset .advancedbutton {
- text-align: right;
-}
.jsenabled .mform .containsadvancedelements .advanced {
display: none;
}
.mform .containsadvancedelements .advanced.show {
display: block;
}
-.mform fieldset.group {
- margin-bottom: 0
-}
-.mform fieldset.error {
- border: 1px solid $state-danger-text;
-}
-.mform span.error,
#adminsettings span.error {
display: inline-block;
border: 1px solid $state-danger-border;
.jsenabled .mform .collapsed .fcontainer {
display: none;
}
-
-.mform .fitem .fitemtitle div {
- display: inline;
-}
-#adminsettings .error,
-.mform .error {
+#adminsettings .error {
color: $state-danger-text;
}
-.mform .fdescription.required {
- margin-left: $display1-size;
-}
-.mform .fpassword .unmask {
- display: inline-block;
- margin-left: 0.5em;
- & > input {
- margin: 0;
- }
- & > label {
- display: inline-block;
- }
-}
-.mform label {
- display: inline-block;
-}
-
-.mform .iconhelp {
- margin-left: 4px;
-}
-.mform .ftextarea #id_alltext {
- width: 100%;
-}
.mform ul.file-list {
padding: 0;
margin: 0;
.mform label .adv {
cursor: help;
}
-.mform .fcheckbox input {
- margin-left: 0;
-}
-.mform .fcheckbox > span,
-.mform .fradio > span,
-.mform .fgroup > span {
- display: inline-block;
- margin-top: 5px;
-}
-.mform .fitem fieldset.fgroup label,
-.mform fieldset.fdate_selector label {
- display: inline;
- float: none;
- width: auto;
-}
-.mform .ftags label.accesshide {
- display: block;
- position: static;
-}
-.mform .ftags select {
- margin-bottom: 0.7em;
- min-width: 22em;
-}
-.mform .helplink img {
- margin: 0 .45em;
- padding: 0;
-}
-.mform legend .helplink img {
- margin: 0 .2em;
-}
-.singleselect label {
- margin-right: .3em;
-}
/*rtl:ignore*/
input#id_externalurl {
direction: ltr;
}
// Copying in Bootstrap styles.
-.form-item,
-.mform .fitem {
+.form-item {
margin-bottom: 10px;
// Theres's a mysterious extra 10px inside this item,
// so reduce margin by 10px from 20px standard to compensate.
}
.form-item .form-setting,
.form-item .form-description,
-.mform .fitem .felement,
#page-mod-forum-search .c1 .form-horizontal {
@extend .controls;
}
// uneditable looks ugly, styling both as form help is fairly
// subtle in it's impact. Going for the latter as the best option.
.form-item .form-description,
-.felement.fstatic {
+.no-felement.fstatic {
@extend .text-muted;
padding-top: 5px;
}
.form-item .form-description {
padding-top: 0;
}
-.fitem .fstaticlabel {
+.no-fitem .fstaticlabel {
font-weight: bold;
}
border: 0;
border-bottom: 1px solid #e5e5e5;
}
-.mform legend a,
-.mform legend a:hover {
- color: $body-color;
- text-decoration: none;
-}
// I think this could be avoided (or at least tidied up) ifr
// we used HTML5 input types like url, phone, email, number etc.
display: inline-block;
}
-// Checkbox labels. Bootstrap puts the associated checkbox inside the label.
-// Moodle puts it beside the label, so we need to make it inline-block
-// to keep it on the same horizontal level.
-input[type="radio"] + label,
-input[type="checkbox"] + label {
- display: inline;
- padding-left: 0.2em;
-}
-input[type="radio"],
-input[type="checkbox"] {
- margin-top: -4px; // Dodgy hack, must be better way.
- margin-right: 7px;
-}
-.singleselect {
- display: inline-block;
- form,
- select{
- margin: 0;
- }
-}
.form-item .form-label label {
margin-bottom: 0;
}
-.felement.ffilepicker {
- margin-top: 5px;
-}
div#dateselector-calendar-panel {
z-index: 3100; /* Set higher than the z-index of the filemanager - see MDL-39047. */
}
/**
* Show the labels above text editors and file managers except on wide screens.
*/
-#region-main .mform:not(.unresponsive) .fitem .fitemtitle label {
- font-weight: bold;
-}
-@mixin makeFormsVertical() {
- #region-main .mform:not(.unresponsive) {
- .fitem {
- .fitemtitle {
- display: block;
- margin-top: 4px;
- margin-bottom: 4px;
- text-align: left;
- width: 100%;
- }
- .felement {
- margin-left: 0;
- width: 100%;
- float: left;
- padding-left: 0;
- padding-right: 0;
- }
- .fstatic:empty {
- display: none;
- }
- .fcheckbox > span,
- .fradio > span,
- .fgroup > span {
- margin-top: 4px;
- }
-
- }
- .femptylabel {
- .fitemtitle {
- display: inline-block;
- width: auto;
- margin-right: 8px;
- }
- .felement {
- display: inline-block;
- margin-top: 4px;
- padding-top: 5px;
- width: auto;
- }
- }
- .fitem_fcheckbox{
- .fitemtitle,
- .felement {
- display: inline-block;
- width: auto;
- }
- .felement {
- padding: 6px;
- }
- }
- }
-}
-
-/**
- * Make forms vertical when the screen is less than 1200px;
- */
-@media (max-width: 1199px) {
- body {
- @include makeFormsVertical();
- }
-}
-
-/**
- * Make forms vertical when the screen is less than 1474px AND both side-pre and side-post contain blocks.
- * This is an extra special media rule.
- * It causes forms to show vertically when the screen size is calculated as:
- * 1199px + (1199px * 23%)
- * Where 23% is the width of span3
- * Full calculation is:
- * $maxWidthForVerticalForms: 1199px * (unit((($fluidGridColumnWidth1200 * 3) + ($fluidGridGutterWidth * (3 - 1)))) / 100) + 1199px;
- */
-$maxWidthForVerticalForms: 1474px;
-@media (max-width: $maxWidthForVerticalForms) {
- .used-region-side-pre.used-region-side-post {
- @include makeFormsVertical();
- }
-}
-
/* Section and module editing forms contain special JS components for the
availability system (if enabled). */
#fitem_id_availabilityconditionsjson {
}
}
-/* Revert to the non-fixed width where a textarea has the number of columns
- specified, or an input has it's size specified. */
-textarea[cols],
-input[size] {
- width: auto;
-}
-
/* Custom styles for autocomplete form element */
.form-autocomplete-selection {
margin: 0.2em;
overflow: auto;
margin: 0px;
padding: 0px;
- margin-top: -0.2em;
+ margin-top: 0.4em;
z-index: 1;
}
.form-autocomplete-suggestions li {
.form-autocomplete-downarrow {
color: $body-color;
position: relative;
- top: -0.3em;
+ top: 0.2em;
left: -1.5em;
cursor: pointer;
}
padding: 0.5em;
font-size: large;
}
+
+select[multiple] {
+ overflow: auto;
+}
--- /dev/null
+{{!
+ This file is part of Moodle - http://moodle.org/
+
+ Moodle is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ Moodle is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with Moodle. If not, see <http://www.gnu.org/licenses/>.
+}}
+{{!
+ @template core/form_autocomplete_input
+
+ Moodle template for the input field in an autocomplate form element.
+
+ Classes required for JS:
+ * none
+
+ Data attributes required for JS:
+ * none
+
+ Context variables required for this template:
+ * inputId The dom id of this input field.
+ * suggestionsId The dom id of the suggestions list.
+ * selectionId The dom id of the current selection list.
+ * downArrowId The dom id of the down arrow to open the suggestions.
+ * placeholder The place holder text when the field is empty
+
+ Example context (json):
+ { "inputID": 1, "suggestionsId": 2, "selectionId": 3, "downArrowId": 4, "placeholder": "Select something" }
+}}
+{{#showSuggestions}}
+<input type="text" id="{{inputId}}" class="form-control col-md-4" list="{{suggestionsId}}" placeholder="{{placeholder}}" role="combobox" aria-expanded="false" autocomplete="off" autocorrect="off" autocapitalize="off" aria-autocomplete="list" aria-owns="{{suggestionsId}} {{selectionId}}"/><span class="form-autocomplete-downarrow" id="{{downArrowId}}">▼</span>
+{{/showSuggestions}}
+{{^showSuggestions}}
+<input type="text" id="{{inputId}}" placeholder="{{placeholder}}" role="textbox" aria-owns="{{selectionId}}"/>
+{{/showSuggestions}}
--- /dev/null
+{{!
+ This file is part of Moodle - http://moodle.org/
+
+ Moodle is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ Moodle is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with Moodle. If not, see <http://www.gnu.org/licenses/>.
+}}
+{{!
+ @template core/form_autocomplete_selection
+
+ Moodle template for the currently selected items in an autocomplate form element.
+
+ Classes required for JS:
+ * none
+
+ Data attributes required for JS:
+ * none
+
+ Context variables required for this template:
+ * multiple True if this field allows multiple selections
+ * selectionId The dom id of the current selection list.
+ * items List of items with label and value fields.
+ * noSelectionString String to use when no items are selected
+
+ Example context (json):
+ { "multiple": true, "selectionId": 1, "items": [
+ { "label": "Item label with <strong>tags</strong>", "value": "5" },
+ { "label": "Another item label with <strong>tags</strong>", "value": "4" }
+ ], "noSelectionString": "No selection" }
+}}
+<div class="form-autocomplete-selection {{#multiple}}form-autocomplete-multiple{{/multiple}}" id="{{selectionId}}" role="list" aria-atomic="true" {{#multiple}}tabindex="0" aria-multiselectable="true"{{/multiple}}>
+<span class="accesshide">{{#str}}selecteditems, form{{/str}}</span>
+ {{#items}}
+ <span role="listitem" data-value="{{value}}" aria-selected="true" class="tag tag-info">
+ {{#multiple}}<span aria-hidden="true">× </span>{{/multiple}}{{{label}}}
+ </span>
+ {{/items}}
+ {{^items}}
+ <span>{{noSelectionString}}</span>
+ {{/items}}
+</div>
+</div>
--- /dev/null
+<div>
+<textarea id="{{id}}" name="{{name}}[text]" class="form-control" rows="{{rows}}" cols="{{cols}}" spellcheck="true" {{#changelistener}} onblur="{{onblur}}"
+ onchange="{{onchange}}" {{/changelistener}}>{{text}}</textarea>
+</div>
+<div>
+ {{^onlyoneformat}}
+ <select name="{{name}}[format]" id="menu{{name}}format" class="custom-select">
+ {{#formats}}
+ <option value="{{value}}" {{#selected}}selected{{/selected}}>{{text}}</option>
+ {{/formats}}
+ </select>
+ {{/onlyoneformat}}
+ {{#onlyoneformat}}
+ <input name="{{name}}[format]" id="menu{{name}}format" type="hidden" value="{{format}}"/>
+ {{/onlyoneformat}}
+</div>
\ No newline at end of file
--- /dev/null
+<input type="hidden" name="{{element.name}}"
+ value="{{element.value}}">
+{{> core_form/element-checkbox-inline }}
\ No newline at end of file
--- /dev/null
+<input type="hidden" name="{{element.name}}"
+ value="{{element.value}}">
+{{> core_form/element-checkbox }}
\ No newline at end of file
--- /dev/null
+<div class="form-group row {{#error}}has-danger{{/error}}">
+ <label class="col-md-3 col-form-label" for="{{element.id}}">
+ {{{label}}} {{{helpbutton}}}
+ </label>
+ <div class="col-md-9 form-inline">
+ <select class="custom-select {{#error}}form-control-danger{{/error}}" name="{{element.name}}"
+ id="{{element.id}}"
+ {{#element.multiple}}multiple{{/element.multiple}}
+ {{#element.frozen}}readonly disabled{{/element.frozen}}
+ {{#error}}
+ autofocus aria-describedby="id_error_{{element.name}}"
+ {{/error}}
+ {{#element.attributes}}
+ {{name}}={{#quote}}{{value}}{{/quote}} ddd
+ {{/element.attributes}}
+ >
+ {{#element.options}}
+ <option value="{{value}}" {{#selected}}selected{{/selected}}>{{text}}</option>
+ {{/element.options}}
+ </select>
+ <div class="form-control-feedback" id="id_error_{{element.name}}" {{^error}} style="display: none;"{{/error}}>
+ {{{error}}}
+ </div>
+ </div>
+</div>
+{{#js}}
+require(['jquery', 'core/event'], function($, Event) {
+ var element = document.getElementById('{{element.id}}');
+ $(element).on(Event.Events.FORM_FIELD_VALIDATION, function(event, msg) {
+ event.preventDefault();
+ var parent = $(element).closest('.form-group');
+ var feedback = parent.find('.form-control-feedback');
+ if (msg !== '') {
+ parent.addClass('has-danger');
+ $(element).addClass('form-control-danger');
+ $(element).attr('aria-describedby', $(element).attr('id') + '-feedback');
+ feedback.html(msg);
+ feedback.show();
+ } else {
+ parent.removeClass('has-danger');
+ $(element).removeClass('form-control-danger');
+ $(element).attr('aria-describedby', '');
+ feedback.hide();
+ }
+ });
+});
+{{/js}}
\ No newline at end of file
--- /dev/null
+ <div class="form-group">
+ <label class="col-md-3 col-form-label {{#element.hideLabel}}sr-only{{/element.hideLabel}}" for="{{element.id}}">
+ {{{label}}} {{{helpbutton}}}
+ </label>
+ <button {{#element.frozen}}readonly{{/element.frozen}}
+ class="btn btn-secondary"
+ name="{{element.name}}"
+ id="{{element.id}}" >
+ {{{element.value}}}
+ </button>
+ </div>
\ No newline at end of file
--- /dev/null
+<div class="form-group row">
+ <label class="col-md-3 col-form-label {{#element.hideLabel}}sr-only{{/element.hideLabel}}" for="{{element.id}}">
+ {{{label}}} {{{helpbutton}}}
+ </label>
+ <div class="col-md-9 form-inline">
+ <button {{#element.frozen}}readonly{{/element.frozen}}
+ class="btn btn-secondary m-l-0"
+ name="{{element.name}}"
+ id="{{element.id}}"
+ {{#error}}
+ autofocus aria-describedby="id_error_{{element.name}}"
+ {{/error}} >
+ {{{element.value}}}
+ </button>
+ </div>
+</div>
--- /dev/null
+<label class="form-check-inline {{#error}}has-danger{{/error}}">
+<input type="checkbox" name="{{element.name}}"
+ id="{{element.id}}" value="{{element.value}}" size="{{element.size}}"
+ {{#element.frozen}}readonly disabled{{/element.frozen}}
+ {{#error}}
+ autofocus aria-describedby="id_error_{{element.name}}"
+ {{/error}} >
+ {{{label}}} {{{helpbutton}}}
+</label>
+<span class="form-control-feedback" id="id_error_{{element.name}}" {{^error}} style="display: none;"{{/error}}>
+ {{{error}}}
+</span>
+{{#js}}
+require(['jquery', 'core/event'], function($, Event) {
+ var element = document.getElementById('{{element.id}}');
+ $(element).on(Event.Events.FORM_FIELD_VALIDATION, function(event, msg) {
+ event.preventDefault();
+ var parent = $(element).closest('.form-group');
+ var feedback = parent.find('.form-control-feedback');
+ if (msg !== '') {
+ parent.addClass('has-danger');
+ $(element).attr('aria-describedby', $(element).attr('id') + '-feedback');
+ feedback.html(msg);
+ feedback.show();
+ } else {
+ parent.removeClass('has-danger');
+ $(element).attr('aria-describedby', '');
+ feedback.hide();
+ }
+ });
+});
+{{/js}}
\ No newline at end of file
--- /dev/null
+<div class="form-group row {{#error}}has-danger{{/error}}">
+ <div class="col-md-9 push-md-3 checkbox">
+ <label>
+ <input type="checkbox" name="{{element.name}}"
+ id="{{element.id}}" value="{{element.value}}" size="{{element.size}}"
+ {{#element.frozen}}readonly disabled{{/element.frozen}}
+ {{#error}}
+ autofocus aria-describedby="id_error_{{element.name}}"
+ {{/error}} >
+ {{{label}}} {{{helpbutton}}}
+ </label>
+ <div class="form-control-feedback" id="id_error_{{element.name}}" {{^error}} style="display: none;"{{/error}}>
+ {{{error}}}
+ </div>
+ </div>
+</div>
+{{#js}}
+require(['jquery', 'core/event'], function($, Event) {
+ var element = document.getElementById('{{element.id}}');
+ $(element).on(Event.Events.FORM_FIELD_VALIDATION, function(event, msg) {
+ event.preventDefault();
+ var parent = $(element).closest('.form-group');
+ var feedback = parent.find('.form-control-feedback');
+ if (msg !== '') {
+ parent.addClass('has-danger');
+ $(element).attr('aria-describedby', $(element).attr('id') + '-feedback');
+ feedback.html(msg);
+ feedback.show();
+ } else {
+ parent.removeClass('has-danger');
+ $(element).attr('aria-describedby', '');
+ feedback.hide();
+ }
+ });
+});
+{{/js}}
\ No newline at end of file
--- /dev/null
+<div class="form-group row {{#error}}has-danger{{/error}}">
+ <label class="col-md-3 col-form-label" for="{{element.id}}">
+ {{{label}}} {{{helpbutton}}}
+ </label>
+ <div class="col-md-9 form-inline fdate_selector">
+ {{#element.elements}}
+ {{{.}}}
+ {{/element.elements}}
+ </div>
+</div>
\ No newline at end of file
--- /dev/null
+<div class="form-group row {{#error}}has-danger{{/error}}">
+ <label class="col-md-3 col-form-label" for="{{element.id}}">
+ {{{label}}} {{{helpbutton}}}
+ </label>
+ <div class="col-md-9 form-inline fdate_time_selector">
+ {{#element.elements}}
+ {{{.}}}
+ {{/element.elements}}
+ </div>
+ <div class="form-control-feedback" id="id_error_{{element.name}}" {{^error}} style="display: none;"{{/error}}>
+ {{{error}}}
+ </div>
+</div>
\ No newline at end of file
--- /dev/null
+{{> core_form/element-group }}
\ No newline at end of file
--- /dev/null
+<div class="form-group row {{#error}}has-danger{{/error}}">
+ <label class="col-md-3 col-form-label {{#element.hideLabel}}sr-only{{/element.hideLabel}}" for="{{element.id}}">
+ {{{label}}} {{{helpbutton}}}
+ </label>
+ <div class="col-md-9">
+ {{{element.html}}}
+ <div class="form-control-feedback" id="id_error_{{element.name}}_5btext_5d" {{^error}} style="display: none;"{{/error}}>
+ {{{error}}}
+ </div>
+ </div>
+</div>
+{{#js}}
+require(['jquery', 'core/event'], function($, Event) {
+ var element = document.getElementById('{{element.id}}');
+ $(element).on(Event.Events.FORM_FIELD_VALIDATION, function(event, msg) {
+ event.preventDefault();
+ var parent = $(element).closest('.form-group');
+ var feedback = parent.find('.form-control-feedback');
+ if (msg !== '') {
+ parent.addClass('has-danger');
+ $(element).addClass('form-control-danger');
+ $(element).attr('aria-describedby', $(element).attr('id') + '-feedback');
+ feedback.html(msg);
+ feedback.show();
+ } else {
+ parent.removeClass('has-danger');
+ $(element).removeClass('form-control-danger');
+ $(element).attr('aria-describedby', '');
+ feedback.hide();
+ }
+ });
+});
+{{/js}}
\ No newline at end of file
--- /dev/null
+<div class="form-group row {{#error}}has-danger{{/error}}">
+ <label class="col-md-3 col-form-label {{#element.hideLabel}}sr-only{{/element.hideLabel}}" for="{{element.id}}">
+ {{{label}}} {{{helpbutton}}}
+ </label>
+ <div class="col-md-9">
+ {{{element.html}}}
+ <div class="form-control-feedback" id="id_error_{{element.name}}" {{^error}} style="display: none;"{{/error}}>
+ {{{error}}}
+ </div>
+ </div>
+</div>
+{{#js}}
+require(['jquery', 'core/event'], function($, Event) {
+ var element = document.getElementById('{{element.id}}');
+ $(element).on(Event.Events.FORM_FIELD_VALIDATION, function(event, msg) {
+ event.preventDefault();
+ var parent = $(element).closest('.form-group');
+ var feedback = parent.find('.form-control-feedback');
+ if (msg !== '') {
+ parent.addClass('has-danger');
+ $(element).addClass('form-control-danger');
+ $(element).attr('aria-describedby', $(element).attr('id') + '-feedback');
+ feedback.html(msg);
+ feedback.show();
+ } else {
+ parent.removeClass('has-danger');
+ $(element).removeClass('form-control-danger');
+ $(element).attr('aria-describedby', '');
+ feedback.hide();
+ }
+ });
+});
+{{/js}}
\ No newline at end of file
--- /dev/null
+<div class="form-group row {{#error}}has-danger{{/error}}">
+ <label class="col-md-3 col-form-label {{#element.hideLabel}}sr-only{{/element.hideLabel}}" for="{{element.id}}">
+ {{{label}}} {{{helpbutton}}}
+ </label>
+ <div class="col-md-9">
+ {{{element.html}}}
+ <div class="form-control-feedback" id="id_error_{{element.name}}" {{^error}} style="display: none;"{{/error}}>
+ {{{error}}}
+ </div>
+ </div>
+</div>
+{{#js}}
+require(['jquery', 'core/event'], function($, Event) {
+ var element = document.getElementById('{{element.id}}');
+ $(element).on(Event.Events.FORM_FIELD_VALIDATION, function(event, msg) {
+ event.preventDefault();
+ var parent = $(element).closest('.form-group');
+ var feedback = parent.find('.form-control-feedback');
+ if (msg !== '') {
+ parent.addClass('has-danger');
+ $(element).addClass('form-control-danger');
+ $(element).attr('aria-describedby', $(element).attr('id') + '-feedback');
+ feedback.html(msg);
+ feedback.show();
+ } else {
+ parent.removeClass('has-danger');
+ $(element).removeClass('form-control-danger');
+ $(element).attr('aria-describedby', '');
+ feedback.hide();
+ }
+ });
+});
+{{/js}}
\ No newline at end of file
--- /dev/null
+<div class="form-group row {{#error}}has-danger{{/error}}">
+ <label class="col-md-3 col-form-label {{#element.hideLabel}}sr-only{{/element.hideLabel}}" for="{{element.id}}">
+ {{{label}}} {{{helpbutton}}}
+ </label>
+ <div class="col-md-9">
+ {{{element}}}
+ <div class="form-control-feedback" id="id_error_{{element.name}}" {{^error}} style="display: none;"{{/error}}>
+ {{{error}}}
+ </div>
+ </div>
+</div>
+{{#js}}
+require(['jquery', 'core/event'], function($, Event) {
+ var element = document.getElementById('{{element.id}}');
+ $(element).on(Event.Events.FORM_FIELD_VALIDATION, function(event, msg) {
+ event.preventDefault();
+ var parent = $(element).closest('.form-group');
+ var feedback = parent.find('.form-control-feedback');
+ if (msg !== '') {
+ parent.addClass('has-danger');
+ $(element).addClass('form-control-danger');
+ $(element).attr('aria-describedby', $(element).attr('id') + '-feedback');
+ feedback.html(msg);
+ feedback.show();
+ } else {
+ parent.removeClass('has-danger');
+ $(element).removeClass('form-control-danger');
+ $(element).attr('aria-describedby', '');
+ feedback.hide();
+ }
+ });
+});
+{{/js}}
\ No newline at end of file
--- /dev/null
+<div class="form-group row {{#error}}has-danger{{/error}}">
+ <label class="col-md-3 col-form-label" for="{{element.id}}">
+ {{{label}}} {{{helpbutton}}}
+ </label>
+ <div class="col-md-9 form-inline">
+ {{#element.elements}}
+ {{{.}}}
+ {{/element.elements}}
+ </div>
+</div>
\ No newline at end of file
--- /dev/null
+{{> core_form/element-group }}
\ No newline at end of file
--- /dev/null
+{{> core_form/element-select }}
\ No newline at end of file
--- /dev/null
+<div class="form-group row {{#error}}has-danger{{/error}}">
+ <label class="col-md-3 col-form-label {{#element.hideLabel}}sr-only{{/element.hideLabel}}" for="{{element.id}}">
+ {{{label}}} {{{helpbutton}}}
+ </label>
+ <div class="col-md-9">
+ <input type="password"
+ {{#element.frozen}}readonly{{/element.frozen}}
+ class="form-control {{#error}}form-control-danger{{/error}}"
+ name="{{element.name}}"
+ id="{{element.id}}"
+ value="{{element.value}}"
+ size="{{element.size}}"
+ {{#error}}
+ autofocus aria-describedby="id_error_{{element.name}}"
+ {{/error}} >
+ <div class="form-control-feedback" id="id_error_{{element.name}}" {{^error}} style="display: none;"{{/error}}>
+ {{{error}}}
+ </div>
+ </div>
+</div>
+{{#js}}
+require(['core/yui'], function(Y) {
+ Y.use('moodle-form-passwordunmask', function() {
+ M.form.passwordunmask({ formid: {{#quote}}{{element.id}}{{/quote}},
+ checkboxlabel: '{{#str}}unmaskpassword, form{{/str}}',
+ checkboxname: {{#quote}}{{element.name}}{{/quote}} });
+ });
+});
+require(['jquery', 'core/event'], function($, Event) {
+ var element = document.getElementById('{{element.id}}');
+ $(element).on(Event.Events.FORM_FIELD_VALIDATION, function(event, msg) {
+ event.preventDefault();
+ var parent = $(element).closest('.form-group');
+ var feedback = parent.find('.form-control-feedback');
+ if (msg !== '') {
+ parent.addClass('has-danger');
+ $(element).addClass('form-control-danger');
+ $(element).attr('aria-describedby', $(element).attr('id') + '-feedback');
+ feedback.html(msg);
+ feedback.show();
+ } else {
+ parent.removeClass('has-danger');
+ $(element).removeClass('form-control-danger');
+ $(element).attr('aria-describedby', '');
+ feedback.hide();
+ }
+ });
+});
+{{/js}}
\ No newline at end of file
--- /dev/null
+{{> core_form/element-selectgroups-inline }}
\ No newline at end of file
--- /dev/null
+{{> core_form/element-selectgroups }}
\ No newline at end of file
--- /dev/null
+<div class="form-group row {{#error}}has-danger{{/error}}">
+ <label class="col-md-3 col-form-label {{#element.hideLabel}}sr-only{{/element.hideLabel}}" for="{{element.id}}">
+ {{{label}}} {{{helpbutton}}}
+ </label>
+ <div class="col-md-9">
+ {{{element.html}}}
+ <div class="form-control-feedback" id="id_error_{{element.name}}" {{^error}} style="display: none;"{{/error}}>
+ {{{error}}}
+ </div>
+ </div>
+</div>
+{{#js}}
+require(['jquery', 'core/event'], function($, Event) {
+ var element = document.getElementById('{{element.id}}');
+ $(element).on(Event.Events.FORM_FIELD_VALIDATION, function(event, msg) {
+ event.preventDefault();
+ var parent = $(element).closest('.form-group');
+ var feedback = parent.find('.form-control-feedback');
+ if (msg !== '') {
+ parent.addClass('has-danger');
+ $(element).addClass('form-control-danger');
+ $(element).attr('aria-describedby', $(element).attr('id') + '-feedback');
+ feedback.html(msg);
+ feedback.show();
+ } else {
+ parent.removeClass('has-danger');
+ $(element).removeClass('form-control-danger');
+ $(element).attr('aria-describedby', '');
+ feedback.hide();
+ }
+ });
+});
+{{/js}}
\ No newline at end of file
--- /dev/null
+<div class="form-group {{#error}}has-danger{{/error}}">
+ <label for="{{element.id}}" class="{{#element.hideLabel}}sr-only{{/element.hideLabel}}">
+ {{{label}}} {{{helpbutton}}}
+ </label>
+ <select class="custom-select {{#error}}form-control-danger{{/error}}" name="{{element.name}}"
+ id="{{element.id}}"
+ {{#element.multiple}}multiple{{/element.multiple}}
+ {{#element.frozen}}readonly disabled{{/element.frozen}}
+ {{#error}}
+ autofocus aria-describedby="id_error_{{element.name}}"
+ {{/error}}
+ {{#element.attributes}}
+ {{name}}={{#quote}}{{value}}{{/quote}}
+ {{/element.attributes}}>
+ {{#element.options}}
+ <option value="{{value}}" {{#selected}}selected{{/selected}}>{{text}}</option>
+ {{/element.options}}
+ </select>
+ <div class="form-control-feedback" id="id_error_{{element.name}}" {{^error}} style="display: none;"{{/error}}>
+ {{{error}}}
+ </div>
+</div>
+{{#js}}
+require(['jquery', 'core/event'], function($, Event) {
+ var element = document.getElementById('{{element.id}}');
+ $(element).on(Event.Events.FORM_FIELD_VALIDATION, function(event, msg) {
+ event.preventDefault();
+ var parent = $(element).closest('.form-group');
+ var feedback = parent.find('.form-control-feedback');
+ if (msg !== '') {
+ parent.addClass('has-danger');
+ $(element).addClass('form-control-danger');
+ $(element).attr('aria-describedby', $(element).attr('id') + '-feedback');
+ feedback.html(msg);
+ feedback.show();
+ } else {
+ parent.removeClass('has-danger');
+ $(element).removeClass('form-control-danger');
+ $(element).attr('aria-describedby', '');
+ feedback.hide();
+ }
+ });
+});
+{{/js}}
\ No newline at end of file
--- /dev/null
+<div class="form-group row {{#error}}has-danger{{/error}}">
+ <label class="col-md-3 col-form-label" for="{{element.id}}">
+ {{{label}}} {{{helpbutton}}}
+ </label>
+ <div class="col-md-9">
+ <select class="custom-select {{#error}}form-control-danger{{/error}}" name="{{element.name}}"
+ id="{{element.id}}"
+ {{#element.multiple}}multiple{{/element.multiple}}
+ {{#element.frozen}}readonly disabled{{/element.frozen}}
+ {{#error}}
+ autofocus aria-describedby="id_error_{{element.name}}"
+ {{/error}}
+ {{#element.attributes}}
+ {{name}}={{#quote}}{{value}}{{/quote}} ddd
+ {{/element.attributes}}
+ >
+ {{#element.options}}
+ <option value="{{value}}" {{#selected}}selected{{/selected}}>{{text}}</option>
+ {{/element.options}}
+ </select>
+ <div class="form-control-feedback" id="id_error_{{element.name}}" {{^error}} style="display: none;"{{/error}}>
+ {{{error}}}
+ </div>
+ </div>
+</div>
+{{#js}}
+require(['jquery', 'core/event'], function($, Event) {
+ var element = document.getElementById('{{element.id}}');
+ $(element).on(Event.Events.FORM_FIELD_VALIDATION, function(event, msg) {
+ event.preventDefault();
+ var parent = $(element).closest('.form-group');
+ var feedback = parent.find('.form-control-feedback');
+ if (msg !== '') {
+ parent.addClass('has-danger');
+ $(element).addClass('form-control-danger');
+ $(element).attr('aria-describedby', $(element).attr('id') + '-feedback');
+ feedback.html(msg);
+ feedback.show();
+ } else {
+ parent.removeClass('has-danger');
+ $(element).removeClass('form-control-danger');
+ $(element).attr('aria-describedby', '');
+ feedback.hide();
+ }
+ });
+});
+{{/js}}
\ No newline at end of file
--- /dev/null
+<div class="form-group {{#error}}has-danger{{/error}}">
+ <label for="{{element.id}}" class="{{#element.hideLabel}}sr-only{{/element.hideLabel}}">
+ {{{label}}} {{{helpbutton}}}
+ </label>
+ <select class="form-control {{#error}}form-control-danger{{/error}}" name="{{element.name}}"
+ id="{{element.id}}"
+ {{#element.multiple}}multiple{{/element.multiple}}
+ {{#element.frozen}}readonly disabled{{/element.frozen}}
+ {{#error}}
+ autofocus aria-describedby="id_error_{{element.name}}"
+ {{/error}}
+ {{#element.attributes}}
+ {{name}}={{#quote}}{{value}}{{/quote}}
+ {{/element.attributes}}>
+ {{#element.options}}
+ <option value="{{value}}" {{#selected}}selected{{/selected}}>{{{text}}}</option>
+ {{/element.options}}
+ </select>
+ <div class="form-control-feedback" id="id_error_{{element.name}}" {{^error}} style="display: none;"{{/error}}>
+ {{{error}}}
+ </div>
+</div>
+{{#js}}
+require(['jquery', 'core/event'], function($, Event) {
+ var element = document.getElementById('{{element.id}}');
+ $(element).on(Event.Events.FORM_FIELD_VALIDATION, function(event, msg) {
+ event.preventDefault();
+ var parent = $(element).closest('.form-group');
+ var feedback = parent.find('.form-control-feedback');
+ if (msg !== '') {
+ parent.addClass('has-danger');
+ $(element).addClass('form-control-danger');
+ $(element).attr('aria-describedby', $(element).attr('id') + '-feedback');
+ feedback.html(msg);
+ feedback.show();
+ } else {
+ parent.removeClass('has-danger');
+ $(element).removeClass('form-control-danger');
+ $(element).attr('aria-describedby', '');
+ feedback.hide();
+ }
+ });
+});
+{{/js}}
\ No newline at end of file
--- /dev/null
+<div class="form-group row {{#error}}has-danger{{/error}}">
+ <label class="col-md-3 col-form-label" for="{{element.id}}">
+ {{{label}}} {{{helpbutton}}}
+ </label>
+ <div class="col-md-9">
+ <select class="form-control {{#error}}form-control-danger{{/error}}" name="{{element.name}}"
+ id="{{element.id}}"
+ {{#element.multiple}}multiple{{/element.multiple}}
+ {{#element.frozen}}readonly disabled{{/element.frozen}}
+ {{#error}}
+ autofocus aria-describedby="id_error_{{element.name}}"
+ {{/error}}
+ {{#element.attributes}}
+ {{name}}={{#quote}}{{value}}{{/quote}}
+ {{/element.attributes}}
+ >
+ {{#element.optiongroups}}
+ <optgroup label="{{text}}">
+ {{#options}}
+ <option value="{{value}}" {{#selected}}selected{{/selected}}>{{{text}}}</option>
+ {{/options}}
+ {{/element.optiongroups}}
+ </optgroup>
+ </select>
+ <div class="form-control-feedback" id="id_error_{{element.name}}" {{^error}} style="display: none;"{{/error}}>
+ {{{error}}}
+ </div>
+ </div>
+</div>
+{{#js}}
+require(['jquery', 'core/event'], function($, Event) {
+ var element = document.getElementById('{{element.id}}');
+ $(element).on(Event.Events.FORM_FIELD_VALIDATION, function(event, msg) {
+ event.preventDefault();
+ var parent = $(element).closest('.form-group');
+ var feedback = parent.find('.form-control-feedback');
+ if (msg !== '') {
+ parent.addClass('has-danger');
+ $(element).addClass('form-control-danger');
+ $(element).attr('aria-describedby', $(element).attr('id') + '-feedback');
+ feedback.html(msg);
+ feedback.show();
+ } else {
+ parent.removeClass('has-danger');
+ $(element).removeClass('form-control-danger');
+ $(element).attr('aria-describedby', '');
+ feedback.hide();
+ }
+ });
+});
+{{/js}}
\ No newline at end of file
--- /dev/null
+{{> core_form/element-select-inline }}
\ No newline at end of file
--- /dev/null
+{{> core_form/element-select }}
\ No newline at end of file
--- /dev/null
+<div class="form-group row fitem {{#error}}has-danger{{/error}}">
+ <label class="col-md-3 col-form-label {{#element.hideLabel}}sr-only{{/element.hideLabel}}" for="{{element.id}}">
+ {{{label}}} {{{helpbutton}}}
+ </label>
+ <div class="col-md-9">
+ {{{element.html}}}
+ <div class="form-control-feedback" id="id_error_{{element.name}}" {{^error}} style="display: none;"{{/error}}>
+ {{{error}}}
+ </div>
+ </div>
+</div>
+{{#js}}
+require(['jquery', 'core/event'], function($, Event) {
+ var element = document.getElementById('{{element.id}}');
+ $(element).on(Event.Events.FORM_FIELD_VALIDATION, function(event, msg) {
+ event.preventDefault();
+ var parent = $(element).closest('.form-group');
+ var feedback = parent.find('.form-control-feedback');
+ if (msg !== '') {
+ parent.addClass('has-danger');
+ $(element).addClass('form-control-danger');
+ $(element).attr('aria-describedby', $(element).attr('id') + '-feedback');
+ feedback.html(msg);
+ feedback.show();
+ } else {
+ parent.removeClass('has-danger');
+ $(element).removeClass('form-control-danger');
+ $(element).attr('aria-describedby', '');
+ feedback.hide();
+ }
+ });
+});
+{{/js}}
\ No newline at end of file
--- /dev/null
+ <div class="form-group">
+ <label class="col-form-label {{#element.hideLabel}}sr-only{{/element.hideLabel}}" for="{{element.id}}">
+ {{{label}}} {{{helpbutton}}}
+ </label>
+ <input type="submit" {{#element.frozen}}readonly{{/element.frozen}}
+ class="btn btn-primary"
+ name="{{element.name}}"
+ id="{{element.id}}"
+ value="{{element.value}}" >
+ </div>
\ No newline at end of file
--- /dev/null
+<div class="form-group row">
+ <label class="col-md-3 col-form-label {{#element.hideLabel}}sr-only{{/element.hideLabel}}" for="{{element.id}}">
+ {{{label}}} {{{helpbutton}}}
+ </label>
+ <div class="col-md-9 form-inline">
+ <input type="submit" {{#element.frozen}}readonly{{/element.frozen}}
+ class="btn {{^iscancel}}btn-primary{{/iscancel}}{{#iscancel}}btn-secondary{{/iscancel}} m-l-0"
+ name="{{element.name}}"
+ id="{{element.id}}"
+ {{#error}}
+ autofocus aria-describedby="id_error_{{element.name}}"
+ {{/error}}
+ value="{{element.value}}">
+ </div>
+</div>
--- /dev/null
+<div class="form-group {{#error}}has-danger{{/error}}">
+ <label class="{{#element.hideLabel}}sr-only{{/element.hideLabel}}" for="{{element.id}}">
+ {{{label}}} {{{helpbutton}}}
+ </label>
+ <input type="text"
+ {{#element.frozen}}readonly{{/element.frozen}}
+ class="form-control {{#error}}form-control-danger{{/error}}"
+ name="{{element.name}}"
+ id="{{element.id}}"
+ value="{{element.value}}"
+ size="{{element.size}}"
+ {{#error}}
+ autofocus aria-describedby="id_error_{{element.name}}"
+ {{/error}} >
+ <div class="form-control-feedback" id="id_error_{{element.name}}" {{^error}} style="display: none;"{{/error}}>
+ {{{error}}}
+ </div>
+</div>
+{{#js}}
+require(['jquery', 'core/event'], function($, Event) {
+ var element = document.getElementById('{{element.id}}');
+ $(element).on(Event.Events.FORM_FIELD_VALIDATION, function(event, msg) {
+ event.preventDefault();
+ var parent = $(element).closest('.form-group');
+ var feedback = parent.find('.form-control-feedback');
+ if (msg !== '') {
+ parent.addClass('has-danger');
+ $(element).addClass('form-control-danger');
+ $(element).attr('aria-describedby', $(element).attr('id') + '-feedback');
+ feedback.html(msg);
+ feedback.show();
+ } else {
+ parent.removeClass('has-danger');
+ $(element).removeClass('form-control-danger');
+ $(element).attr('aria-describedby', '');
+ feedback.hide();
+ }
+ });
+});
+{{/js}}
\ No newline at end of file
--- /dev/null
+<div class="form-group row {{#error}}has-danger{{/error}}">
+ <label class="col-md-3 col-form-label {{#element.hideLabel}}sr-only{{/element.hideLabel}}" for="{{element.id}}">
+ {{{label}}} {{{helpbutton}}}
+ </label>
+ <div class="col-md-9">
+ <input type="text"
+ {{#element.frozen}}readonly{{/element.frozen}}
+ class="form-control {{#error}}form-control-danger{{/error}}"
+ name="{{element.name}}"
+ id="{{element.id}}"
+ value="{{element.value}}"
+ size="{{element.size}}"
+ {{#error}}
+ autofocus aria-describedby="id_error_{{element.name}}"
+ {{/error}} >
+ <div class="form-control-feedback" id="id_error_{{element.name}}" {{^error}} style="display: none;"{{/error}}>
+ {{{error}}}
+ </div>
+ </div>
+</div>
+{{#js}}
+require(['jquery', 'core/event'], function($, Event) {
+ var element = document.getElementById('{{element.id}}');
+ $(element).on(Event.Events.FORM_FIELD_VALIDATION, function(event, msg) {
+ event.preventDefault();
+ var parent = $(element).closest('.form-group');
+ var feedback = parent.find('.form-control-feedback');
+ if (msg !== '') {
+ parent.addClass('has-danger');
+ $(element).addClass('form-control-danger');
+ $(element).attr('aria-describedby', $(element).attr('id') + '-feedback');
+ feedback.html(msg);
+ feedback.show();
+ } else {
+ parent.removeClass('has-danger');
+ $(element).removeClass('form-control-danger');
+ $(element).attr('aria-describedby', '');
+ feedback.hide();
+ }
+ });
+});
+{{/js}}
\ No newline at end of file
--- /dev/null
+<div class="form-group row fitem {{#error}}has-danger{{/error}}" id="fitem_{{element.id}}">
+ <label class="col-md-3 col-form-label {{#element.hideLabel}}sr-only{{/element.hideLabel}}" for="{{element.id}}">
+ {{{label}}} {{{helpbutton}}}
+ </label>
+ <div class="col-md-9">
+ <textarea name="{{element.name}}" id="{{element.id}}">{{element.value}}</textarea>
+ <div class="form-control-feedback" id="id_error_{{element.name}}" {{^error}} style="display: none;"{{/error}}>
+ {{{error}}}
+ </div>
+ </div>
+</div>
+{{#js}}
+require(['jquery', 'core/event'], function($, Event) {
+ var element = document.getElementById('{{element.id}}');
+ $(element).on(Event.Events.FORM_FIELD_VALIDATION, function(event, msg) {
+ event.preventDefault();
+ var parent = $(element).closest('.form-group');
+ var feedback = parent.find('.form-control-feedback');
+ if (msg !== '') {
+ parent.addClass('has-danger');
+ $(element).addClass('form-control-danger');
+ $(element).attr('aria-describedby', $(element).attr('id') + '-feedback');
+ feedback.html(msg);
+ feedback.show();
+ } else {
+ parent.removeClass('has-danger');
+ $(element).removeClass('form-control-danger');
+ $(element).attr('aria-describedby', '');
+ feedback.hide();
+ }
+ });
+});
+{{/js}}
\ No newline at end of file
--- /dev/null
+<div class="form-group row {{#error}}has-danger{{/error}}">
+ <label class="col-md-3 col-form-label {{#element.hideLabel}}sr-only{{/element.hideLabel}}" for="{{element.id}}">
+ {{{label}}} {{{helpbutton}}}
+ </label>
+ <div class="col-md-9">
+ <input type="url"
+ {{#element.frozen}}readonly{{/element.frozen}}
+ class="form-control {{#error}}form-control-danger{{/error}}"
+ name="{{element.name}}"
+ id="{{element.id}}"
+ value="{{element.value}}"
+ size="{{element.size}}"
+ {{#error}}
+ autofocus aria-describedby="id_error_{{element.name}}"
+ {{/error}} >
+ {{{element.filepickerhtml}}}
+ <div class="form-control-feedback" id="id_error_{{element.name}}" {{^error}} style="display: none;"{{/error}}>
+ {{{error}}}
+ </div>
+ </div>
+</div>
+{{#js}}
+require(['jquery', 'core/event'], function($, Event) {
+ var element = document.getElementById('{{element.id}}');
+ $(element).on(Event.Events.FORM_FIELD_VALIDATION, function(event, msg) {
+ event.preventDefault();
+ var parent = $(element).closest('.form-group');
+ var feedback = parent.find('.form-control-feedback');
+ if (msg !== '') {
+ parent.addClass('has-danger');
+ $(element).addClass('form-control-danger');
+ $(element).attr('aria-describedby', $(element).attr('id') + '-feedback');
+ feedback.html(msg);
+ feedback.show();
+ } else {
+ parent.removeClass('has-danger');
+ $(element).removeClass('form-control-danger');
+ $(element).attr('aria-describedby', '');
+ feedback.hide();
+ }
+ });
+});
+{{/js}}
\ No newline at end of file
--- /dev/null
+<div class="form-group row fitem has-danger">
+ <label class="col-md-3 col-form-label {{#element.hideLabel}}sr-only{{/element.hideLabel}}" for="{{element.id}}">
+ {{{label}}} {{{helpbutton}}}
+ </label>
+ <div class="col-md-9">
+ <div class="form-control-feedback" id="id_error_{{element.name}}">
+ {{{element.html}}}
+ </div>
+ </div>
+</div>
\ No newline at end of file