da1320da |
1 | <?php // $Id$ |
da6f8763 |
2 | /** |
3 | * formslib.php - library of classes for creating forms in Moodle, based on PEAR QuickForms. |
da1320da |
4 | * |
5 | * To use formslib then you will want to create a new file purpose_form.php eg. edit_form.php |
6 | * and you want to name your class something like {modulename}_{purpose}_form. Your class will |
7 | * extend moodleform overriding abstract classes definition and optionally defintion_after_data |
8 | * and validation. |
9 | * |
10 | * See examples of use of this library in course/edit.php and course/edit_form.php |
11 | * |
12 | * A few notes : |
13 | * form defintion is used for both printing of form and processing and should be the same |
14 | * for both or you may lose some submitted data which won't be let through. |
15 | * you should be using setType for every form element except select, radio or checkbox |
16 | * elements, these elements clean themselves. |
17 | * |
18 | * |
da6f8763 |
19 | * @author Jamie Pratt |
20 | * @version $Id$ |
21 | * @license http://www.gnu.org/copyleft/gpl.html GNU Public License |
22 | */ |
23 | |
24 | //point pear include path to moodles lib/pear so that includes and requires will search there for files before anywhere else. |
25 | if (FALSE===strstr(ini_get('include_path'), $CFG->libdir.'/pear' )){ |
26 | ini_set('include_path', $CFG->libdir.'/pear' . PATH_SEPARATOR . ini_get('include_path')); |
27 | } |
28 | require_once 'HTML/QuickForm.php'; |
29 | require_once 'HTML/QuickForm/DHTMLRulesTableless.php'; |
30 | require_once 'HTML/QuickForm/Renderer/Tableless.php'; |
31 | |
49292f8c |
32 | require_once $CFG->libdir.'/uploadlib.php'; |
33 | |
864cc1de |
34 | if ($CFG->debug >= DEBUG_ALL){ |
35 | PEAR::setErrorHandling(PEAR_ERROR_PRINT); |
36 | } |
37 | |
05f5c40c |
38 | /** |
da1320da |
39 | * Moodle specific wrapper that separates quickforms syntax from moodle code. You won't directly |
40 | * use this class you should write a class defintion which extends this class or a more specific |
41 | * subclass such a moodleform_mod for each form you want to display and/or process with formslib. |
42 | * |
43 | * You will write your own definition() method which performs the form set up. |
05f5c40c |
44 | */ |
7f40a229 |
45 | class moodleform { |
49292f8c |
46 | var $_formname; // form name |
3c7656b4 |
47 | /** |
48 | * quickform object definition |
49 | * |
50 | * @var MoodleQuickForm |
51 | */ |
52 | var $_form; |
53 | /** |
54 | * globals workaround |
55 | * |
56 | * @var array |
57 | */ |
58 | var $_customdata; |
59 | /** |
60 | * file upload manager |
61 | * |
62 | * @var upload_manager |
63 | */ |
64 | var $_upload_manager; // |
7f40a229 |
65 | |
19110c57 |
66 | |
ebd3c7ac |
67 | |
da1320da |
68 | /** |
69 | * The constructor function calls the abstract function definition() and it will then |
70 | * process and clean and attempt to validate incoming data. |
71 | * |
72 | * It will call your custom validate method to validate data and will also check any rules |
73 | * you have specified in definition using addRule |
74 | * |
75 | * The name of the form (id attribute of the form) is automatically generated depending on |
76 | * the name you gave the class extending moodleform. You should call your class something |
77 | * like |
78 | * |
79 | * @param string $action the action attribute for the form. |
80 | * @param array $customdata if your form defintion method needs access to data such as $course |
81 | * $cm, etc. to construct the form definition then pass it in this array. You can |
82 | * use globals for somethings. |
83 | * @param string $method if you set this to anything other than 'post' then _GET and _POST will |
84 | * be merged and used as incoming data to the form. |
85 | * @param string $target target frame for form submission. You will rarely use this. Don't use |
86 | * it if you don't need to as the target attribute is deprecated in xhtml |
87 | * strict. |
88 | * @param mixed $attributes you can pass a string of html attributes here or an array. |
89 | * @return moodleform |
90 | */ |
7f40a229 |
91 | function moodleform($action, $customdata=null, $method='post', $target='', $attributes=null) { |
44875d78 |
92 | //strip '_form' from the end of class name to make form 'id' attribute. |
93 | $this->_formname = preg_replace('/_form$/', '', get_class($this), 1); |
7f40a229 |
94 | $this->_customdata = $customdata; |
5bc97c98 |
95 | $this->_form =& new MoodleQuickForm($this->_formname, $method, $action, $target, $attributes); |
7f40a229 |
96 | |
97 | $this->definition(); |
98 | |
99 | $this->_form->addElement('hidden', 'sesskey', null); // automatic sesskey protection |
100 | $this->_form->setDefault('sesskey', sesskey()); |
5bc97c98 |
101 | $this->_form->addElement('hidden', '_qf__'.$this->_formname, null); // form submission marker |
102 | $this->_form->setDefault('_qf__'.$this->_formname, 1); |
103 | $this->_form->_setDefaultRuleMessages(); |
7f40a229 |
104 | |
105 | // we have to know all input types before processing submission ;-) |
106 | $this->_process_submission($method); |
107 | |
05f5c40c |
108 | // update form definition based on final data |
109 | $this->definition_after_data(); |
7f40a229 |
110 | } |
05f5c40c |
111 | |
2c412890 |
112 | /** |
da1320da |
113 | * To autofocus on first form element or first element with error. |
2c412890 |
114 | * |
115 | * @return string javascript to select form element with first error or |
da1320da |
116 | * first element if no errors. Use this as a parameter |
117 | * when calling print_header |
2c412890 |
118 | */ |
119 | function focus(){ |
9403060a |
120 | $form =& $this->_form; |
5c52df67 |
121 | $elkeys=array_keys($form->_elementIndex); |
9403060a |
122 | if (isset($form->_errors) && 0 != count($form->_errors)){ |
123 | $errorkeys = array_keys($form->_errors); |
124 | $elkeys = array_intersect($elkeys, $errorkeys); |
2c412890 |
125 | } |
9403060a |
126 | $names=null; |
127 | while (!$names){ |
128 | $el = array_shift($elkeys); |
129 | $names=$form->_getElNamesRecursive($el); |
130 | } |
131 | $name=array_shift($names); |
132 | $focus='forms[\''.$this->_form->getAttribute('id').'\'].elements[\''.$name.'\']'; |
133 | return $focus; |
134 | } |
7f40a229 |
135 | |
05f5c40c |
136 | /** |
137 | * Internal method. Alters submitted data to be suitable for quickforms processing. |
138 | * Must be called when the form is fully set up. |
139 | */ |
7f40a229 |
140 | function _process_submission($method) { |
141 | $submission = array(); |
142 | if ($method == 'post') { |
143 | if (!empty($_POST)) { |
144 | $submission = $_POST; |
145 | } |
146 | } else { |
147 | $submission = array_merge_recursive($_GET, $_POST); // emulate handling of parameters in xxxx_param() |
148 | } |
149 | |
150 | // following trick is needed to enable proper sesskey checks when using GET forms |
5bc97c98 |
151 | // the _qf__.$this->_formname serves as a marker that form was actually submitted |
152 | if (array_key_exists('_qf__'.$this->_formname, $submission) and $submission['_qf__'.$this->_formname] == 1) { |
7f40a229 |
153 | if (!confirm_sesskey()) { |
154 | error('Incorrect sesskey submitted, form not accepted!'); |
155 | } |
05f5c40c |
156 | $files = $_FILES; |
7f40a229 |
157 | } else { |
158 | $submission = array(); |
05f5c40c |
159 | $files = array(); |
7f40a229 |
160 | } |
161 | |
05f5c40c |
162 | $this->_form->updateSubmission($submission, $files); |
7f40a229 |
163 | } |
164 | |
05f5c40c |
165 | /** |
166 | * Internal method. Validates all uploaded files. |
167 | */ |
49292f8c |
168 | function _validate_files() { |
169 | if (empty($_FILES)) { |
170 | // we do not need to do any checks because no files were submitted |
171 | // TODO: find out why server side required rule does not work for uploaded files; |
172 | // testing is easily done by always returning true from this function and adding |
173 | // $mform->addRule('soubor', get_string('required'), 'required', null, 'server'); |
174 | // and submitting form without selected file |
175 | return true; |
176 | } |
177 | $errors = array(); |
178 | $mform =& $this->_form; |
179 | |
180 | // create default upload manager if not already created |
181 | if (empty($this->_upload_manager)) { |
182 | $this->_upload_manager = new upload_manager(); |
183 | } |
184 | |
185 | // check the files |
186 | $status = $this->_upload_manager->preprocess_files(); |
187 | |
188 | // now check that we really want each file |
189 | foreach ($_FILES as $elname=>$file) { |
190 | if ($mform->elementExists($elname) and $mform->getElementType($elname)=='file') { |
191 | $required = $mform->isElementRequired($elname); |
192 | if (!empty($this->_upload_manager->files[$elname]['uploadlog']) and empty($this->_upload_manager->files[$elname]['clear'])) { |
193 | if (!$required and $file['error'] == UPLOAD_ERR_NO_FILE) { |
194 | // file not uploaded and not required - ignore it |
195 | continue; |
196 | } |
197 | $errors[$elname] = $this->_upload_manager->files[$elname]['uploadlog']; |
198 | } |
199 | } else { |
200 | error('Incorrect upload attemp!'); |
201 | } |
202 | } |
203 | |
204 | // return errors if found |
205 | if ($status and 0 == count($errors)){ |
206 | return true; |
207 | } else { |
208 | return $errors; |
209 | } |
210 | } |
211 | |
05f5c40c |
212 | /** |
da1320da |
213 | * Load in existing data as form defaults. Usually new entry defaults are stored directly in |
214 | * form definition (new entry form); this function is used to load in data where values |
215 | * already exist and data is being edited (edit entry form). |
05f5c40c |
216 | * |
217 | * @param mixed $default_values object or array of default values |
218 | * @param bool $slased true if magic quotes applied to data values |
219 | */ |
7f40a229 |
220 | function set_defaults($default_values, $slashed=false) { |
221 | if (is_object($default_values)) { |
222 | $default_values = (array)$default_values; |
223 | } |
224 | $filter = $slashed ? 'stripslashes' : NULL; |
225 | $this->_form->setDefaults($default_values, $filter); |
38f394b2 |
226 | //update form definition when data changed |
05f5c40c |
227 | $this->definition_after_data(); |
7f40a229 |
228 | } |
229 | |
c80a13c7 |
230 | /** |
231 | * Set maximum allowed uploaded file size. |
232 | * Must be used BEFORE creating of file element! |
233 | * |
234 | * @param object $course |
ebd3c7ac |
235 | * @param object $modbytes - max size limit defined in module |
c80a13c7 |
236 | */ |
237 | function set_max_file_size($course=null, $modbytes=0) { |
238 | global $CFG, $COURSE; |
239 | |
240 | if (empty($course->id)) { |
241 | $course = $COURSE; |
242 | } |
243 | |
244 | $maxbytes = get_max_upload_file_size($CFG->maxbytes, $course->maxbytes, $modbytes); |
245 | $this->_form->setMaxFileSize($maxbytes); |
246 | } |
247 | |
05f5c40c |
248 | /** |
249 | * Check that form was submitted. Does not check validity of submitted data. |
250 | * |
251 | * @return bool true if form properly submitted |
252 | */ |
7f40a229 |
253 | function is_submitted() { |
254 | return $this->_form->isSubmitted(); |
255 | } |
256 | |
05f5c40c |
257 | /** |
258 | * Check that form data is valid. |
259 | * |
260 | * @return bool true if form data valid |
261 | */ |
7f40a229 |
262 | function is_validated() { |
49292f8c |
263 | static $validated = null; // one validation is enough |
3ba2c187 |
264 | $mform =& $this->_form; |
265 | foreach ($mform->_noSubmitButtons as $nosubmitbutton){ |
266 | if (optional_param($nosubmitbutton, 0, PARAM_RAW)){ |
1c51317b |
267 | return false; |
3ba2c187 |
268 | } |
269 | } |
7f40a229 |
270 | if ($validated === null) { |
3ba2c187 |
271 | $internal_val = $mform->validate(); |
272 | $moodle_val = $this->validation($mform->exportValues(null, true)); |
7f40a229 |
273 | if ($moodle_val !== true) { |
274 | if (!empty($moodle_val)) { |
275 | foreach ($moodle_val as $element=>$msg) { |
3ba2c187 |
276 | $mform->setElementError($element, $msg); |
7f40a229 |
277 | } |
278 | } |
279 | $moodle_val = false; |
280 | } |
49292f8c |
281 | $file_val = $this->_validate_files(); |
282 | if ($file_val !== true) { |
283 | if (!empty($file_val)) { |
284 | foreach ($file_val as $element=>$msg) { |
3ba2c187 |
285 | $mform->setElementError($element, $msg); |
49292f8c |
286 | } |
287 | } |
288 | $file_val = false; |
289 | } |
290 | $validated = ($internal_val and $moodle_val and $file_val); |
7f40a229 |
291 | } |
292 | return $validated; |
293 | } |
294 | |
19110c57 |
295 | /** |
296 | * Return true if a cancel button has been pressed resulting in the form being submitted. |
297 | * |
298 | * @return boolean true if a cancel button has been pressed |
299 | */ |
300 | function is_cancelled(){ |
301 | $mform =& $this->_form; |
302 | foreach ($mform->_cancelButtons as $cancelbutton){ |
3ba2c187 |
303 | if (optional_param($cancelbutton, 0, PARAM_RAW)){ |
19110c57 |
304 | return true; |
305 | } |
306 | } |
307 | return false; |
308 | } |
309 | |
05f5c40c |
310 | /** |
da1320da |
311 | * Return submitted data if properly submitted or returns NULL if validation fails or |
312 | * if there is no submitted data. |
05f5c40c |
313 | * |
314 | * @param bool $slashed true means return data with addslashes applied |
315 | * @return object submitted data; NULL if not valid or not submitted |
316 | */ |
7f40a229 |
317 | function data_submitted($slashed=true) { |
19110c57 |
318 | $mform =& $this->_form; |
3ba2c187 |
319 | |
7f40a229 |
320 | if ($this->is_submitted() and $this->is_validated()) { |
19110c57 |
321 | $data = $mform->exportValues(null, $slashed); |
5bc97c98 |
322 | unset($data['sesskey']); // we do not need to return sesskey |
323 | unset($data['_qf__'.$this->_formname]); // we do not need the submission marker too |
7f40a229 |
324 | if (empty($data)) { |
325 | return NULL; |
326 | } else { |
327 | return (object)$data; |
328 | } |
329 | } else { |
330 | return NULL; |
331 | } |
332 | } |
333 | |
05f5c40c |
334 | /** |
335 | * Save verified uploaded files into directory. Upload process can be customised from definition() |
38f394b2 |
336 | * method by creating instance of upload manager and storing it in $this->_upload_form |
05f5c40c |
337 | * |
338 | * @param string $destination where to store uploaded files |
339 | * @return bool success |
340 | */ |
49292f8c |
341 | function save_files($destination) { |
342 | if (empty($this->_upload_manager)) { |
343 | return false; |
344 | } |
345 | if ($this->is_submitted() and $this->is_validated()) { |
346 | return $this->_upload_manager->save_files($destination); |
347 | } |
348 | return false; |
349 | } |
2b63df96 |
350 | |
05f5c40c |
351 | /** |
352 | * Print html form. |
353 | */ |
7f40a229 |
354 | function display() { |
355 | $this->_form->display(); |
356 | } |
357 | |
49292f8c |
358 | /** |
05f5c40c |
359 | * Abstract method - always override! |
49292f8c |
360 | * |
361 | * If you need special handling of uploaded files, create instance of $this->_upload_manager here. |
362 | */ |
7f40a229 |
363 | function definition() { |
364 | error('Abstract form_definition() method in class '.get_class($this).' must be overriden, please fix the code.'); |
365 | } |
2c412890 |
366 | |
c08ac016 |
367 | /** |
05f5c40c |
368 | * Dummy stub method - override if you need to setup the form depending on current |
369 | * values. This method is called after definition(), data submission and set_defaults(). |
370 | * All form setup that is dependent on form values should go in here. |
c08ac016 |
371 | */ |
372 | function definition_after_data(){ |
c08ac016 |
373 | } |
7f40a229 |
374 | |
05f5c40c |
375 | /** |
376 | * Dummy stub method - override if you needed to perform some extra validation. |
377 | * If there are errors return array of errors ("fieldname"=>"error message"), |
378 | * otherwise true if ok. |
38f394b2 |
379 | * |
05f5c40c |
380 | * @param array $data array of ("fieldname"=>value) of submitted data |
38f394b2 |
381 | * @return bool array of errors or true if ok |
05f5c40c |
382 | */ |
7f40a229 |
383 | function validation($data) { |
7f40a229 |
384 | return true; |
385 | } |
ebd3c7ac |
386 | |
19110c57 |
387 | |
ebd3c7ac |
388 | |
616b549a |
389 | /** |
390 | * Method to add a repeating group of elements to a form. |
391 | * |
392 | * @param array $elementobjs Array of elements or groups of elements that are to be repeated |
393 | * @param integer $repeats no of times to repeat elements initially |
394 | * @param array $options Array of options to apply to elements. Array keys are element names. |
395 | * This is an array of arrays. The second sets of keys are the option types |
396 | * for the elements : |
397 | * 'default' - default value is value |
398 | * 'type' - PARAM_* constant is value |
399 | * 'helpbutton' - helpbutton params array is value |
400 | * 'disabledif' - last three moodleform::disabledIf() |
401 | * params are value as an array |
402 | * @param string $repeathiddenname name for hidden element storing no of repeats in this form |
403 | * @param string $addfieldsname name for button to add more fields |
404 | * @param int $addfieldsno how many fields to add at a time |
405 | * @param array $addstring array of params for get_string for name of button, $a is no of fields that |
406 | * will be added. |
407 | */ |
ebd3c7ac |
408 | function repeat_elements($elementobjs, $repeats, $options, $repeathiddenname, $addfieldsname, $addfieldsno=5, $addstring=array('addfields', 'form')){ |
409 | $repeats = optional_param($repeathiddenname, $repeats, PARAM_INT); |
410 | $addfields = optional_param($addfieldsname, '', PARAM_TEXT); |
411 | if (!empty($addfields)){ |
412 | $repeats += $addfieldsno; |
413 | } |
ebd3c7ac |
414 | $mform =& $this->_form; |
19110c57 |
415 | $mform->_registerNoSubmitButton($addfieldsname); |
ebd3c7ac |
416 | $mform->addElement('hidden', $repeathiddenname, $repeats); |
417 | //value not to be overridden by submitted value |
418 | $mform->setConstants(array($repeathiddenname=>$repeats)); |
419 | for ($i=0; $i<$repeats; $i++) { |
420 | foreach ($elementobjs as $elementobj){ |
421 | $elementclone=clone($elementobj); |
422 | $name=$elementclone->getName(); |
423 | $elementclone->setName($name."[$i]"); |
424 | if (is_a($elementclone, 'HTML_QuickForm_header')){ |
425 | $value=$elementclone->_text; |
426 | $elementclone->setValue($value.' '.($i+1)); |
427 | |
428 | } |
429 | $mform->addElement($elementclone); |
430 | } |
431 | } |
432 | for ($i=0; $i<$repeats; $i++) { |
433 | foreach ($options as $elementname => $elementoptions){ |
434 | $pos=strpos($elementname, '['); |
435 | if ($pos!==FALSE){ |
436 | $realelementname = substr($elementname, 0, $pos+1)."[$i]"; |
437 | $realelementname .= substr($elementname, $pos+1); |
438 | }else { |
439 | $realelementname = $elementname."[$i]"; |
440 | } |
441 | foreach ($elementoptions as $option => $params){ |
442 | |
443 | switch ($option){ |
444 | case 'default' : |
445 | $mform->setDefault($realelementname, $params); |
446 | break; |
447 | case 'type' : |
448 | $mform->setType($realelementname, $params); |
449 | break; |
450 | case 'helpbutton' : |
451 | $mform->setHelpButton($realelementname, $params); |
452 | break; |
453 | case 'disabledif' : |
454 | $mform->disabledIf($realelementname, $params[0], $params[1], $params[2]); |
455 | break; |
456 | |
457 | } |
458 | } |
459 | } |
460 | } |
461 | $mform->addElement('submit', $addfieldsname, get_string('addfields', 'form', $addfieldsno), |
462 | array('onclick'=>'this.form.submit();'));//need this to bypass client validation |
463 | |
e35c9eeb |
464 | $renderer =& $mform->defaultRenderer(); |
ebd3c7ac |
465 | $renderer->addStopFieldsetElements($addfieldsname); |
466 | |
467 | } |
7f40a229 |
468 | } |
469 | |
da1320da |
470 | /** |
471 | * You never extend this class directly. The class methods of this class are available from |
472 | * the private $this->_form property on moodleform and it's children. You generally only |
473 | * call methods on this class from within abstract methods that you override on moodleform such |
474 | * as definition and definition_after_data |
475 | * |
476 | */ |
7f40a229 |
477 | class MoodleQuickForm extends HTML_QuickForm_DHTMLRulesTableless { |
478 | var $_types = array(); |
50ef8eb9 |
479 | var $_dependencies = array(); |
19110c57 |
480 | /** |
481 | * Array of buttons that if pressed do not result in the processing of the form. |
482 | * |
483 | * @var array |
484 | */ |
485 | var $_noSubmitButtons=array(); |
486 | /** |
487 | * Array of buttons that if pressed do not result in the processing of the form. |
488 | * |
489 | * @var array |
490 | */ |
491 | var $_cancelButtons=array(); |
7f40a229 |
492 | |
da6f8763 |
493 | /** |
494 | * Class constructor - same parameters as HTML_QuickForm_DHTMLRulesTableless |
495 | * @param string $formName Form's name. |
496 | * @param string $method (optional)Form's method defaults to 'POST' |
497 | * @param string $action (optional)Form's action |
498 | * @param string $target (optional)Form's target defaults to none |
499 | * @param mixed $attributes (optional)Extra attributes for <form> tag |
500 | * @param bool $trackSubmit (optional)Whether to track if the form was submitted by adding a special hidden field |
501 | * @access public |
502 | */ |
7f40a229 |
503 | function MoodleQuickForm($formName, $method, $action, $target='', $attributes=null){ |
da6f8763 |
504 | global $CFG; |
7f40a229 |
505 | |
da6f8763 |
506 | HTML_Common::HTML_Common($attributes); |
da6f8763 |
507 | $target = empty($target) ? array() : array('target' => $target); |
508 | //no 'name' atttribute for form in xhtml strict : |
509 | $attributes = array('action'=>$action, 'method'=>$method, 'id'=>$formName) + $target; |
510 | $this->updateAttributes($attributes); |
da6f8763 |
511 | |
7f40a229 |
512 | //this is custom stuff for Moodle : |
da6f8763 |
513 | $oldclass= $this->getAttribute('class'); |
514 | if (!empty($oldclass)){ |
515 | $this->updateAttributes(array('class'=>$oldclass.' mform')); |
516 | }else { |
80f962df |
517 | $this->updateAttributes(array('class'=>'mform')); |
da6f8763 |
518 | } |
7f40a229 |
519 | $this->_helpImageURL="$CFG->wwwroot/lib/form/req.gif"; |
3d685169 |
520 | $this->_reqHTML = '<img alt="'.get_string('requiredelement', 'form').'" src="'.$this->_helpImageURL.'" />'; |
521 | $this->setRequiredNote(get_string('denotesreq', 'form', |
da6f8763 |
522 | helpbutton('requiredelement', get_string('requiredelement', 'form'),'moodle', |
3ba2c187 |
523 | true, false, '', true, '<img alt="'.get_string('requiredelement', 'form').'" src="'. |
3d685169 |
524 | $this->_helpImageURL.'" />'))); |
da6f8763 |
525 | } |
bb40325e |
526 | |
da1320da |
527 | /** |
528 | * Should be used for all elements of a form except for select, radio and checkboxes which |
529 | * clean their own data. |
530 | * |
531 | * @param string $elementname |
532 | * @param integer $paramtype use the constants PARAM_*. |
533 | * * PARAM_CLEAN is deprecated and you should try to use a more specific type. |
534 | * * PARAM_TEXT should be used for cleaning data that is expected to be plain text. |
535 | * It will strip all html tags. But will still let tags for multilang support |
536 | * through. |
537 | * * PARAM_RAW means no cleaning whatsoever, it is used mostly for data from the |
538 | * html editor. Data from the editor is later cleaned before display using |
539 | * format_text() function. PARAM_RAW can also be used for data that is validated |
540 | * by some other way or printed by p() or s(). |
541 | * * PARAM_INT should be used for integers. |
542 | * * PARAM_ACTION is an alias of PARAM_ALPHA and is used for hidden fields specifying |
543 | * form actions. |
544 | */ |
7f40a229 |
545 | function setType($elementname, $paramtype) { |
546 | $this->_types[$elementname] = $paramtype; |
547 | } |
49292f8c |
548 | |
da1320da |
549 | /** |
550 | * See description of setType above. This can be used to set several types at once. |
551 | * |
552 | * @param array $paramtypes |
553 | */ |
c56f1826 |
554 | function setTypes($paramtypes) { |
555 | $this->_types = $paramtypes + $this->_types; |
556 | } |
49292f8c |
557 | |
558 | function updateSubmission($submission, $files) { |
559 | $this->_flagSubmitted = false; |
560 | |
7f40a229 |
561 | if (empty($submission)) { |
562 | $this->_submitValues = array(); |
7f40a229 |
563 | } else { |
564 | foreach ($submission as $key=>$s) { |
565 | if (array_key_exists($key, $this->_types)) { |
566 | $submission[$key] = clean_param($s, $this->_types[$key]); |
567 | } |
568 | } |
569 | $this->_submitValues = $this->_recursiveFilter('stripslashes', $submission); |
570 | $this->_flagSubmitted = true; |
571 | } |
572 | |
49292f8c |
573 | if (empty($files)) { |
574 | $this->_submitFiles = array(); |
575 | } else { |
576 | if (1 == get_magic_quotes_gpc()) { |
577 | foreach ($files as $elname=>$file) { |
578 | // dangerous characters in filenames are cleaned later in upload_manager |
579 | $files[$elname]['name'] = stripslashes($files[$elname]['name']); |
580 | } |
581 | } |
582 | $this->_submitFiles = $files; |
583 | $this->_flagSubmitted = true; |
584 | } |
585 | |
2c412890 |
586 | // need to tell all elements that they need to update their value attribute. |
587 | foreach (array_keys($this->_elements) as $key) { |
588 | $this->_elements[$key]->onQuickFormEvent('updateValue', null, $this); |
589 | } |
7f40a229 |
590 | } |
591 | |
da6f8763 |
592 | function getReqHTML(){ |
593 | return $this->_reqHTML; |
594 | } |
7f40a229 |
595 | |
596 | /** |
da1320da |
597 | * Initializes a default form value. Used to specify the default for a new entry where |
598 | * no data is loaded in using moodleform::set_defaults() |
7f40a229 |
599 | * |
600 | * @param string $elementname element name |
601 | * @param mixed $values values for that element name |
602 | * @param bool $slashed the default value is slashed |
603 | * @access public |
604 | * @return void |
605 | */ |
606 | function setDefault($elementName, $defaultValue, $slashed=false){ |
607 | $filter = $slashed ? 'stripslashes' : NULL; |
608 | $this->setDefaults(array($elementName=>$defaultValue), $filter); |
609 | } // end func setDefault |
da6f8763 |
610 | /** |
c56f1826 |
611 | * Add an array of buttons to the form |
7f40a229 |
612 | * @param array $buttons An associative array representing help button to attach to |
da6f8763 |
613 | * to the form. keys of array correspond to names of elements in form. |
7f40a229 |
614 | * |
da6f8763 |
615 | * @access public |
616 | */ |
d4fe14d3 |
617 | function setHelpButtons($buttons, $suppresscheck=false, $function='helpbutton'){ |
7f40a229 |
618 | |
c56f1826 |
619 | foreach ($buttons as $elementname => $button){ |
d4fe14d3 |
620 | $this->setHelpButton($elementname, $button, $suppresscheck, $function); |
da6f8763 |
621 | } |
622 | } |
c56f1826 |
623 | /** |
da1320da |
624 | * Add a single button. |
c56f1826 |
625 | * |
626 | * @param string $elementname name of the element to add the item to |
d4fe14d3 |
627 | * @param array $button - arguments to pass to function $function |
c56f1826 |
628 | * @param boolean $suppresscheck - whether to throw an error if the element |
629 | * doesn't exist. |
d4fe14d3 |
630 | * @param string $function - function to generate html from the arguments in $button |
c56f1826 |
631 | */ |
d4fe14d3 |
632 | function setHelpButton($elementname, $button, $suppresscheck=false, $function='helpbutton'){ |
c56f1826 |
633 | if (array_key_exists($elementname, $this->_elementIndex)){ |
634 | //_elements has a numeric index, this code accesses the elements by name |
635 | $element=&$this->_elements[$this->_elementIndex[$elementname]]; |
636 | if (method_exists($element, 'setHelpButton')){ |
d4fe14d3 |
637 | $element->setHelpButton($button, $function); |
c56f1826 |
638 | }else{ |
639 | $a=new object(); |
640 | $a->name=$element->getName(); |
641 | $a->classname=get_class($element); |
642 | print_error('nomethodforaddinghelpbutton', 'form', '', $a); |
643 | } |
644 | }elseif (!$suppresscheck){ |
645 | print_error('nonexistentformelements', 'form', '', $elementname); |
2c412890 |
646 | } |
c56f1826 |
647 | } |
7f40a229 |
648 | |
42f248e6 |
649 | function exportValues($elementList= null, $addslashes=true){ |
da6f8763 |
650 | $unfiltered=parent::exportValues($elementList); |
7f40a229 |
651 | |
da6f8763 |
652 | if ($addslashes){ |
42f248e6 |
653 | return $this->_recursiveFilter('addslashes',$unfiltered); |
da6f8763 |
654 | } else { |
655 | return $unfiltered; |
656 | } |
657 | } |
5bc97c98 |
658 | /** |
659 | * Returns the client side validation script |
660 | * |
661 | * The code here was copied from HTML_QuickForm_DHTMLRulesTableless who copied it from HTML_QuickForm |
662 | * and slightly modified to run rules per-element |
663 | * Needed to override this because of an error with client side validation of grouped elements. |
664 | * |
665 | * @access public |
666 | * @return string Javascript to perform validation, empty string if no 'client' rules were added |
667 | */ |
668 | function getValidationScript() |
669 | { |
670 | if (empty($this->_rules) || empty($this->_attributes['onsubmit'])) { |
671 | return ''; |
672 | } |
673 | |
674 | include_once('HTML/QuickForm/RuleRegistry.php'); |
675 | $registry =& HTML_QuickForm_RuleRegistry::singleton(); |
676 | $test = array(); |
677 | $js_escape = array( |
678 | "\r" => '\r', |
679 | "\n" => '\n', |
680 | "\t" => '\t', |
681 | "'" => "\\'", |
682 | '"' => '\"', |
683 | '\\' => '\\\\' |
684 | ); |
685 | |
686 | foreach ($this->_rules as $elementName => $rules) { |
687 | foreach ($rules as $rule) { |
688 | if ('client' == $rule['validation']) { |
da1320da |
689 | unset($element); //TODO: find out how to properly initialize it |
5bc97c98 |
690 | |
691 | $dependent = isset($rule['dependent']) && is_array($rule['dependent']); |
692 | $rule['message'] = strtr($rule['message'], $js_escape); |
693 | |
694 | if (isset($rule['group'])) { |
695 | $group =& $this->getElement($rule['group']); |
696 | // No JavaScript validation for frozen elements |
697 | if ($group->isFrozen()) { |
698 | continue 2; |
699 | } |
700 | $elements =& $group->getElements(); |
701 | foreach (array_keys($elements) as $key) { |
702 | if ($elementName == $group->getElementName($key)) { |
703 | $element =& $elements[$key]; |
704 | break; |
705 | } |
706 | } |
707 | } elseif ($dependent) { |
708 | $element = array(); |
709 | $element[] =& $this->getElement($elementName); |
710 | foreach ($rule['dependent'] as $idx => $elName) { |
711 | $element[] =& $this->getElement($elName); |
712 | } |
713 | } else { |
714 | $element =& $this->getElement($elementName); |
715 | } |
716 | // No JavaScript validation for frozen elements |
717 | if (is_object($element) && $element->isFrozen()) { |
718 | continue 2; |
719 | } elseif (is_array($element)) { |
720 | foreach (array_keys($element) as $key) { |
721 | if ($element[$key]->isFrozen()) { |
722 | continue 3; |
723 | } |
724 | } |
725 | } |
726 | // Fix for bug displaying errors for elements in a group |
727 | //$test[$elementName][] = $registry->getValidationScript($element, $elementName, $rule); |
728 | $test[$elementName][0][] = $registry->getValidationScript($element, $elementName, $rule); |
729 | $test[$elementName][1]=$element; |
730 | //end of fix |
731 | } |
732 | } |
733 | } |
734 | $js = ' |
735 | <script type="text/javascript"> |
736 | //<![CDATA[ |
1cbb09f1 |
737 | |
738 | var skipClientValidation = false; |
739 | |
5bc97c98 |
740 | function qf_errorHandler(element, _qfMsg) { |
741 | div = element.parentNode; |
742 | if (_qfMsg != \'\') { |
e35c9eeb |
743 | var errorSpan = document.getElementById(\'id_error_\'+element.name); |
e7004d05 |
744 | if (!errorSpan) { |
745 | errorSpan = document.createElement("span"); |
e35c9eeb |
746 | errorSpan.id = \'id_error_\'+element.name; |
747 | errorSpan.className = "error"; |
fed13a5e |
748 | element.parentNode.insertBefore(errorSpan, element.parentNode.firstChild); |
5bc97c98 |
749 | } |
fed13a5e |
750 | |
e7004d05 |
751 | while (errorSpan.firstChild) { |
752 | errorSpan.removeChild(errorSpan.firstChild); |
5bc97c98 |
753 | } |
2c412890 |
754 | |
e7004d05 |
755 | errorSpan.appendChild(document.createTextNode(_qfMsg.substring(3))); |
e35c9eeb |
756 | errorSpan.appendChild(document.createElement("br")); |
5bc97c98 |
757 | |
758 | if (div.className.substr(div.className.length - 6, 6) != " error" |
759 | && div.className != "error") { |
760 | div.className += " error"; |
761 | } |
762 | |
763 | return false; |
764 | } else { |
e35c9eeb |
765 | var errorSpan = document.getElementById(\'id_error_\'+element.name); |
e7004d05 |
766 | if (errorSpan) { |
767 | errorSpan.parentNode.removeChild(errorSpan); |
5bc97c98 |
768 | } |
769 | |
770 | if (div.className.substr(div.className.length - 6, 6) == " error") { |
771 | div.className = div.className.substr(0, div.className.length - 6); |
772 | } else if (div.className == "error") { |
773 | div.className = ""; |
774 | } |
775 | |
776 | return true; |
777 | } |
778 | }'; |
779 | $validateJS = ''; |
780 | foreach ($test as $elementName => $jsandelement) { |
781 | // Fix for bug displaying errors for elements in a group |
782 | //unset($element); |
783 | list($jsArr,$element)=$jsandelement; |
784 | //end of fix |
785 | $js .= ' |
786 | function validate_' . $this->_attributes['id'] . '_' . $elementName . '(element) { |
787 | var value = \'\'; |
788 | var errFlag = new Array(); |
789 | var _qfGroups = {}; |
790 | var _qfMsg = \'\'; |
791 | var frm = element.parentNode; |
792 | while (frm && frm.nodeName != "FORM") { |
793 | frm = frm.parentNode; |
794 | } |
795 | ' . join("\n", $jsArr) . ' |
796 | return qf_errorHandler(element, _qfMsg); |
797 | } |
798 | '; |
799 | $validateJS .= ' |
800 | ret = validate_' . $this->_attributes['id'] . '_' . $elementName.'(frm.elements[\''.$elementName.'\']) && ret;'; |
801 | // Fix for bug displaying errors for elements in a group |
802 | //unset($element); |
803 | //$element =& $this->getElement($elementName); |
804 | //end of fix |
805 | $valFunc = 'validate_' . $this->_attributes['id'] . '_' . $elementName . '(this)'; |
806 | $onBlur = $element->getAttribute('onBlur'); |
807 | $onChange = $element->getAttribute('onChange'); |
808 | $element->updateAttributes(array('onBlur' => $onBlur . $valFunc, |
809 | 'onChange' => $onChange . $valFunc)); |
810 | } |
e7004d05 |
811 | // do not rely on frm function parameter, because htmlarea breaks it when overloading the onsubmit method |
5bc97c98 |
812 | $js .= ' |
813 | function validate_' . $this->_attributes['id'] . '(frm) { |
1cbb09f1 |
814 | if (skipClientValidation) { |
815 | return true; |
816 | } |
5bc97c98 |
817 | var ret = true; |
0befbdfd |
818 | |
819 | var frm = document.getElementById(\''. $this->_attributes['id'] .'\') |
820 | |
5bc97c98 |
821 | ' . $validateJS . '; |
822 | return ret; |
823 | } |
824 | //]]> |
825 | </script>'; |
826 | return $js; |
827 | } // end func getValidationScript |
828 | function _setDefaultRuleMessages(){ |
829 | foreach ($this->_rules as $field => $rulesarr){ |
830 | foreach ($rulesarr as $key => $rule){ |
831 | if ($rule['message']===null){ |
832 | $a=new object(); |
833 | $a->format=$rule['format']; |
834 | $str=get_string('err_'.$rule['type'], 'form', $a); |
835 | if (strpos($str, '[[')!==0){ |
836 | $this->_rules[$field][$key]['message']=$str; |
2c412890 |
837 | } |
5bc97c98 |
838 | } |
839 | } |
840 | } |
841 | } |
bb40325e |
842 | |
d01a38cb |
843 | function getLockOptionEndScript(){ |
50ef8eb9 |
844 | $js = '<script type="text/javascript" language="javascript">'."\n"; |
845 | $js .= "var ".$this->getAttribute('id')."items= {"; |
846 | foreach ($this->_dependencies as $dependentOn => $elements){ |
46e648b6 |
847 | $js .= "'$dependentOn'".' : {dependents :['; |
50ef8eb9 |
848 | foreach ($elements as $element){ |
11f260f4 |
849 | $elementNames = $this->_getElNamesRecursive($element['dependent']); |
850 | foreach ($elementNames as $dependent){ |
851 | if ($dependent != $dependentOn) { |
852 | $js.="'".$dependent."', "; |
853 | } |
854 | } |
50ef8eb9 |
855 | } |
856 | $js=rtrim($js, ', '); |
857 | $js .= "],\n"; |
e24b7f85 |
858 | $js .= "condition : '{$element['condition']}',\n"; |
859 | $js .= "value : '{$element['value']}'},\n"; |
50ef8eb9 |
860 | |
861 | }; |
862 | $js=rtrim($js, ",\n"); |
863 | $js .= '};'."\n"; |
d01a38cb |
864 | $js .="lockoptionsallsetup('".$this->getAttribute('id')."');\n"; |
50ef8eb9 |
865 | $js .='</script>'."\n"; |
866 | return $js; |
bb40325e |
867 | } |
d01a38cb |
868 | |
869 | function _getElNamesRecursive(&$element, $group=null){ |
870 | if ($group==null){ |
9403060a |
871 | $el = $this->getElement($element); |
d01a38cb |
872 | } else { |
9403060a |
873 | $el = &$element; |
d01a38cb |
874 | } |
875 | if (is_a($el, 'HTML_QuickForm_group')){ |
9403060a |
876 | $group = $el; |
877 | $elsInGroup = $group->getElements(); |
878 | $elNames = array(); |
d01a38cb |
879 | foreach ($elsInGroup as $elInGroup){ |
880 | $elNames = array_merge($elNames, $this->_getElNamesRecursive($elInGroup, $group)); |
881 | } |
882 | }else{ |
9403060a |
883 | if ($group != null){ |
884 | $elNames = array($group->getElementName($el->getName())); |
885 | } elseif (is_a($el, 'HTML_QuickForm_header')) { |
886 | return null; |
2dbd6409 |
887 | } elseif (method_exists($el, 'getPrivateName')) { |
888 | return array($el->getPrivateName()); |
d01a38cb |
889 | } else { |
9403060a |
890 | $elNames = array($el->getName()); |
d01a38cb |
891 | } |
892 | } |
893 | return $elNames; |
894 | |
50ef8eb9 |
895 | } |
6e372b25 |
896 | /** |
897 | * Adds a dependency for $elementName which will be disabled if $condition is met. |
9403060a |
898 | * If $condition = 'notchecked' (default) then the condition is that the $dependentOn element |
899 | * is not checked. If $condition = 'checked' then the condition is that the $dependentOn element |
6e372b25 |
900 | * is checked. If $condition is something else then it is checked to see if the value |
901 | * of the $dependentOn element is equal to $condition. |
902 | * |
903 | * @param string $elementName the name of the element which will be disabled |
904 | * @param string $dependentOn the name of the element whose state will be checked for |
905 | * condition |
906 | * @param string $condition the condition to check |
19110c57 |
907 | * @param mixed $value used in conjunction with condition. |
6e372b25 |
908 | */ |
e24b7f85 |
909 | function disabledIf($elementName, $dependentOn, $condition = 'notchecked', $value=null){ |
11f260f4 |
910 | $this->_dependencies[$dependentOn][] = array('dependent'=>$elementName, |
e24b7f85 |
911 | 'condition'=>$condition, 'value'=>$value); |
bb40325e |
912 | } |
19110c57 |
913 | function _registerNoSubmitButton($addfieldsname){ |
914 | $this->_noSubmitButtons[]=$addfieldsname; |
915 | } |
916 | function _registerCancelButton($addfieldsname){ |
917 | $this->_cancelButtons[]=$addfieldsname; |
918 | } |
da6f8763 |
919 | } |
920 | |
e24b7f85 |
921 | |
da6f8763 |
922 | /** |
7f40a229 |
923 | * A renderer for MoodleQuickForm that only uses XHTML and CSS and no |
da6f8763 |
924 | * table tags, extends PEAR class HTML_QuickForm_Renderer_Tableless |
7f40a229 |
925 | * |
da6f8763 |
926 | * Stylesheet is part of standard theme and should be automatically included. |
927 | * |
928 | * @author Jamie Pratt <me@jamiep.org> |
929 | * @license gpl license |
930 | */ |
7f40a229 |
931 | class MoodleQuickForm_Renderer extends HTML_QuickForm_Renderer_Tableless{ |
da6f8763 |
932 | |
933 | /** |
934 | * Element template array |
935 | * @var array |
936 | * @access private |
937 | */ |
938 | var $_elementTemplates; |
42f248e6 |
939 | |
49c53687 |
940 | // uncomment templates below and edit formslib.php for |
42f248e6 |
941 | // ol li containers for form items. |
942 | |
49c53687 |
943 | /** |
944 | * Template used when opening a hidden fieldset |
945 | * (i.e. a fieldset that is opened when there is no header element) |
946 | * @var string |
947 | * @access private |
948 | */ |
949 | var $_openHiddenFieldsetTemplate = "\n\t<fieldset class=\"hidden\">"; |
42f248e6 |
950 | // var $_openHiddenFieldsetTemplate = "\n\t<fieldset class=\"hidden\">\n\t\t<ol>"; |
951 | // /** |
952 | // * Header Template string |
953 | // * @var string |
954 | // * @access private |
955 | // */ |
7f40a229 |
956 | // var $_headerTemplate = |
42f248e6 |
957 | // "\n\t\t<legend>{header}</legend>\n\t\t<ol>"; |
7f40a229 |
958 | // var $_headerTemplate = |
49c53687 |
959 | // "\n\t\t<legend>{header}</legend>\n\t\t<ol>"; |
7f40a229 |
960 | |
49c53687 |
961 | /** |
962 | * Template used when closing a fieldset |
963 | * @var string |
964 | * @access private |
965 | */ |
966 | var $_closeFieldsetTemplate = "\n\t\t</fieldset>"; |
42f248e6 |
967 | // var $_closeFieldsetTemplate = "\n\t\t</ol>\n\t</fieldset>"; |
968 | |
49c53687 |
969 | /** |
970 | * Required Note template string |
971 | * @var string |
972 | * @access private |
973 | */ |
7f40a229 |
974 | var $_requiredNoteTemplate = |
49c53687 |
975 | "\n\t\t<div class=\"fdescription\">{requiredNote}</div>"; |
7f40a229 |
976 | |
977 | function MoodleQuickForm_Renderer(){ |
42f248e6 |
978 | // switch next two lines for ol li containers for form items. |
49c53687 |
979 | // $this->_elementTemplates=array('default'=>"\n\t\t<li class=\"fitem\"><label>{label}{help}<!-- BEGIN required -->{req}<!-- END required --></label><div class=\"qfelement<!-- BEGIN error --> error<!-- END error --> {type}\"><!-- BEGIN error --><span class=\"error\">{error}</span><br /><!-- END error -->{element}</div></li>"); |
e7004d05 |
980 | $this->_elementTemplates = array('default'=>"\n\t\t<div class=\"fitem\"><span class=\"fitemtitle\"><label>{label}<!-- BEGIN required -->{req}<!-- END required --></label>{help}</span><div class=\"felement {type}<!-- BEGIN error --> error<!-- END error -->\"><!-- BEGIN error --><span class=\"error\" id=\"id_error_{name}\">{error}</span><br /><!-- END error -->{element}</div></div>", |
981 | 'fieldset'=>"\n\t\t<div class=\"fitem\"><span class=\"fitemtitle\"><label>{label}<!-- BEGIN required -->{req}<!-- END required --></label>{help}</span><fieldset class=\"felement {type}<!-- BEGIN error --> error<!-- END error -->\"><!-- BEGIN error --><span class=\"error\" id=\"id_error_{name}\">{error}</span><br /><!-- END error -->{element}</fieldset></div>"); |
da6f8763 |
982 | |
983 | parent::HTML_QuickForm_Renderer_Tableless(); |
984 | } |
7f40a229 |
985 | |
da6f8763 |
986 | function startForm(&$form){ |
9403060a |
987 | $this->_reqHTML = $form->getReqHTML(); |
988 | $this->_elementTemplates = str_replace('{req}', $this->_reqHTML, $this->_elementTemplates); |
da6f8763 |
989 | parent::startForm($form); |
990 | } |
7f40a229 |
991 | |
da6f8763 |
992 | function startGroup(&$group, $required, $error){ |
993 | if (method_exists($group, 'getElementTemplateType')){ |
e249661f |
994 | $html = $this->_elementTemplates[$group->getElementTemplateType()]; |
da6f8763 |
995 | }else{ |
996 | $html = $this->_elementTemplates['default']; |
7f40a229 |
997 | |
da6f8763 |
998 | } |
999 | if (method_exists($group, 'getHelpButton')){ |
1000 | $html =str_replace('{help}', $group->getHelpButton(), $html); |
1001 | }else{ |
1002 | $html =str_replace('{help}', '', $html); |
7f40a229 |
1003 | |
da6f8763 |
1004 | } |
e7004d05 |
1005 | $html =str_replace('{name}', $group->getName(), $html); |
49c53687 |
1006 | $html =str_replace('{type}', 'fgroup', $html); |
7f40a229 |
1007 | |
da6f8763 |
1008 | $this->_templates[$group->getName()]=$html; |
1009 | // Fix for bug in tableless quickforms that didn't allow you to stop a |
1010 | // fieldset before a group of elements. |
1011 | // if the element name indicates the end of a fieldset, close the fieldset |
1012 | if ( in_array($group->getName(), $this->_stopFieldsetElements) |
1013 | && $this->_fieldsetsOpen > 0 |
1014 | ) { |
1015 | $this->_html .= $this->_closeFieldsetTemplate; |
1016 | $this->_fieldsetsOpen--; |
1017 | } |
1018 | parent::startGroup($group, $required, $error); |
1019 | } |
7f40a229 |
1020 | |
da6f8763 |
1021 | function renderElement(&$element, $required, $error){ |
1022 | if (method_exists($element, 'getElementTemplateType')){ |
1023 | $html = $this->_elementTemplates[$element->getElementTemplateType()]; |
1024 | }else{ |
1025 | $html = $this->_elementTemplates['default']; |
7f40a229 |
1026 | |
da6f8763 |
1027 | } |
49c53687 |
1028 | $html =str_replace('{type}', 'f'.$element->getType(), $html); |
e7004d05 |
1029 | $html =str_replace('{name}', $element->getName(), $html); |
da6f8763 |
1030 | if (method_exists($element, 'getHelpButton')){ |
9403060a |
1031 | $html = str_replace('{help}', $element->getHelpButton(), $html); |
da6f8763 |
1032 | }else{ |
9403060a |
1033 | $html = str_replace('{help}', '', $html); |
7f40a229 |
1034 | |
da6f8763 |
1035 | } |
9403060a |
1036 | $this->_templates[$element->getName()] = $html; |
230a910a |
1037 | if (!is_null($element->getAttribute('id'))) { |
1038 | $id = $element->getAttribute('id'); |
1039 | } else { |
1040 | $id = $element->getName(); |
1041 | } |
44875d78 |
1042 | $id = preg_replace('/^qf_/', '', $id, 1); |
1043 | if (strpos($id, 'id_') !== 0){ |
1044 | $element->updateAttributes(array('id'=>'id_'.$id)); |
1045 | } |
da6f8763 |
1046 | parent::renderElement($element, $required, $error); |
1047 | } |
bb40325e |
1048 | function finishForm(&$form){ |
1049 | parent::finishForm($form); |
d01a38cb |
1050 | // add a lockoptions script |
bb40325e |
1051 | if ('' != ($script = $form->getLockOptionEndScript())) { |
1052 | $this->_html = $this->_html . "\n" . $script; |
1053 | } |
1054 | } |
da6f8763 |
1055 | } |
1056 | |
da6f8763 |
1057 | |
9403060a |
1058 | $GLOBALS['_HTML_QuickForm_default_renderer'] =& new MoodleQuickForm_Renderer(); |
da6f8763 |
1059 | |
7f40a229 |
1060 | MoodleQuickForm::registerElementType('checkbox', "$CFG->libdir/form/checkbox.php", 'MoodleQuickForm_checkbox'); |
1061 | MoodleQuickForm::registerElementType('file', "$CFG->libdir/form/file.php", 'MoodleQuickForm_file'); |
1062 | MoodleQuickForm::registerElementType('group', "$CFG->libdir/form/group.php", 'MoodleQuickForm_group'); |
1063 | MoodleQuickForm::registerElementType('password', "$CFG->libdir/form/password.php", 'MoodleQuickForm_password'); |
1064 | MoodleQuickForm::registerElementType('radio', "$CFG->libdir/form/radio.php", 'MoodleQuickForm_radio'); |
1065 | MoodleQuickForm::registerElementType('select', "$CFG->libdir/form/select.php", 'MoodleQuickForm_select'); |
1066 | MoodleQuickForm::registerElementType('text', "$CFG->libdir/form/text.php", 'MoodleQuickForm_text'); |
1067 | MoodleQuickForm::registerElementType('textarea', "$CFG->libdir/form/textarea.php", 'MoodleQuickForm_textarea'); |
1068 | MoodleQuickForm::registerElementType('date_selector', "$CFG->libdir/form/dateselector.php", 'MoodleQuickForm_date_selector'); |
1069 | MoodleQuickForm::registerElementType('date_time_selector', "$CFG->libdir/form/datetimeselector.php", 'MoodleQuickForm_date_time_selector'); |
1070 | MoodleQuickForm::registerElementType('htmleditor', "$CFG->libdir/form/htmleditor.php", 'MoodleQuickForm_htmleditor'); |
effa85f4 |
1071 | MoodleQuickForm::registerElementType('format', "$CFG->libdir/form/format.php", 'MoodleQuickForm_format'); |
7f40a229 |
1072 | MoodleQuickForm::registerElementType('static', "$CFG->libdir/form/static.php", 'MoodleQuickForm_static'); |
1073 | MoodleQuickForm::registerElementType('hidden', "$CFG->libdir/form/hidden.php", 'MoodleQuickForm_hidden'); |
e2294b98 |
1074 | MoodleQuickForm::registerElementType('modvisible', "$CFG->libdir/form/modvisible.php", 'MoodleQuickForm_modvisible'); |
1075 | MoodleQuickForm::registerElementType('modgroupmode', "$CFG->libdir/form/modgroupmode.php", 'MoodleQuickForm_modgroupmode'); |
e0f40684 |
1076 | MoodleQuickForm::registerElementType('selectyesno', "$CFG->libdir/form/selectyesno.php", 'MoodleQuickForm_selectyesno'); |
d4fe14d3 |
1077 | MoodleQuickForm::registerElementType('modgrade', "$CFG->libdir/form/modgrade.php", 'MoodleQuickForm_modgrade'); |
19110c57 |
1078 | MoodleQuickForm::registerElementType('cancel', "$CFG->libdir/form/cancel.php", 'MoodleQuickForm_cancel'); |
3c7656b4 |
1079 | MoodleQuickForm::registerElementType('button', "$CFG->libdir/form/button.php", 'MoodleQuickForm_button'); |
1080 | MoodleQuickForm::registerElementType('choosecoursefile', "$CFG->libdir/form/choosecoursefile.php", 'MoodleQuickForm_choosecoursefile'); |
864cc1de |
1081 | |
da6f8763 |
1082 | ?> |