From 91bda4cd45e91f356036b1fd73bc8efcfb089166 Mon Sep 17 00:00:00 2001 From: Damyon Wiese Date: Thu, 4 Aug 2016 22:29:32 +0800 Subject: [PATCH] MDL-55417 forms: Render form elements with a template 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 --- grade/edit/outcome/edit_form.php | 8 +- grade/edit/tree/outcomeitem_form.php | 7 +- lib/amd/build/event.min.js | 2 +- lib/amd/src/event.js | 7 + lib/form/advcheckbox.php | 12 +- lib/form/autocomplete.php | 19 ++ lib/form/button.php | 12 +- lib/form/checkbox.php | 12 +- lib/form/editor.php | 48 +-- lib/form/filemanager.php | 13 +- lib/form/filepicker.php | 13 +- lib/form/grading.php | 8 +- lib/form/group.php | 90 +++++- lib/form/modgrade.php | 8 +- lib/form/password.php | 12 +- lib/form/recaptcha.php | 13 +- lib/form/select.php | 32 +- lib/form/selectgroups.php | 47 ++- lib/form/selectwithlink.php | 2 + lib/form/static.php | 13 +- lib/form/submit.php | 14 +- lib/form/submitlink.php | 2 + lib/form/templates/editor_textarea.mustache | 16 + lib/form/text.php | 14 +- lib/form/textarea.php | 13 +- lib/form/url.php | 29 +- lib/formslib.php | 276 ++++++++++-------- lib/outputrenderers.php | 45 +++ theme/noname/scss/moodle/core.scss | 9 + theme/noname/scss/moodle/course.scss | 5 + theme/noname/scss/moodle/forms.scss | 208 +------------ .../core/form_autocomplete_input.mustache | 43 +++ .../core/form_autocomplete_selection.mustache | 51 ++++ .../core_form/editor_textarea.mustache | 16 + .../element-advcheckbox-inline.mustache | 3 + .../core_form/element-advcheckbox.mustache | 3 + .../core_form/element-autocomplete.mustache | 47 +++ .../core_form/element-button-inline.mustache | 11 + .../core_form/element-button.mustache | 16 + .../element-checkbox-inline.mustache | 32 ++ .../core_form/element-checkbox.mustache | 36 +++ .../core_form/element-date_selector.mustache | 10 + .../element-date_time_selector.mustache | 13 + .../core_form/element-duration.mustache | 1 + .../core_form/element-editor.mustache | 33 +++ .../core_form/element-filemanager.mustache | 33 +++ .../core_form/element-filepicker.mustache | 33 +++ .../core_form/element-grading.mustache | 33 +++ .../core_form/element-group.mustache | 10 + .../core_form/element-modgrade.mustache | 1 + .../core_form/element-modvisible.mustache | 1 + .../core_form/element-password.mustache | 49 ++++ .../element-questioncategory-inline.mustache | 1 + .../element-questioncategory.mustache | 1 + .../core_form/element-recaptcha.mustache | 33 +++ .../core_form/element-select-inline.mustache | 44 +++ .../core_form/element-select.mustache | 47 +++ .../element-selectgroups-inline.mustache | 44 +++ .../core_form/element-selectgroups.mustache | 51 ++++ .../element-selectyesno-inline.mustache | 1 + .../core_form/element-selectyesno.mustache | 1 + .../core_form/element-static.mustache | 33 +++ .../core_form/element-submit-inline.mustache | 10 + .../core_form/element-submit.mustache | 15 + .../core_form/element-text-inline.mustache | 40 +++ .../templates/core_form/element-text.mustache | 42 +++ .../core_form/element-textarea.mustache | 33 +++ .../templates/core_form/element-url.mustache | 43 +++ .../core_form/element-warning.mustache | 10 + 69 files changed, 1566 insertions(+), 367 deletions(-) create mode 100644 lib/form/templates/editor_textarea.mustache create mode 100644 theme/noname/templates/core/form_autocomplete_input.mustache create mode 100644 theme/noname/templates/core/form_autocomplete_selection.mustache create mode 100644 theme/noname/templates/core_form/editor_textarea.mustache create mode 100644 theme/noname/templates/core_form/element-advcheckbox-inline.mustache create mode 100644 theme/noname/templates/core_form/element-advcheckbox.mustache create mode 100644 theme/noname/templates/core_form/element-autocomplete.mustache create mode 100644 theme/noname/templates/core_form/element-button-inline.mustache create mode 100644 theme/noname/templates/core_form/element-button.mustache create mode 100644 theme/noname/templates/core_form/element-checkbox-inline.mustache create mode 100644 theme/noname/templates/core_form/element-checkbox.mustache create mode 100644 theme/noname/templates/core_form/element-date_selector.mustache create mode 100644 theme/noname/templates/core_form/element-date_time_selector.mustache create mode 100644 theme/noname/templates/core_form/element-duration.mustache create mode 100644 theme/noname/templates/core_form/element-editor.mustache create mode 100644 theme/noname/templates/core_form/element-filemanager.mustache create mode 100644 theme/noname/templates/core_form/element-filepicker.mustache create mode 100644 theme/noname/templates/core_form/element-grading.mustache create mode 100644 theme/noname/templates/core_form/element-group.mustache create mode 100644 theme/noname/templates/core_form/element-modgrade.mustache create mode 100644 theme/noname/templates/core_form/element-modvisible.mustache create mode 100644 theme/noname/templates/core_form/element-password.mustache create mode 100644 theme/noname/templates/core_form/element-questioncategory-inline.mustache create mode 100644 theme/noname/templates/core_form/element-questioncategory.mustache create mode 100644 theme/noname/templates/core_form/element-recaptcha.mustache create mode 100644 theme/noname/templates/core_form/element-select-inline.mustache create mode 100644 theme/noname/templates/core_form/element-select.mustache create mode 100644 theme/noname/templates/core_form/element-selectgroups-inline.mustache create mode 100644 theme/noname/templates/core_form/element-selectgroups.mustache create mode 100644 theme/noname/templates/core_form/element-selectyesno-inline.mustache create mode 100644 theme/noname/templates/core_form/element-selectyesno.mustache create mode 100644 theme/noname/templates/core_form/element-static.mustache create mode 100644 theme/noname/templates/core_form/element-submit-inline.mustache create mode 100644 theme/noname/templates/core_form/element-submit.mustache create mode 100644 theme/noname/templates/core_form/element-text-inline.mustache create mode 100644 theme/noname/templates/core_form/element-text.mustache create mode 100644 theme/noname/templates/core_form/element-textarea.mustache create mode 100644 theme/noname/templates/core_form/element-url.mustache create mode 100644 theme/noname/templates/core_form/element-warning.mustache diff --git a/grade/edit/outcome/edit_form.php b/grade/edit/outcome/edit_form.php index fd06079b809..ae4bacd6bc9 100644 --- a/grade/edit/outcome/edit_form.php +++ b/grade/edit/outcome/edit_form.php @@ -49,8 +49,12 @@ class edit_outcome_form extends moodleform { $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'); diff --git a/grade/edit/tree/outcomeitem_form.php b/grade/edit/tree/outcomeitem_form.php index 285acbed4c3..5930ca768b3 100644 --- a/grade/edit/tree/outcomeitem_form.php +++ b/grade/edit/tree/outcomeitem_form.php @@ -56,8 +56,11 @@ class edit_outcomeitem_form extends moodleform { $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'); diff --git a/lib/amd/build/event.min.js b/lib/amd/build/event.min.js index 39b9bb55084..5f05de6aeec 100644 --- a/lib/amd/build/event.min.js +++ b/lib/amd/build/event.min.js @@ -1 +1 @@ -define(["jquery","core/yui"],function(a,b){return{notifyFilterContentUpdated:function(c){c=a(c),b.use("event","moodle-core-event",function(b){a(document).trigger(M.core.event.FILTER_CONTENT_UPDATED,c);var d=new b.NodeList(c.get());b.fire(M.core.event.FILTER_CONTENT_UPDATED,{nodes:d})})},notifyEditorContentRestored:function(){b.use("event","moodle-core-event",function(b){a(document).trigger(M.core.event.EDITOR_CONTENT_RESTORED),b.fire(M.core.event.EDITOR_CONTENT_RESTORED)})}}}); \ No newline at end of file +define(["jquery","core/yui"],function(a,b){return{Events:{FORM_FIELD_VALIDATION:"core_form-field-validation"},notifyFilterContentUpdated:function(c){c=a(c),b.use("event","moodle-core-event",function(b){a(document).trigger(M.core.event.FILTER_CONTENT_UPDATED,c);var d=new b.NodeList(c.get());b.fire(M.core.event.FILTER_CONTENT_UPDATED,{nodes:d})})},notifyEditorContentRestored:function(){b.use("event","moodle-core-event",function(b){a(document).trigger(M.core.event.EDITOR_CONTENT_RESTORED),b.fire(M.core.event.EDITOR_CONTENT_RESTORED)})}}}); \ No newline at end of file diff --git a/lib/amd/src/event.js b/lib/amd/src/event.js index 0923668316a..568f4df3aa6 100644 --- a/lib/amd/src/event.js +++ b/lib/amd/src/event.js @@ -27,7 +27,14 @@ define(['jquery', 'core/yui'], 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 * diff --git a/lib/form/advcheckbox.php b/lib/form/advcheckbox.php index 97118d6410f..00bcb17aac9 100644 --- a/lib/form/advcheckbox.php +++ b/lib/form/advcheckbox.php @@ -26,6 +26,7 @@ */ require_once('HTML/QuickForm/advcheckbox.php'); +require_once(__DIR__ . '/../outputcomponents.php'); /** * HTML class for an advcheckbox type element @@ -38,7 +39,7 @@ require_once('HTML/QuickForm/advcheckbox.php'); * @copyright 2007 Jamie Pratt * @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=''; @@ -130,4 +131,13 @@ class MoodleQuickForm_advcheckbox extends HTML_QuickForm_advcheckbox{ } 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; + } } diff --git a/lib/form/autocomplete.php b/lib/form/autocomplete.php index 1f2dac3ac39..5d695ea6653 100644 --- a/lib/form/autocomplete.php +++ b/lib/form/autocomplete.php @@ -204,4 +204,23 @@ class MoodleQuickForm_autocomplete extends MoodleQuickForm_select { } 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; + } } diff --git a/lib/form/button.php b/lib/form/button.php index a69e2171053..3546f67e28f 100644 --- a/lib/form/button.php +++ b/lib/form/button.php @@ -26,6 +26,7 @@ */ require_once("HTML/QuickForm/button.php"); +require_once(__DIR__ . '/../outputcomponents.php'); /** * HTML class for a button type element @@ -37,7 +38,7 @@ require_once("HTML/QuickForm/button.php"); * @copyright 2007 Jamie Pratt * @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=''; @@ -85,4 +86,13 @@ class MoodleQuickForm_button extends HTML_QuickForm_button 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; + } } diff --git a/lib/form/checkbox.php b/lib/form/checkbox.php index 8aaecdde1ab..00ab2401934 100644 --- a/lib/form/checkbox.php +++ b/lib/form/checkbox.php @@ -26,6 +26,7 @@ */ require_once('HTML/QuickForm/checkbox.php'); +require_once(__DIR__ . '/../outputcomponents.php'); /** * HTML class for a checkbox type element @@ -39,7 +40,7 @@ require_once('HTML/QuickForm/checkbox.php'); * @copyright 2007 Jamie Pratt * @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=''; @@ -138,4 +139,13 @@ class MoodleQuickForm_checkbox extends HTML_QuickForm_checkbox{ } 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; + } } diff --git a/lib/form/editor.php b/lib/form/editor.php index 4e06505dfb2..85d4f868920 100644 --- a/lib/form/editor.php +++ b/lib/form/editor.php @@ -30,6 +30,7 @@ global $CFG; 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 @@ -43,7 +44,7 @@ require_once($CFG->dirroot.'/repository/lib.php'); * @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 = ''; @@ -293,7 +294,7 @@ class MoodleQuickForm_editor extends HTML_QuickForm_element { * @return string */ function toHtml() { - global $CFG, $PAGE; + global $CFG, $PAGE, $OUTPUT; require_once($CFG->dirroot.'/repository/lib.php'); if ($this->_flagFrozen) { @@ -394,24 +395,27 @@ class MoodleQuickForm_editor extends HTML_QuickForm_element { $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; } - $str .= '
'; + $context['hasformats'] = count($formats) > 1; + $context['formats'] = []; + foreach ($formats as $value => $text) { + $context['formats'][] = ['value' => $value, 'text' => $text, 'selected' => ($value == $format)]; + } + $context['id'] = $id; + $context['value'] = $text; + $context['format'] = $format; - $str .= '
'; - 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 .= '
'; // during moodle installation, user area doesn't exist // so we need to disable filepicker here. @@ -446,6 +450,16 @@ class MoodleQuickForm_editor extends HTML_QuickForm_element { 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. * diff --git a/lib/form/filemanager.php b/lib/form/filemanager.php index d5252531297..7cde5ef88ad 100644 --- a/lib/form/filemanager.php +++ b/lib/form/filemanager.php @@ -30,6 +30,7 @@ global $CFG; 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 @@ -40,7 +41,7 @@ require_once($CFG->dirroot.'/repository/lib.php'); * @copyright 2009 Dongsheng Cai * @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 = ''; @@ -297,6 +298,16 @@ class MoodleQuickForm_filemanager extends HTML_QuickForm_element { 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; + } } /** diff --git a/lib/form/filepicker.php b/lib/form/filepicker.php index 16340963f20..b81a631f92f 100644 --- a/lib/form/filepicker.php +++ b/lib/form/filepicker.php @@ -29,6 +29,7 @@ global $CFG; require_once("HTML/QuickForm/button.php"); require_once($CFG->dirroot.'/repository/lib.php'); +require_once($CFG->libdir.'/outputcomponents.php'); /** * Filepicker form element @@ -40,7 +41,7 @@ require_once($CFG->dirroot.'/repository/lib.php'); * @copyright 2009 Dongsheng Cai * @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 = ''; @@ -220,4 +221,14 @@ class MoodleQuickForm_filepicker extends HTML_QuickForm_input { 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; + } } diff --git a/lib/form/grading.php b/lib/form/grading.php index c47de8a0ed3..d2aadeed85f 100644 --- a/lib/form/grading.php +++ b/lib/form/grading.php @@ -28,6 +28,7 @@ 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'); @@ -47,7 +48,7 @@ if (class_exists('HTML_QuickForm')) { * @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=''; @@ -63,6 +64,7 @@ class MoodleQuickForm_grading extends HTML_QuickForm_input{ */ public function __construct($elementName=null, $elementLabel=null, $attributes=null) { parent::__construct($elementName, $elementLabel, $attributes); + $this->_type = 'grading'; $this->gradingattributes = $attributes; } @@ -158,4 +160,8 @@ class MoodleQuickForm_grading extends HTML_QuickForm_input{ } return true; } + + public function export_for_template(renderer_base $output) { + return $this->toHtml(); + } } diff --git a/lib/form/group.php b/lib/form/group.php index 6750d36258c..fbe4de83a7d 100644 --- a/lib/form/group.php +++ b/lib/form/group.php @@ -26,6 +26,7 @@ */ require_once("HTML/QuickForm/group.php"); +require_once(__DIR__ . '/../outputcomponents.php'); /** * HTML class for a form element group @@ -37,13 +38,15 @@ require_once("HTML/QuickForm/group.php"); * @copyright 2007 Jamie Pratt * @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 * @@ -147,4 +150,89 @@ class MoodleQuickForm_group extends HTML_QuickForm_group{ } 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); + } } diff --git a/lib/form/modgrade.php b/lib/form/modgrade.php index 1be7cc846c2..efa3d6958df 100644 --- a/lib/form/modgrade.php +++ b/lib/form/modgrade.php @@ -149,14 +149,14 @@ class MoodleQuickForm_modgrade extends MoodleQuickForm_group { $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)); @@ -169,7 +169,7 @@ class MoodleQuickForm_modgrade extends MoodleQuickForm_group { $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)); @@ -188,7 +188,7 @@ class MoodleQuickForm_modgrade extends MoodleQuickForm_group { 'modgrade_rescalegrades', $langrescalegrades, $choices); - $rescalegradesselect->setHiddenLabel = false; + $rescalegradesselect->setHiddenLabel(true); $rescalegradesselectid = $this->generate_modgrade_subelement_id('modgrade_rescalegrades'); $rescalegradesselect->updateAttributes(array('id' => $rescalegradesselectid)); } diff --git a/lib/form/password.php b/lib/form/password.php index 82153bca919..1e57a0a5627 100644 --- a/lib/form/password.php +++ b/lib/form/password.php @@ -26,6 +26,7 @@ */ require_once('HTML/QuickForm/password.php'); +require_once(__DIR__ . '/../outputcomponents.php'); /** * Password type form element @@ -37,7 +38,7 @@ require_once('HTML/QuickForm/password.php'); * @copyright 2006 Jamie Pratt * @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=''; @@ -83,4 +84,13 @@ class MoodleQuickForm_password extends HTML_QuickForm_password{ 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; + } } diff --git a/lib/form/recaptcha.php b/lib/form/recaptcha.php index f043353c3b2..f086f841ac3 100644 --- a/lib/form/recaptcha.php +++ b/lib/form/recaptcha.php @@ -26,6 +26,7 @@ */ require_once('HTML/QuickForm/input.php'); +require_once(__DIR__ . '/../outputcomponents.php'); /** * recaptcha type form element @@ -37,7 +38,7 @@ require_once('HTML/QuickForm/input.php'); * @copyright 2008 Nicolas Connault * @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=''; @@ -152,4 +153,14 @@ class MoodleQuickForm_recaptcha extends HTML_QuickForm_input { } 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; + } } diff --git a/lib/form/select.php b/lib/form/select.php index aa888cb5627..57c85049716 100644 --- a/lib/form/select.php +++ b/lib/form/select.php @@ -26,6 +26,7 @@ */ require_once('HTML/QuickForm/select.php'); +require_once(__DIR__ . '/../outputcomponents.php'); /** * select type form element @@ -37,7 +38,7 @@ require_once('HTML/QuickForm/select.php'); * @copyright 2006 Jamie Pratt * @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=''; @@ -189,4 +190,33 @@ class MoodleQuickForm_select extends HTML_QuickForm_select{ 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; + } } diff --git a/lib/form/selectgroups.php b/lib/form/selectgroups.php index c942acbdf5e..b277138be12 100644 --- a/lib/form/selectgroups.php +++ b/lib/form/selectgroups.php @@ -26,6 +26,7 @@ */ require_once('HTML/QuickForm/element.php'); +require_once(__DIR__ . '/../outputcomponents.php'); /** * select type form element @@ -37,7 +38,7 @@ require_once('HTML/QuickForm/element.php'); * @copyright 2007 Jamie Pratt * @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; @@ -507,4 +508,48 @@ class MoodleQuickForm_selectgroups extends HTML_QuickForm_element { 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; + } } diff --git a/lib/form/selectwithlink.php b/lib/form/selectwithlink.php index 78832d9376b..eb2a0d07fe5 100644 --- a/lib/form/selectwithlink.php +++ b/lib/form/selectwithlink.php @@ -32,6 +32,7 @@ require_once('HTML/QuickForm/select.php'); * * HTML class for a select type element with options containing link * + * @deprecated since 3.2 * @package core_form * @category form * @copyright 2008 Nicolas Connault @@ -63,6 +64,7 @@ class MoodleQuickForm_selectwithlink extends HTML_QuickForm_select{ * @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']; diff --git a/lib/form/static.php b/lib/form/static.php index 391be8e0cc7..d31329f7f7a 100644 --- a/lib/form/static.php +++ b/lib/form/static.php @@ -26,6 +26,7 @@ */ require_once("HTML/QuickForm/static.php"); +require_once(__DIR__ . '/../outputcomponents.php'); /** * Text type element @@ -37,7 +38,7 @@ require_once("HTML/QuickForm/static.php"); * @copyright 2006 Jamie Pratt * @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'; @@ -82,4 +83,14 @@ class MoodleQuickForm_static extends HTML_QuickForm_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; + } } diff --git a/lib/form/submit.php b/lib/form/submit.php index c0e2d963803..7ccd0cc37e9 100644 --- a/lib/form/submit.php +++ b/lib/form/submit.php @@ -26,6 +26,7 @@ */ require_once("HTML/QuickForm/submit.php"); +require_once(__DIR__ . '/../outputcomponents.php'); /** * submit type form element @@ -37,7 +38,7 @@ require_once("HTML/QuickForm/submit.php"); * @copyright 2006 Jamie Pratt * @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 * @@ -108,4 +109,15 @@ class MoodleQuickForm_submit extends HTML_QuickForm_submit { $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; + } } diff --git a/lib/form/submitlink.php b/lib/form/submitlink.php index bf238a51e31..0cb270c355a 100644 --- a/lib/form/submitlink.php +++ b/lib/form/submitlink.php @@ -20,6 +20,7 @@ * * Contains HTML class for a submitting to link * + * @deprecated since 3.2 * @package core_form * @copyright 2006 Jamie Pratt * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later @@ -52,6 +53,7 @@ class MoodleQuickForm_submitlink extends MoodleQuickForm_submit { * @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); } diff --git a/lib/form/templates/editor_textarea.mustache b/lib/form/templates/editor_textarea.mustache new file mode 100644 index 00000000000..fbec7d1a41f --- /dev/null +++ b/lib/form/templates/editor_textarea.mustache @@ -0,0 +1,16 @@ +
+ +
+
+ {{^onlyoneformat}} + + {{/onlyoneformat}} + {{#onlyoneformat}} + + {{/onlyoneformat}} +
\ No newline at end of file diff --git a/lib/form/text.php b/lib/form/text.php index 8b8c5580319..0264a99ccf2 100644 --- a/lib/form/text.php +++ b/lib/form/text.php @@ -26,6 +26,7 @@ */ require_once("HTML/QuickForm/text.php"); +require_once(__DIR__ . '/../outputcomponents.php'); /** * Text type form element @@ -37,7 +38,8 @@ require_once("HTML/QuickForm/text.php"); * @copyright 2006 Jamie Pratt * @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=''; @@ -124,4 +126,14 @@ class MoodleQuickForm_text extends HTML_QuickForm_text{ 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; + } } diff --git a/lib/form/textarea.php b/lib/form/textarea.php index 273fff5cb01..34ef9fe7546 100644 --- a/lib/form/textarea.php +++ b/lib/form/textarea.php @@ -26,6 +26,7 @@ */ require_once('HTML/QuickForm/textarea.php'); +require_once(__DIR__ . '/../outputcomponents.php'); /** * Textarea type form element @@ -37,7 +38,7 @@ require_once('HTML/QuickForm/textarea.php'); * @copyright 2006 Jamie Pratt * @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 = ''; @@ -130,4 +131,14 @@ class MoodleQuickForm_textarea extends HTML_QuickForm_textarea{ 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; + } } diff --git a/lib/form/url.php b/lib/form/url.php index eb54220556c..47dfa7a7696 100644 --- a/lib/form/url.php +++ b/lib/form/url.php @@ -26,6 +26,7 @@ */ require_once("HTML/QuickForm/text.php"); +require_once(__DIR__ . '/../outputcomponents.php'); /** * url type form element @@ -36,7 +37,7 @@ require_once("HTML/QuickForm/text.php"); * @copyright 2009 Dongsheng Cai * @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=''; @@ -61,7 +62,9 @@ class MoodleQuickForm_url extends HTML_QuickForm_text{ if (!isset($this->_options['usefilepicker'])) { $this->_options['usefilepicker'] = true; } + parent::__construct($elementName, $elementLabel, $attributes); + $this->_type = 'url'; } /** @@ -89,7 +92,7 @@ class MoodleQuickForm_url extends HTML_QuickForm_text{ * @return string */ function toHtml(){ - global $PAGE, $OUTPUT; + $id = $this->_attributes['id']; $elname = $this->_attributes['name']; @@ -105,6 +108,16 @@ class MoodleQuickForm_url extends HTML_QuickForm_text{ return $str; } + // print out file picker + $str .= $this->getFilePickerHTML(); + + return $str; + } + + function getFilePickerHTML() { + global $PAGE, $OUTPUT; + + $str = ''; $client_id = uniqid(); $args = new stdClass(); @@ -119,7 +132,7 @@ class MoodleQuickForm_url extends HTML_QuickForm_text{ if (count($options->repositories) > 0) { $straddlink = get_string('choosealink', 'repository'); $str .= << + EOD; @@ -157,4 +170,14 @@ 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; + } } diff --git a/lib/formslib.php b/lib/formslib.php index 5164ff384db..51ca7b74166 100644 --- a/lib/formslib.php +++ b/lib/formslib.php @@ -2091,6 +2091,8 @@ class MoodleQuickForm extends HTML_QuickForm_DHTMLRulesTableless { */ function getValidationScript() { + global $PAGE; + if (empty($this->_rules) || $this->clientvalidation === false) { return ''; } @@ -2170,67 +2172,74 @@ class MoodleQuickForm extends HTML_QuickForm_DHTMLRulesTableless { unset($element); $js = ' -'; - return $js; + +}); +'; + + $PAGE->requires->js_amd_inline($js); + return ''; } // end func getValidationScript /** @@ -2753,6 +2764,8 @@ class MoodleQuickForm_Renderer extends HTML_QuickForm_Renderer_Tableless{ * @param string $error error message to display */ function startGroup(&$group, $required, $error){ + global $OUTPUT; + // Make sure the element has an id. $group->_generateId(); @@ -2762,47 +2775,50 @@ class MoodleQuickForm_Renderer extends HTML_QuickForm_Renderer_Tableless{ // 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; + } } /** @@ -2813,56 +2829,66 @@ class MoodleQuickForm_Renderer extends HTML_QuickForm_Renderer_Tableless{ * @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); + $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(' {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('{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; + } } /** diff --git a/lib/outputrenderers.php b/lib/outputrenderers.php index 285c27bd2b0..d2fefd78737 100644 --- a/lib/outputrenderers.php +++ b/lib/outputrenderers.php @@ -4421,6 +4421,51 @@ EOD; 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; + } + } } /** diff --git a/theme/noname/scss/moodle/core.scss b/theme/noname/scss/moodle/core.scss index 46e03b9eb47..222fc3d7506 100644 --- a/theme/noname/scss/moodle/core.scss +++ b/theme/noname/scss/moodle/core.scss @@ -157,10 +157,17 @@ a.autolink.glossary:hover { .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; } @@ -168,6 +175,8 @@ img.resize { width: 16px; height: 16px; box-sizing: content-box; +} +.action-menu .dropdown-menu img { padding-right: 0.5rem; } .action-menu .userpicture { diff --git a/theme/noname/scss/moodle/course.scss b/theme/noname/scss/moodle/course.scss index 8d3b8be3159..75baa84e071 100644 --- a/theme/noname/scss/moodle/course.scss +++ b/theme/noname/scss/moodle/course.scss @@ -1,5 +1,10 @@ /* course.less */ /* COURSE CONTENT */ +.section-modchooser-link img { + margin-right: 0.5rem; + width: 16px; + height: 16px; +} .section_add_menus { text-align: right; clear: both; diff --git a/theme/noname/scss/moodle/forms.scss b/theme/noname/scss/moodle/forms.scss index 846b38554d0..77002fbd9a0 100644 --- a/theme/noname/scss/moodle/forms.scss +++ b/theme/noname/scss/moodle/forms.scss @@ -5,25 +5,12 @@ * */ -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; @@ -47,37 +34,9 @@ form { .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; @@ -87,39 +46,6 @@ form { .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; @@ -129,8 +55,7 @@ input#id_externalurl { } // 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. @@ -145,7 +70,6 @@ input#id_externalurl { } .form-item .form-setting, .form-item .form-description, -.mform .fitem .felement, #page-mod-forum-search .c1 .form-horizontal { @extend .controls; } @@ -159,14 +83,14 @@ input#id_externalurl { // 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; } @@ -204,11 +128,6 @@ div.backup-section + form, 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. @@ -306,32 +225,9 @@ div.backup-section + form, 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. */ } @@ -343,88 +239,7 @@ fieldset.coursesearchbox label { /** * 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). */ @@ -538,13 +353,6 @@ $maxWidthForVerticalForms: 1474px; } } -/* 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; @@ -564,7 +372,7 @@ input[size] { overflow: auto; margin: 0px; padding: 0px; - margin-top: -0.2em; + margin-top: 0.4em; z-index: 1; } .form-autocomplete-suggestions li { @@ -586,7 +394,7 @@ input[size] { .form-autocomplete-downarrow { color: $body-color; position: relative; - top: -0.3em; + top: 0.2em; left: -1.5em; cursor: pointer; } @@ -598,3 +406,7 @@ input[size] { padding: 0.5em; font-size: large; } + +select[multiple] { + overflow: auto; +} diff --git a/theme/noname/templates/core/form_autocomplete_input.mustache b/theme/noname/templates/core/form_autocomplete_input.mustache new file mode 100644 index 00000000000..89bb1a4c8aa --- /dev/null +++ b/theme/noname/templates/core/form_autocomplete_input.mustache @@ -0,0 +1,43 @@ +{{! + 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 . +}} +{{! + @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}} + +{{/showSuggestions}} +{{^showSuggestions}} + +{{/showSuggestions}} diff --git a/theme/noname/templates/core/form_autocomplete_selection.mustache b/theme/noname/templates/core/form_autocomplete_selection.mustache new file mode 100644 index 00000000000..16f5010079c --- /dev/null +++ b/theme/noname/templates/core/form_autocomplete_selection.mustache @@ -0,0 +1,51 @@ +{{! + 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 . +}} +{{! + @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 tags", "value": "5" }, + { "label": "Another item label with tags", "value": "4" } + ], "noSelectionString": "No selection" } +}} +
+{{#str}}selecteditems, form{{/str}} + {{#items}} + + {{#multiple}}{{/multiple}}{{{label}}} + + {{/items}} + {{^items}} + {{noSelectionString}} + {{/items}} +
+ diff --git a/theme/noname/templates/core_form/editor_textarea.mustache b/theme/noname/templates/core_form/editor_textarea.mustache new file mode 100644 index 00000000000..b256f9d0a7b --- /dev/null +++ b/theme/noname/templates/core_form/editor_textarea.mustache @@ -0,0 +1,16 @@ +
+ +
+
+ {{^onlyoneformat}} + + {{/onlyoneformat}} + {{#onlyoneformat}} + + {{/onlyoneformat}} +
\ No newline at end of file diff --git a/theme/noname/templates/core_form/element-advcheckbox-inline.mustache b/theme/noname/templates/core_form/element-advcheckbox-inline.mustache new file mode 100644 index 00000000000..67ed18eb7a7 --- /dev/null +++ b/theme/noname/templates/core_form/element-advcheckbox-inline.mustache @@ -0,0 +1,3 @@ + +{{> core_form/element-checkbox-inline }} \ No newline at end of file diff --git a/theme/noname/templates/core_form/element-advcheckbox.mustache b/theme/noname/templates/core_form/element-advcheckbox.mustache new file mode 100644 index 00000000000..2b649506e5e --- /dev/null +++ b/theme/noname/templates/core_form/element-advcheckbox.mustache @@ -0,0 +1,3 @@ + +{{> core_form/element-checkbox }} \ No newline at end of file diff --git a/theme/noname/templates/core_form/element-autocomplete.mustache b/theme/noname/templates/core_form/element-autocomplete.mustache new file mode 100644 index 00000000000..03ae368948a --- /dev/null +++ b/theme/noname/templates/core_form/element-autocomplete.mustache @@ -0,0 +1,47 @@ +
+ +
+ + +
+
+{{#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 diff --git a/theme/noname/templates/core_form/element-button-inline.mustache b/theme/noname/templates/core_form/element-button-inline.mustache new file mode 100644 index 00000000000..96abc13f04d --- /dev/null +++ b/theme/noname/templates/core_form/element-button-inline.mustache @@ -0,0 +1,11 @@ +
+ + +
\ No newline at end of file diff --git a/theme/noname/templates/core_form/element-button.mustache b/theme/noname/templates/core_form/element-button.mustache new file mode 100644 index 00000000000..996a3cb13f6 --- /dev/null +++ b/theme/noname/templates/core_form/element-button.mustache @@ -0,0 +1,16 @@ +
+ +
+ +
+
diff --git a/theme/noname/templates/core_form/element-checkbox-inline.mustache b/theme/noname/templates/core_form/element-checkbox-inline.mustache new file mode 100644 index 00000000000..5400d7433a4 --- /dev/null +++ b/theme/noname/templates/core_form/element-checkbox-inline.mustache @@ -0,0 +1,32 @@ + + +{{#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 diff --git a/theme/noname/templates/core_form/element-checkbox.mustache b/theme/noname/templates/core_form/element-checkbox.mustache new file mode 100644 index 00000000000..5122bd96a59 --- /dev/null +++ b/theme/noname/templates/core_form/element-checkbox.mustache @@ -0,0 +1,36 @@ +
+
+ + +
+
+{{#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 diff --git a/theme/noname/templates/core_form/element-date_selector.mustache b/theme/noname/templates/core_form/element-date_selector.mustache new file mode 100644 index 00000000000..645b0846dc3 --- /dev/null +++ b/theme/noname/templates/core_form/element-date_selector.mustache @@ -0,0 +1,10 @@ +
+ +
+ {{#element.elements}} + {{{.}}} + {{/element.elements}} +
+
\ No newline at end of file diff --git a/theme/noname/templates/core_form/element-date_time_selector.mustache b/theme/noname/templates/core_form/element-date_time_selector.mustache new file mode 100644 index 00000000000..be63490d3b4 --- /dev/null +++ b/theme/noname/templates/core_form/element-date_time_selector.mustache @@ -0,0 +1,13 @@ +
+ +
+ {{#element.elements}} + {{{.}}} + {{/element.elements}} +
+ +
\ No newline at end of file diff --git a/theme/noname/templates/core_form/element-duration.mustache b/theme/noname/templates/core_form/element-duration.mustache new file mode 100644 index 00000000000..7e804bb54e0 --- /dev/null +++ b/theme/noname/templates/core_form/element-duration.mustache @@ -0,0 +1 @@ +{{> core_form/element-group }} \ No newline at end of file diff --git a/theme/noname/templates/core_form/element-editor.mustache b/theme/noname/templates/core_form/element-editor.mustache new file mode 100644 index 00000000000..be567796673 --- /dev/null +++ b/theme/noname/templates/core_form/element-editor.mustache @@ -0,0 +1,33 @@ +
+ +
+ {{{element.html}}} + +
+
+{{#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 diff --git a/theme/noname/templates/core_form/element-filemanager.mustache b/theme/noname/templates/core_form/element-filemanager.mustache new file mode 100644 index 00000000000..02403ac1de2 --- /dev/null +++ b/theme/noname/templates/core_form/element-filemanager.mustache @@ -0,0 +1,33 @@ +
+ +
+ {{{element.html}}} + +
+
+{{#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 diff --git a/theme/noname/templates/core_form/element-filepicker.mustache b/theme/noname/templates/core_form/element-filepicker.mustache new file mode 100644 index 00000000000..02403ac1de2 --- /dev/null +++ b/theme/noname/templates/core_form/element-filepicker.mustache @@ -0,0 +1,33 @@ +
+ +
+ {{{element.html}}} + +
+
+{{#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 diff --git a/theme/noname/templates/core_form/element-grading.mustache b/theme/noname/templates/core_form/element-grading.mustache new file mode 100644 index 00000000000..9c4e7b7170f --- /dev/null +++ b/theme/noname/templates/core_form/element-grading.mustache @@ -0,0 +1,33 @@ +
+ +
+ {{{element}}} + +
+
+{{#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 diff --git a/theme/noname/templates/core_form/element-group.mustache b/theme/noname/templates/core_form/element-group.mustache new file mode 100644 index 00000000000..d93f0008343 --- /dev/null +++ b/theme/noname/templates/core_form/element-group.mustache @@ -0,0 +1,10 @@ +
+ +
+ {{#element.elements}} + {{{.}}} + {{/element.elements}} +
+
\ No newline at end of file diff --git a/theme/noname/templates/core_form/element-modgrade.mustache b/theme/noname/templates/core_form/element-modgrade.mustache new file mode 100644 index 00000000000..7e804bb54e0 --- /dev/null +++ b/theme/noname/templates/core_form/element-modgrade.mustache @@ -0,0 +1 @@ +{{> core_form/element-group }} \ No newline at end of file diff --git a/theme/noname/templates/core_form/element-modvisible.mustache b/theme/noname/templates/core_form/element-modvisible.mustache new file mode 100644 index 00000000000..5878ca97962 --- /dev/null +++ b/theme/noname/templates/core_form/element-modvisible.mustache @@ -0,0 +1 @@ +{{> core_form/element-select }} \ No newline at end of file diff --git a/theme/noname/templates/core_form/element-password.mustache b/theme/noname/templates/core_form/element-password.mustache new file mode 100644 index 00000000000..88112600199 --- /dev/null +++ b/theme/noname/templates/core_form/element-password.mustache @@ -0,0 +1,49 @@ +
+ +
+ + +
+
+{{#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 diff --git a/theme/noname/templates/core_form/element-questioncategory-inline.mustache b/theme/noname/templates/core_form/element-questioncategory-inline.mustache new file mode 100644 index 00000000000..b46bf08dfe2 --- /dev/null +++ b/theme/noname/templates/core_form/element-questioncategory-inline.mustache @@ -0,0 +1 @@ +{{> core_form/element-selectgroups-inline }} \ No newline at end of file diff --git a/theme/noname/templates/core_form/element-questioncategory.mustache b/theme/noname/templates/core_form/element-questioncategory.mustache new file mode 100644 index 00000000000..b98d62ab1ee --- /dev/null +++ b/theme/noname/templates/core_form/element-questioncategory.mustache @@ -0,0 +1 @@ +{{> core_form/element-selectgroups }} \ No newline at end of file diff --git a/theme/noname/templates/core_form/element-recaptcha.mustache b/theme/noname/templates/core_form/element-recaptcha.mustache new file mode 100644 index 00000000000..02403ac1de2 --- /dev/null +++ b/theme/noname/templates/core_form/element-recaptcha.mustache @@ -0,0 +1,33 @@ +
+ +
+ {{{element.html}}} + +
+
+{{#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 diff --git a/theme/noname/templates/core_form/element-select-inline.mustache b/theme/noname/templates/core_form/element-select-inline.mustache new file mode 100644 index 00000000000..97432a6cc45 --- /dev/null +++ b/theme/noname/templates/core_form/element-select-inline.mustache @@ -0,0 +1,44 @@ +
+ + + +
+{{#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 diff --git a/theme/noname/templates/core_form/element-select.mustache b/theme/noname/templates/core_form/element-select.mustache new file mode 100644 index 00000000000..003d81104ec --- /dev/null +++ b/theme/noname/templates/core_form/element-select.mustache @@ -0,0 +1,47 @@ +
+ +
+ + +
+
+{{#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 diff --git a/theme/noname/templates/core_form/element-selectgroups-inline.mustache b/theme/noname/templates/core_form/element-selectgroups-inline.mustache new file mode 100644 index 00000000000..f57bfe7d982 --- /dev/null +++ b/theme/noname/templates/core_form/element-selectgroups-inline.mustache @@ -0,0 +1,44 @@ +
+ + + +
+{{#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 diff --git a/theme/noname/templates/core_form/element-selectgroups.mustache b/theme/noname/templates/core_form/element-selectgroups.mustache new file mode 100644 index 00000000000..756f1e85868 --- /dev/null +++ b/theme/noname/templates/core_form/element-selectgroups.mustache @@ -0,0 +1,51 @@ +
+ +
+ + +
+
+{{#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 diff --git a/theme/noname/templates/core_form/element-selectyesno-inline.mustache b/theme/noname/templates/core_form/element-selectyesno-inline.mustache new file mode 100644 index 00000000000..de47adee9ae --- /dev/null +++ b/theme/noname/templates/core_form/element-selectyesno-inline.mustache @@ -0,0 +1 @@ +{{> core_form/element-select-inline }} \ No newline at end of file diff --git a/theme/noname/templates/core_form/element-selectyesno.mustache b/theme/noname/templates/core_form/element-selectyesno.mustache new file mode 100644 index 00000000000..5878ca97962 --- /dev/null +++ b/theme/noname/templates/core_form/element-selectyesno.mustache @@ -0,0 +1 @@ +{{> core_form/element-select }} \ No newline at end of file diff --git a/theme/noname/templates/core_form/element-static.mustache b/theme/noname/templates/core_form/element-static.mustache new file mode 100644 index 00000000000..7963d861c0f --- /dev/null +++ b/theme/noname/templates/core_form/element-static.mustache @@ -0,0 +1,33 @@ +
+ +
+ {{{element.html}}} + +
+
+{{#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 diff --git a/theme/noname/templates/core_form/element-submit-inline.mustache b/theme/noname/templates/core_form/element-submit-inline.mustache new file mode 100644 index 00000000000..425a5f910db --- /dev/null +++ b/theme/noname/templates/core_form/element-submit-inline.mustache @@ -0,0 +1,10 @@ +
+ + +
\ No newline at end of file diff --git a/theme/noname/templates/core_form/element-submit.mustache b/theme/noname/templates/core_form/element-submit.mustache new file mode 100644 index 00000000000..f6bb32ef2f2 --- /dev/null +++ b/theme/noname/templates/core_form/element-submit.mustache @@ -0,0 +1,15 @@ +
+ +
+ +
+
diff --git a/theme/noname/templates/core_form/element-text-inline.mustache b/theme/noname/templates/core_form/element-text-inline.mustache new file mode 100644 index 00000000000..e18121df7fa --- /dev/null +++ b/theme/noname/templates/core_form/element-text-inline.mustache @@ -0,0 +1,40 @@ +
+ + + +
+{{#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 diff --git a/theme/noname/templates/core_form/element-text.mustache b/theme/noname/templates/core_form/element-text.mustache new file mode 100644 index 00000000000..2dc6233dfd4 --- /dev/null +++ b/theme/noname/templates/core_form/element-text.mustache @@ -0,0 +1,42 @@ +
+ +
+ + +
+
+{{#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 diff --git a/theme/noname/templates/core_form/element-textarea.mustache b/theme/noname/templates/core_form/element-textarea.mustache new file mode 100644 index 00000000000..ac463e93824 --- /dev/null +++ b/theme/noname/templates/core_form/element-textarea.mustache @@ -0,0 +1,33 @@ +
+ +
+ + +
+
+{{#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 diff --git a/theme/noname/templates/core_form/element-url.mustache b/theme/noname/templates/core_form/element-url.mustache new file mode 100644 index 00000000000..88c6f019001 --- /dev/null +++ b/theme/noname/templates/core_form/element-url.mustache @@ -0,0 +1,43 @@ +
+ +
+ + {{{element.filepickerhtml}}} + +
+
+{{#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 diff --git a/theme/noname/templates/core_form/element-warning.mustache b/theme/noname/templates/core_form/element-warning.mustache new file mode 100644 index 00000000000..368b019328c --- /dev/null +++ b/theme/noname/templates/core_form/element-warning.mustache @@ -0,0 +1,10 @@ +
+ +
+ +
+
\ No newline at end of file