Updated the HEAD build version to 20090918
[moodle.git] / lib / javascript-static.js
CommitLineData
47aa42e2 1// Miscellaneous core Javascript functions for Moodle
2
b48fd7b5 3function popupchecker(msg) {
4 var testwindow = window.open('itestwin.html', '', 'width=1,height=1,left=0,top=0,scrollbars=no');
f6b6861d 5 if (!testwindow) {
6 alert(msg);
7 } else {
b48fd7b5 8 testwindow.close();
9 }
10}
11
63d28811 12function checkall() {
214f5850 13 var inputs = document.getElementsByTagName('input');
14 for (var i = 0; i < inputs.length; i++) {
15 if (inputs[i].type == 'checkbox') {
16 inputs[i].checked = true;
17 }
d2ce367f 18 }
63d28811 19}
20
03f9425f 21function checknone() {
214f5850 22 var inputs = document.getElementsByTagName('input');
23 for (var i = 0; i < inputs.length; i++) {
24 if (inputs[i].type == 'checkbox') {
25 inputs[i].checked = false;
26 }
d2ce367f 27 }
03f9425f 28}
29
d2ce367f 30function lockoptions(formid, master, subitems) {
027d0485 31 // Subitems is an array of names of sub items.
32 // Optionally, each item in subitems may have a
63d28811 33 // companion hidden item in the form with the
027d0485 34 // same name but prefixed by "h".
d2ce367f 35 var form = document.forms[formid];
36
37 if (eval("form."+master+".checked")) {
63d28811 38 for (i=0; i<subitems.length; i++) {
39 unlockoption(form, subitems[i]);
40 }
41 } else {
42 for (i=0; i<subitems.length; i++) {
43 lockoption(form, subitems[i]);
44 }
45 }
46 return(true);
47}
48
f07b9627 49function lockoption(form,item) {
d2ce367f 50 eval("form."+item+".disabled=true");/* IE thing */
51 if(form.elements['h'+item]) {
52 eval("form.h"+item+".value=1");
f07b9627 53 }
54}
55
56function unlockoption(form,item) {
d2ce367f 57 eval("form."+item+".disabled=false");/* IE thing */
58 if(form.elements['h'+item]) {
59 eval("form.h"+item+".value=0");
f07b9627 60 }
61}
dd07bbac 62
b51709c1 63/**
64 * Get the value of the 'virtual form element' with a particular name. That is,
65 * abstracts away the difference between a normal form element, like a select
66 * which is a single HTML element with a .value property, and a set of radio
67 * buttons, which is several HTML elements.
68 *
69 * @param form a HTML form.
70 * @param master the name of an element in that form.
71 * @return the value of that element.
72 */
73function get_form_element_value(form, name) {
74 var element = form[name];
75 if (!element) {
76 return null;
77 }
78 if (element.tagName) {
79 // Ordinarly thing like a select box.
80 return element.value;
81 }
82 // Array of things, like radio buttons.
83 for (var j = 0; j < element.length; j++) {
84 var el = element[j];
85 if (el.checked) {
86 return el.value;
87 }
88 }
89 return null;
90}
91
92
93/**
94 * Set the disabled state of the 'virtual form element' with a particular name.
95 * This abstracts away the difference between a normal form element, like a select
96 * which is a single HTML element with a .value property, and a set of radio
97 * buttons, which is several HTML elements.
98 *
99 * @param form a HTML form.
100 * @param master the name of an element in that form.
101 * @param disabled the disabled state to set.
102 */
103function set_form_element_disabled(form, name, disabled) {
104 var element = form[name];
105 if (!element) {
106 return;
107 }
108 if (element.tagName) {
109 // Ordinarly thing like a select box.
110 element.disabled = disabled;
111 }
112 // Array of things, like radio buttons.
113 for (var j = 0; j < element.length; j++) {
114 var el = element[j];
115 el.disabled = disabled;
116 }
117}
dd07bbac 118
50ef8eb9 119function lockoptionsall(formid) {
dd07bbac 120 var form = document.forms[formid];
b51709c1 121 var dependons = eval(formid + 'items');
122 var tolock = [];
dd07bbac 123 for (var dependon in dependons) {
d63ef3b8 124 // change for MooTools compatibility
125 if (!dependons.propertyIsEnumerable(dependon)) {
126 continue;
127 }
b51709c1 128 if (!form[dependon]) {
4bc24867 129 continue;
130 }
dd07bbac 131 for (var condition in dependons[dependon]) {
132 for (var value in dependons[dependon][condition]) {
133 var lock;
134 switch (condition) {
135 case 'notchecked':
b51709c1 136 lock = !form[dependon].checked; break;
dd07bbac 137 case 'checked':
b51709c1 138 lock = form[dependon].checked; break;
dd07bbac 139 case 'noitemselected':
b51709c1 140 lock = form[dependon].selectedIndex == -1; break;
dd07bbac 141 case 'eq':
b51709c1 142 lock = get_form_element_value(form, dependon) == value; break;
dd07bbac 143 default:
b51709c1 144 lock = get_form_element_value(form, dependon) != value; break;
dd07bbac 145 }
146 for (var ei in dependons[dependon][condition][value]) {
d63ef3b8 147 // change for MooTools compatibility
148 if (!window.webkit && (!dependons[dependon][condition][value].propertyIsEnumerable(ei))) {
149 continue;
150 }
632b88d5 151 var eltolock = dependons[dependon][condition][value][ei];
b51709c1 152 if (tolock[eltolock] != null) {
153 tolock[eltolock] = lock || tolock[eltolock];
632b88d5 154 } else {
155 tolock[eltolock] = lock;
156 }
dd07bbac 157 }
158 }
50ef8eb9 159 }
dd07bbac 160 }
b51709c1 161 for (var el in tolock) {
d63ef3b8 162 // change for MooTools compatibility
163 if (!tolock.propertyIsEnumerable(el)) {
164 continue;
165 }
b51709c1 166 set_form_element_disabled(form, el, tolock[el]);
632b88d5 167 }
dd07bbac 168 return true;
50ef8eb9 169}
170
d01a38cb 171function lockoptionsallsetup(formid) {
dd07bbac 172 var form = document.forms[formid];
173 var dependons = eval(formid+'items');
174 for (var dependon in dependons) {
d63ef3b8 175 // change for MooTools compatibility
176 if (!dependons.propertyIsEnumerable(dependon)) {
177 continue;
178 }
b51709c1 179 var masters = form[dependon];
180 if (!masters) {
4bc24867 181 continue;
182 }
a4db2e7c 183 if (masters.tagName) {
b51709c1 184 // If master is radio buttons, we get an array, otherwise we don't.
185 // Convert both cases to an array for convinience.
186 masters = [masters];
187 }
188 for (var j = 0; j < masters.length; j++) {
189 master = masters[j];
190 master.formid = formid;
191 master.onclick = function() {return lockoptionsall(this.formid);};
192 master.onblur = function() {return lockoptionsall(this.formid);};
193 master.onchange = function() {return lockoptionsall(this.formid);};
194 }
dd07bbac 195 }
b51709c1 196 for (var i = 0; i < form.elements.length; i++) {
dd07bbac 197 var formelement = form.elements[i];
198 if (formelement.type=='reset') {
c0056e22 199 formelement.formid = formid;
200 formelement.onclick = function() {this.form.reset();return lockoptionsall(this.formid);};
201 formelement.onblur = function() {this.form.reset();return lockoptionsall(this.formid);};
202 formelement.onchange = function() {this.form.reset();return lockoptionsall(this.formid);};
dd07bbac 203 }
204 }
205 return lockoptionsall(formid);
d01a38cb 206}
50ef8eb9 207
dc580207 208/**
209 * Helper function mainly for drop-down menus' onchange events,
210 * submits the form designated by args.id. If args.selectid is also
5529f787 211 * given, it only submits the form if the selected <option> is not
dc580207 212 * the first one (usually the "Choose..." option)
7b1f2c82 213 * Example usage of the html_select component with this function:
dc580207 214 * <pre>
7b1f2c82 215 * $select = new html_select();
49c8c8d2 216 * $select->options = array('delete' => get_string('delete'));
217 * $select->name = 'action';
218 * $select->button->label = get_string('withselected', 'quiz');
219 * $select->id = 'menuaction';
220 * $select->add_action('change', 'submit_form_by_id', array('id' => 'attemptsform', 'selectid' => 'menuaction'));
221 * echo $OUTPUT->select($select);
dc580207 222 * </pre>
223 */
224function submit_form_by_id(e, args) {
8e127eb3 225 var theform = document.getElementById(args.id);
dc580207 226 if (!theform) {
7678e65c 227 return false;
228 }
dc580207 229 if (theform.tagName.toLowerCase() != 'form') {
7678e65c 230 return false;
231 }
dc580207 232 if (args.selectid) {
233 var select = document.getElementById(args.selectid);
234 if (select.selectedIndex == 0) {
235 return false;
236 }
7678e65c 237 }
dc580207 238 return theform.submit();
7678e65c 239}
363cb62c 240
45caa363 241/**
242 * Either check, or uncheck, all checkboxes inside the element with id is
243 * @param id the id of the container
244 * @param checked the new state, either '' or 'checked'.
245 */
246function select_all_in_element_with_id(id, checked) {
247 var container = document.getElementById(id);
248 if (!container) {
249 return;
250 }
251 var inputs = container.getElementsByTagName('input');
252 for (var i = 0; i < inputs.length; ++i) {
253 if (inputs[i].type == 'checkbox' || inputs[i].type == 'radio') {
254 inputs[i].checked = checked;
255 }
256 }
257}
258
8ceb09e0 259function select_all_in(elTagName, elClass, elId) {
d2ce367f 260 var inputs = document.getElementsByTagName('input');
8ceb09e0 261 inputs = filterByParent(inputs, function(el) {return findParentNode(el, elTagName, elClass, elId);});
363cb62c 262 for(var i = 0; i < inputs.length; ++i) {
bee40515 263 if(inputs[i].type == 'checkbox' || inputs[i].type == 'radio') {
363cb62c 264 inputs[i].checked = 'checked';
265 }
266 }
267}
268
8ceb09e0 269function deselect_all_in(elTagName, elClass, elId) {
363cb62c 270 var inputs = document.getElementsByTagName('INPUT');
8ceb09e0 271 inputs = filterByParent(inputs, function(el) {return findParentNode(el, elTagName, elClass, elId);});
363cb62c 272 for(var i = 0; i < inputs.length; ++i) {
bee40515 273 if(inputs[i].type == 'checkbox' || inputs[i].type == 'radio') {
363cb62c 274 inputs[i].checked = '';
275 }
276 }
277}
278
279function confirm_if(expr, message) {
280 if(!expr) {
281 return true;
282 }
283 return confirm(message);
284}
47aa42e2 285
286
287/*
288 findParentNode (start, elementName, elementClass, elementID)
50ef8eb9 289
47aa42e2 290 Travels up the DOM hierarchy to find a parent element with the
291 specified tag name, class, and id. All conditions must be met,
292 but any can be ommitted. Returns the BODY element if no match
293 found.
294*/
295function findParentNode(el, elName, elClass, elId) {
45caa363 296 while (el.nodeName.toUpperCase() != 'BODY') {
297 if ((!elName || el.nodeName.toUpperCase() == elName) &&
47aa42e2 298 (!elClass || el.className.indexOf(elClass) != -1) &&
45caa363 299 (!elId || el.id == elId)) {
47aa42e2 300 break;
301 }
302 el = el.parentNode;
303 }
304 return el;
305}
19194f82 306/*
307 findChildNode (start, elementName, elementClass, elementID)
308
309 Travels down the DOM hierarchy to find all child elements with the
310 specified tag name, class, and id. All conditions must be met,
311 but any can be ommitted.
a23f0aaf 312 Doesn't examine children of matches.
19194f82 313*/
314function findChildNodes(start, tagName, elementClass, elementID, elementName) {
315 var children = new Array();
83c9a8a2 316 for (var i = 0; i < start.childNodes.length; i++) {
a23f0aaf 317 var classfound = false;
83c9a8a2 318 var child = start.childNodes[i];
a23f0aaf 319 if((child.nodeType == 1) &&//element node type
b51709c1 320 (elementClass && (typeof(child.className)=='string'))) {
a23f0aaf 321 var childClasses = child.className.split(/\s+/);
b51709c1 322 for (var childClassIndex in childClasses) {
323 if (childClasses[childClassIndex]==elementClass) {
a23f0aaf 324 classfound = true;
325 break;
326 }
327 }
328 }
f07b9627 329 if(child.nodeType == 1) { //element node type
330 if ( (!tagName || child.nodeName == tagName) &&
331 (!elementClass || classfound)&&
332 (!elementID || child.id == elementID) &&
333 (!elementName || child.name == elementName))
334 {
335 children = children.concat(child);
336 } else {
337 children = children.concat(findChildNodes(child, tagName, elementClass, elementID, elementName));
338 }
19194f82 339 }
19194f82 340 }
341 return children;
342}
343/*
344 elementSetHide (elements, hide)
345
346 Adds or removes the "hide" class for the specified elements depending on boolean hide.
347*/
348function elementShowAdvanced(elements, show) {
b51709c1 349 for (var elementIndex in elements) {
19194f82 350 element = elements[elementIndex];
351 element.className = element.className.replace(new RegExp(' ?hide'), '')
352 if(!show) {
353 element.className += ' hide';
354 }
355 }
356}
357
cd350b53 358function showAdvancedInit(addBefore, nameAttr, buttonLabel, hideText, showText) {
359 var showHideButton = document.createElement("input");
360 showHideButton.type = 'button';
361 showHideButton.value = buttonLabel;
362 showHideButton.name = nameAttr;
363 showHideButton.moodle = {
fc4f5796 364 hideLabel: mstr.form.hideadvanced,
365 showLabel: mstr.form.showadvanced
cd350b53 366 };
367 YAHOO.util.Event.addListener(showHideButton, 'click', showAdvancedOnClick);
368 el = document.getElementById(addBefore);
369 el.parentNode.insertBefore(showHideButton, el);
370}
371
372function showAdvancedOnClick(e) {
373 var button = e.target ? e.target : e.srcElement;
374
19194f82 375 var toSet=findChildNodes(button.form, null, 'advanced');
376 var buttontext = '';
74d15d35 377 if (button.form.elements['mform_showadvanced_last'].value == '0' || button.form.elements['mform_showadvanced_last'].value == '' ) {
19194f82 378 elementShowAdvanced(toSet, true);
cd350b53 379 buttontext = button.moodle.hideLabel;
19194f82 380 button.form.elements['mform_showadvanced_last'].value = '1';
381 } else {
382 elementShowAdvanced(toSet, false);
cd350b53 383 buttontext = button.moodle.showLabel;
19194f82 384 button.form.elements['mform_showadvanced_last'].value = '0';
385 }
386 var formelements = button.form.elements;
4ea054ec 387 // Fixed MDL-10506
b51709c1 388 for (var i = 0; i < formelements.length; i++) {
389 if (formelements[i] && formelements[i].name && (formelements[i].name=='mform_showadvanced')) {
19194f82 390 formelements[i].value = buttontext;
391 }
392 }
393 //never submit the form if js is enabled.
394 return false;
395}
47aa42e2 396
54bb33eb 397function unmaskPassword(id) {
239ade45 398 var pw = document.getElementById(id);
54bb33eb 399 var chb = document.getElementById(id+'unmask');
239ade45 400
401 try {
402 // first try IE way - it can not set name attribute later
403 if (chb.checked) {
404 var newpw = document.createElement('<input type="text" name="'+pw.name+'">');
405 } else {
406 var newpw = document.createElement('<input type="password" name="'+pw.name+'">');
407 }
eba8cd63 408 newpw.attributes['class'].nodeValue = pw.attributes['class'].nodeValue;
239ade45 409 } catch (e) {
410 var newpw = document.createElement('input');
411 newpw.setAttribute('name', pw.name);
412 if (chb.checked) {
413 newpw.setAttribute('type', 'text');
414 } else {
415 newpw.setAttribute('type', 'password');
416 }
eba8cd63 417 newpw.setAttribute('class', pw.getAttribute('class'));
239ade45 418 }
419 newpw.id = pw.id;
420 newpw.size = pw.size;
421 newpw.onblur = pw.onblur;
422 newpw.onchange = pw.onchange;
423 newpw.value = pw.value;
424 pw.parentNode.replaceChild(newpw, pw);
425}
426
8e7cebb0 427/**
428 * Search a Moodle form to find all the fdate_time_selector and fdate_selector
429 * elements, and add date_selector_calendar instance to each.
430 */
431function init_date_selectors(firstdayofweek) {
8e7cebb0 432 var els = YAHOO.util.Dom.getElementsByClassName('fdate_time_selector', 'fieldset');
433 for (var i = 0; i < els.length; i++) {
434 new date_selector_calendar(els[i], firstdayofweek);
435 }
436 els = YAHOO.util.Dom.getElementsByClassName('fdate_selector', 'fieldset');
437 for (i = 0; i < els.length; i++) {
438 new date_selector_calendar(els[i], firstdayofweek);
439 }
440}
441
442/**
9bad31f5 443 * Constructor for a JavaScript object that connects to a fdate_time_selector
8e7cebb0 444 * or a fdate_selector in a Moodle form, and shows a popup calendar whenever
445 * that element has keyboard focus.
446 * @param el the fieldset class="fdate_time_selector" or "fdate_selector".
447 */
448function date_selector_calendar(el, firstdayofweek) {
449 // Ensure that the shared div and calendar exist.
450 if (!date_selector_calendar.panel) {
451 date_selector_calendar.panel = new YAHOO.widget.Panel('date_selector_calendar_panel',
b3a49376 452 {visible: false, draggable: false});
8e7cebb0 453 var div = document.createElement('div');
454 date_selector_calendar.panel.setBody(div);
455 date_selector_calendar.panel.render(document.body);
456
457 YAHOO.util.Event.addListener(document, 'click', date_selector_calendar.document_click);
458 date_selector_calendar.panel.showEvent.subscribe(function() {
459 date_selector_calendar.panel.fireEvent('changeContent');
460 });
b3a49376 461 date_selector_calendar.panel.hideEvent.subscribe(date_selector_calendar.release_current);
8e7cebb0 462
463 date_selector_calendar.calendar = new YAHOO.widget.Calendar(div,
464 {iframe: false, hide_blank_weeks: true, start_weekday: firstdayofweek});
465 date_selector_calendar.calendar.renderEvent.subscribe(function() {
466 date_selector_calendar.panel.fireEvent('changeContent');
bd55319b 467 date_selector_calendar.delayed_reposition();
8e7cebb0 468 });
8e7cebb0 469 }
470
471 this.fieldset = el;
472 var controls = el.getElementsByTagName('select');
473 for (var i = 0; i < controls.length; i++) {
8e7cebb0 474 if (/\[year\]$/.test(controls[i].name)) {
475 this.yearselect = controls[i];
9bad31f5 476 } else if (/\[month\]$/.test(controls[i].name)) {
8e7cebb0 477 this.monthselect = controls[i];
9bad31f5 478 } else if (/\[day\]$/.test(controls[i].name)) {
8e7cebb0 479 this.dayselect = controls[i];
9bad31f5 480 } else {
bd55319b 481 YAHOO.util.Event.addFocusListener(controls[i], date_selector_calendar.cancel_any_timeout, this);
9bad31f5 482 YAHOO.util.Event.addBlurListener(controls[i], this.blur_event, this);
8e7cebb0 483 }
484 }
485 if (!(this.yearselect && this.monthselect && this.dayselect)) {
486 throw 'Failed to initialise calendar.';
487 }
9bad31f5 488 YAHOO.util.Event.addFocusListener([this.yearselect, this.monthselect, this.dayselect], this.focus_event, this);
489 YAHOO.util.Event.addBlurListener([this.yearselect, this.monthselect, this.dayselect], this.blur_event, this);
8e7cebb0 490
491 this.enablecheckbox = el.getElementsByTagName('input')[0];
492 if (this.enablecheckbox) {
493 YAHOO.util.Event.addFocusListener(this.enablecheckbox, this.focus_event, this);
494 YAHOO.util.Event.addListener(this.enablecheckbox, 'change', this.focus_event, this);
495 YAHOO.util.Event.addBlurListener(this.enablecheckbox, this.blur_event, this);
496 }
497}
498
499/** The pop-up calendar that contains the calendar. */
500date_selector_calendar.panel = null;
501
502/** The shared YAHOO.widget.Calendar used by all date_selector_calendars. */
503date_selector_calendar.calendar = null;
504
505/** The date_selector_calendar that currently owns the shared stuff. */
506date_selector_calendar.currentowner = null;
507
508/** Used as a timeout when hiding the calendar on blur - so we don't hide the calendar
509 * if we are just jumping from on of our controls to another. */
510date_selector_calendar.hidetimeout = null;
511
bd55319b 512/** Timeout for repositioning after a delay after a change of months. */
513date_selector_calendar.repositiontimeout = null;
8e7cebb0 514
bd55319b 515/** Member variables. Pointers to various bits of the DOM. */
8e7cebb0 516date_selector_calendar.prototype.fieldset = null;
517date_selector_calendar.prototype.yearselect = null;
518date_selector_calendar.prototype.monthselect = null;
519date_selector_calendar.prototype.dayselect = null;
520date_selector_calendar.prototype.enablecheckbox = null;
521
bd55319b 522date_selector_calendar.cancel_any_timeout = function() {
8e7cebb0 523 if (date_selector_calendar.hidetimeout) {
524 clearTimeout(date_selector_calendar.hidetimeout);
525 date_selector_calendar.hidetimeout = null;
526 }
bd55319b 527 if (date_selector_calendar.repositiontimeout) {
528 clearTimeout(date_selector_calendar.repositiontimeout);
529 date_selector_calendar.repositiontimeout = null;
530 }
531}
532
533date_selector_calendar.delayed_reposition = function() {
534 if (date_selector_calendar.repositiontimeout) {
535 clearTimeout(date_selector_calendar.repositiontimeout);
536 date_selector_calendar.repositiontimeout = null;
537 }
b3a49376 538 date_selector_calendar.repositiontimeout = setTimeout(date_selector_calendar.fix_position, 500);
bd55319b 539}
540
541date_selector_calendar.fix_position = function() {
542 if (date_selector_calendar.currentowner) {
543 date_selector_calendar.panel.cfg.setProperty('context', [date_selector_calendar.currentowner.fieldset, 'bl', 'tl']);
544 }
8e7cebb0 545}
546
b3a49376 547date_selector_calendar.release_current = function() {
548 if (date_selector_calendar.currentowner) {
549 date_selector_calendar.currentowner.release_calendar();
550 }
551}
552
8e7cebb0 553date_selector_calendar.prototype.focus_event = function(e, me) {
bd55319b 554 date_selector_calendar.cancel_any_timeout();
8e7cebb0 555 if (me.enablecheckbox == null || me.enablecheckbox.checked) {
556 me.claim_calendar();
557 } else {
558 if (date_selector_calendar.currentowner) {
559 date_selector_calendar.currentowner.release_calendar();
560 }
561 }
562}
563
564date_selector_calendar.prototype.blur_event = function(e, me) {
b3a49376 565 date_selector_calendar.hidetimeout = setTimeout(date_selector_calendar.release_current, 300);
8e7cebb0 566}
567
568date_selector_calendar.prototype.handle_select_change = function(e, me) {
569 me.set_date_from_selects();
570}
571
572date_selector_calendar.document_click = function(event) {
573 if (date_selector_calendar.currentowner) {
574 var currentcontainer = date_selector_calendar.currentowner.fieldset;
575 var eventarget = YAHOO.util.Event.getTarget(event);
b3a49376 576 if (YAHOO.util.Dom.isAncestor(currentcontainer, eventarget)) {
577 setTimeout(function() {date_selector_calendar.cancel_any_timeout()}, 100);
578 } else {
8e7cebb0 579 date_selector_calendar.currentowner.release_calendar();
580 }
581 }
f8065dd2 582}
8e7cebb0 583
584date_selector_calendar.prototype.claim_calendar = function() {
bd55319b 585 date_selector_calendar.cancel_any_timeout();
8e7cebb0 586 if (date_selector_calendar.currentowner == this) {
587 return;
588 }
589 if (date_selector_calendar.currentowner) {
590 date_selector_calendar.currentowner.release_calendar();
591 }
592
bd55319b 593 if (date_selector_calendar.currentowner != this) {
594 this.connect_handlers();
595 }
596 date_selector_calendar.currentowner = this;
597
8e7cebb0 598 date_selector_calendar.calendar.cfg.setProperty('mindate', new Date(this.yearselect.options[0].value, 0, 1));
599 date_selector_calendar.calendar.cfg.setProperty('maxdate', new Date(this.yearselect.options[this.yearselect.options.length - 1].value, 11, 31));
bd55319b 600 this.fieldset.insertBefore(date_selector_calendar.panel.element, this.yearselect.nextSibling);
8e7cebb0 601 this.set_date_from_selects();
602 date_selector_calendar.panel.show();
603 var me = this;
bd55319b 604 setTimeout(function() {date_selector_calendar.cancel_any_timeout()}, 100);
8e7cebb0 605}
606
607date_selector_calendar.prototype.set_date_from_selects = function() {
608 var year = parseInt(this.yearselect.value);
609 var month = parseInt(this.monthselect.value) - 1;
610 var day = parseInt(this.dayselect.value);
611 date_selector_calendar.calendar.select(new Date(year, month, day));
612 date_selector_calendar.calendar.setMonth(month);
613 date_selector_calendar.calendar.setYear(year);
bd55319b 614 date_selector_calendar.calendar.render();
615 date_selector_calendar.fix_position();
8e7cebb0 616}
617
618date_selector_calendar.prototype.set_selects_from_date = function(eventtype, args) {
619 var date = args[0][0];
620 var newyear = date[0];
621 var newindex = newyear - this.yearselect.options[0].value;
622 this.yearselect.selectedIndex = newindex;
623 this.monthselect.selectedIndex = date[1] - this.monthselect.options[0].value;
624 this.dayselect.selectedIndex = date[2] - this.dayselect.options[0].value;
625}
626
627date_selector_calendar.prototype.connect_handlers = function() {
628 YAHOO.util.Event.addListener([this.yearselect, this.monthselect, this.dayselect], 'change', this.handle_select_change, this);
629 date_selector_calendar.calendar.selectEvent.subscribe(this.set_selects_from_date, this, true);
630}
631
632date_selector_calendar.prototype.release_calendar = function() {
633 date_selector_calendar.panel.hide();
634 date_selector_calendar.currentowner = null;
635 YAHOO.util.Event.removeListener([this.yearselect, this.monthselect, this.dayselect], this.handle_select_change);
636 date_selector_calendar.calendar.selectEvent.unsubscribe(this.set_selects_from_date, this);
637}
638
47aa42e2 639function filterByParent(elCollection, parentFinder) {
640 var filteredCollection = [];
45caa363 641 for (var i = 0; i < elCollection.length; ++i) {
47aa42e2 642 var findParent = parentFinder(elCollection[i]);
45caa363 643 if (findParent.nodeName.toUpperCase != 'BODY') {
47aa42e2 644 filteredCollection.push(elCollection[i]);
645 }
646 }
647 return filteredCollection;
648}
649
7979105c 650/*
651 All this is here just so that IE gets to handle oversized blocks
652 in a visually pleasing manner. It does a browser detect. So sue me.
653*/
654
655function fix_column_widths() {
656 var agt = navigator.userAgent.toLowerCase();
657 if ((agt.indexOf("msie") != -1) && (agt.indexOf("opera") == -1)) {
658 fix_column_width('left-column');
659 fix_column_width('right-column');
660 }
661}
662
663function fix_column_width(colName) {
664 if(column = document.getElementById(colName)) {
665 if(!column.offsetWidth) {
666 setTimeout("fix_column_width('" + colName + "')", 20);
667 return;
668 }
669
670 var width = 0;
671 var nodes = column.childNodes;
672
673 for(i = 0; i < nodes.length; ++i) {
674 if(nodes[i].className.indexOf("sideblock") != -1 ) {
675 if(width < nodes[i].offsetWidth) {
676 width = nodes[i].offsetWidth;
677 }
678 }
679 }
680
681 for(i = 0; i < nodes.length; ++i) {
682 if(nodes[i].className.indexOf("sideblock") != -1 ) {
683 nodes[i].style.width = width + 'px';
684 }
685 }
686 }
687}
d13c5938 688
689
690/*
9f439b17 691 Insert myValue at current cursor position
692 */
d13c5938 693function insertAtCursor(myField, myValue) {
9f439b17 694 // IE support
695 if (document.selection) {
696 myField.focus();
697 sel = document.selection.createRange();
698 sel.text = myValue;
699 }
700 // Mozilla/Netscape support
701 else if (myField.selectionStart || myField.selectionStart == '0') {
702 var startPos = myField.selectionStart;
703 var endPos = myField.selectionEnd;
704 myField.value = myField.value.substring(0, startPos)
705 + myValue + myField.value.substring(endPos, myField.value.length);
706 } else {
707 myField.value += myValue;
708 }
d13c5938 709}
7470d6de 710
711
712/*
c0056e22 713 Call instead of setting window.onload directly or setting body onload=.
714 Adds your function to a chain of functions rather than overwriting anything
715 that exists.
716*/
7470d6de 717function addonload(fn) {
718 var oldhandler=window.onload;
719 window.onload=function() {
720 if(oldhandler) oldhandler();
c0056e22 721 fn();
7470d6de 722 }
723}
7d2a0492 724/**
725 * Replacement for getElementsByClassName in browsers that aren't cool enough
726 *
727 * Relying on the built-in getElementsByClassName is far, far faster than
728 * using YUI.
729 *
730 * Note: the third argument used to be an object with odd behaviour. It now
731 * acts like the 'name' in the HTML5 spec, though the old behaviour is still
732 * mimicked if you pass an object.
733 *
734 * @param {Node} oElm The top-level node for searching. To search a whole
735 * document, use `document`.
736 * @param {String} strTagName filter by tag names
737 * @param {String} name same as HTML5 spec
738 */
739function getElementsByClassName(oElm, strTagName, name) {
740 // for backwards compatibility
741 if(typeof name == "object") {
742 var names = new Array();
743 for(var i=0; i<name.length; i++) names.push(names[i]);
744 name = names.join('');
745 }
746 // use native implementation if possible
747 if (oElm.getElementsByClassName && Array.filter) {
748 if (strTagName == '*') {
749 return oElm.getElementsByClassName(name);
750 } else {
751 return Array.filter(oElm.getElementsByClassName(name), function(el) {
752 return el.nodeName.toLowerCase() == strTagName.toLowerCase();
753 });
754 }
755 }
756 // native implementation unavailable, fall back to slow method
c849ed1e 757 var arrElements = (strTagName == "*" && oElm.all)? oElm.all : oElm.getElementsByTagName(strTagName);
758 var arrReturnElements = new Array();
759 var arrRegExpClassNames = new Array();
7d2a0492 760 var names = name.split(' ');
761 for(var i=0; i<names.length; i++) {
762 arrRegExpClassNames.push(new RegExp("(^|\\s)" + names[i].replace(/\-/g, "\\-") + "(\\s|$)"));
c849ed1e 763 }
764 var oElement;
765 var bMatchesAll;
b51709c1 766 for(var j=0; j<arrElements.length; j++) {
c849ed1e 767 oElement = arrElements[j];
768 bMatchesAll = true;
b51709c1 769 for(var k=0; k<arrRegExpClassNames.length; k++) {
770 if(!arrRegExpClassNames[k].test(oElement.className)) {
c849ed1e 771 bMatchesAll = false;
772 break;
773 }
774 }
b51709c1 775 if(bMatchesAll) {
c849ed1e 776 arrReturnElements.push(oElement);
777 }
778 }
779 return (arrReturnElements)
780}
77241d9b 781
f8065dd2 782function openpopup(event, args) {
783
784 YAHOO.util.Event.preventDefault(event);
785
786 var fullurl = args.url;
787 if (!args.url.match(/https?:\/\//)) {
788 fullurl = moodle_cfg.wwwroot + args.url;
bed9cec8 789 }
f8065dd2 790 var windowobj = window.open(fullurl,args.name,args.options);
214f5850 791 if (!windowobj) {
792 return true;
793 }
77241d9b 794 if (fullscreen) {
795 windowobj.moveTo(0,0);
796 windowobj.resizeTo(screen.availWidth,screen.availHeight);
797 }
798 windowobj.focus();
799 return false;
800}
740939ec 801
802/* This is only used on a few help pages. */
803emoticons_help = {
804 inputarea: null,
805
806 init: function(formname, fieldname, listid) {
807 if (!opener || !opener.document.forms[formname]) {
808 return;
809 }
810 emoticons_help.inputarea = opener.document.forms[formname][fieldname];
811 if (!emoticons_help.inputarea) {
812 return;
813 }
814 var emoticons = document.getElementById(listid).getElementsByTagName('li');
815 for (var i = 0; i < emoticons.length; i++) {
816 var text = emoticons[i].getElementsByTagName('img')[0].alt;
817 YAHOO.util.Event.addListener(emoticons[i], 'click', emoticons_help.inserttext, text);
818 }
819 },
820
821 inserttext: function(e, text) {
822 text = ' ' + text + ' ';
823 if (emoticons_help.inputarea.createTextRange && emoticons_help.inputarea.caretPos) {
824 var caretPos = emoticons_help.inputarea.caretPos;
825 caretPos.text = caretPos.text.charAt(caretPos.text.length - 1) == ' ' ? text + ' ' : text;
826 } else {
827 emoticons_help.inputarea.value += text;
828 }
829 emoticons_help.inputarea.focus();
830 }
bd1884fe 831}
832
833/**
834 * Makes a best effort to connect back to Moodle to update a user preference,
835 * however, there is no mechanism for finding out if the update succeeded.
836 *
837 * Before you can use this function in your JavsScript, you must have called
838 * user_preference_allow_ajax_update from moodlelib.php to tell Moodle that
839 * the udpate is allowed, and how to safely clean and submitted values.
840 *
841 * @param String name the name of the setting to udpate.
842 * @param String the value to set it to.
843 */
844function set_user_preference(name, value) {
845 // Don't generate a script error if the library has not been loaded,
846 // unless we are a Developer, in which case we want the error.
847 if (YAHOO && YAHOO.util && YAHOO.util.Connect || moodle_cfg.developerdebug) {
848 var url = moodle_cfg.wwwroot + '/lib/ajax/setuserpref.php?sesskey=' +
849 moodle_cfg.sesskey + '&pref=' + encodeURI(name) + '&value=' + encodeURI(value);
850
851 // If we are a developer, ensure that failures are reported.
852 var callback = {};
853 if (moodle_cfg.developerdebug) {
854 callback.failure = function() {
855 var a = document.createElement('a');
856 a.href = url;
857 a.classname = 'error';
858 a.appendChild(document.createTextNode("Error updating user preference '" + name + "' using ajax. Clicking this link will repeat the Ajax call that failed so you can see the error."));
859 document.body.insertBefore(a, document.body.firstChild);
860 }
861 }
862
863 // Make the request.
f8065dd2 864 YAHOO.util.Connect.asyncRequest('GET', url, callback);
bd1884fe 865 }
3b0bf2e4 866}
867
868function moodle_initialise_body() {
869 document.body.className += ' jsenabled';
f2eb5002 870}
871
872/**
873 * Oject to handle a collapsible region, see print_collapsible_region in weblib.php
874 * @constructor
875 * @param String id the HTML id for the div.
876 * @param String userpref the user preference that records the state of this box. false if none.
877 * @param Boolean startcollapsed whether the box should start collapsed.
878 */
a28c9253 879function collapsible_region(id, userpref, strtooltip, collapsedicon, expandedicon) {
f2eb5002 880 // Record the pref name
881 this.userpref = userpref;
a28c9253 882 this.collapsedicon = collapsedicon;
883 this.expandedicon = expandedicon;
f2eb5002 884
885 // Find the divs in the document.
886 this.div = document.getElementById(id);
904998d8 887 this.innerdiv = document.getElementById(id + '_sizer');
f2eb5002 888 this.caption = document.getElementById(id + '_caption');
889 this.caption.title = strtooltip;
890
891 // Put the contents of caption in an <a> to make it focussable.
892 var a = document.createElement('a');
893 while (e = this.caption.firstChild) {
894 a.appendChild(e);
895 }
896 a.href = '#';
897 this.caption.appendChild(a);
898
899 // Create the animation.
900 this.animation = new YAHOO.util.Anim(this.div, {}, 0.3, YAHOO.util.Easing.easeBoth);
901
902 // Get to the right initial state.
903 if (this.div.className.match(/\bcollapsed\b/)) {
904 this.collapsed = true;
e7b7583c 905 var self = this;
906 setTimeout(function() {
907 var region = YAHOO.util.Region.getRegion(self.caption);
908 self.div.style.height = (region.bottom - region.top + 3) + 'px';
909 }, 10);
f2eb5002 910 }
911
912 // Add the appropriate image.
913 this.icon = document.createElement('img');
914 this.icon.id = id + '_icon';
915 this.icon.alt = '';
916 if (this.collapsed) {
a28c9253 917 this.icon.src = this.collapsedicon;
f2eb5002 918 } else {
a28c9253 919 this.icon.src = this.expandedicon;
f2eb5002 920 }
c9f8e118 921 a.appendChild(this.icon);
f2eb5002 922
923 // Hook up the event handler.
d4a03c00 924 YAHOO.util.Event.addListener(a, 'click', this.handle_click, null, this);
904998d8 925
926 // Handler for the animation finishing.
927 this.animation.onComplete.subscribe(function() {self.handle_animation_complete();});
f2eb5002 928}
929
930/**
931 * The user preference that stores the state of this box.
6a208406 932 * @property userpref
f2eb5002 933 * @type String
934 */
935collapsible_region.prototype.userpref = null;
936
937/**
f8065dd2 938 * The key divs that make up this
f2eb5002 939 * @property div, innerdiv, captiondiv
940 * @type HTMLDivElement
941 */
942collapsible_region.prototype.div = null;
943collapsible_region.prototype.innerdiv = null;
944collapsible_region.prototype.captiondiv = null;
945
946/**
f8065dd2 947 * The key divs that make up this
f2eb5002 948 * @property icon
949 * @type HTMLImageElement
950 */
951collapsible_region.prototype.icon = null;
952
953/**
954 * Whether the region is currently collapsed.
955 * @property collapsed
956 * @type Boolean
957 */
958collapsible_region.prototype.collapsed = false;
959
960/**
961 * @property animation
962 * @type YAHOO.util.Anim
963 */
964collapsible_region.prototype.animation = null;
965
904998d8 966/** When clicked, toggle the collapsed state, and trigger the animation. */
f2eb5002 967collapsible_region.prototype.handle_click = function(e) {
968 // Toggle the state.
969 this.collapsed = !this.collapsed;
970
971 // Stop the click following the link.
972 YAHOO.util.Event.stopEvent(e);
973
974 // Animate to the appropriate size.
975 if (this.animation.isAnimated()) {
976 this.animation.stop();
977 }
978 if (this.collapsed) {
c679952e 979 var region = YAHOO.util.Region.getRegion(this.caption);
980 var targetheight = region.bottom - region.top + 3;
f2eb5002 981 } else {
c679952e 982 var region = YAHOO.util.Region.getRegion(this.innerdiv);
983 var targetheight = region.bottom - region.top + 2;
f2eb5002 984 this.div.className = this.div.className.replace(/\s*\bcollapsed\b\s*/, ' ');
985 }
c679952e 986 this.animation.attributes.height = { to: targetheight, unit: 'px' };
f2eb5002 987 this.animation.animate();
988
989 // Set the appropriate icon.
990 if (this.collapsed) {
a28c9253 991 this.icon.src =this.collapsedicon;
f2eb5002 992 } else {
a28c9253 993 this.icon.src = this.expandedicon;
f2eb5002 994 }
995
996 // Update the user preference.
997 if (this.userpref) {
998 set_user_preference(this.userpref, this.collapsed);
999 }
1000}
904998d8 1001
1002/** When when the animation is finished, add the collapsed class name in relevant. */
1003collapsible_region.prototype.handle_animation_complete = function() {
1004 if (this.collapsed) {
1005 this.div.className += ' collapsed';
1006 }
b166403f 1007}
1008
d4a03c00 1009/**
1010 * Oject to handle expanding and collapsing blocks when an icon is clicked on.
1011 * @constructor
1012 * @param String id the HTML id for the div.
1013 * @param String userpref the user preference that records the state of this block.
1014 * @param String visibletooltip tool tip/alt to show when the block is visible.
1015 * @param String hiddentooltip tool tip/alt to show when the block is hidden.
1016 * @param String visibleicon URL of the icon to show when the block is visible.
1017 * @param String hiddenicon URL of the icon to show when the block is hidden.
1018 */
1019function block_hider(id, userpref, visibletooltip, hiddentooltip, visibleicon, hiddenicon) {
1020 // Find the elemen that is the block.
1021 this.block = document.getElementById(id);
1022 var title_div = YAHOO.util.Dom.getElementsByClassName('title', 'div', this.block);
1023 if (!title_div || !title_div[0]) {
1024 return this;
1025 }
1026 title_div = title_div[0];
1027 this.ishidden = YAHOO.util.Dom.hasClass(this.block, 'hidden');
1028
1029 // Record the pref name
1030 this.userpref = userpref;
1031 this.visibletooltip = visibletooltip;
1032 this.hiddentooltip = hiddentooltip;
1033 this.visibleicon = visibleicon;
1034 this.hiddenicon = hiddenicon;
1035
1036 // Add the icon.
1037 this.icon = document.createElement('input');
1038 this.icon.type = 'image';
1039 this.icon.className = 'hide-show-image';
1040 this.update_state();
1041 title_div.insertBefore(this.icon, title_div.firstChild);
1042
1043 // Hook up the event handler.
1044 YAHOO.util.Event.addListener(this.icon, 'click', this.handle_click, null, this);
1045}
1046
1047/** Handle click on a block show/hide icon. */
1048block_hider.prototype.handle_click = function(e) {
1049 YAHOO.util.Event.stopEvent(e);
1050 this.ishidden = !this.ishidden;
1051 this.update_state();
1052 set_user_preference(this.userpref, this.ishidden);
1053}
1054
1055/** Set the state of the block show/hide icon to this.ishidden. */
1056block_hider.prototype.update_state = function () {
1057 if (this.ishidden) {
1058 YAHOO.util.Dom.addClass(this.block, 'hidden');
1059 this.icon.alt = this.hiddentooltip;
1060 this.icon.title = this.hiddentooltip;
1061 this.icon.src = this.hiddenicon;
1062 } else {
1063 YAHOO.util.Dom.removeClass(this.block, 'hidden');
1064 this.icon.alt = this.visibletooltip;
1065 this.icon.title = this.visibletooltip;
1066 this.icon.src = this.visibleicon;
1067 }
1068}
1069
b166403f 1070/** Close the current browser window. */
7a5c78e0 1071function close_window(e) {
1072 YAHOO.util.Event.preventDefault(e);
1073 self.close();
b166403f 1074}
1075
1076/**
1077 * Close the current browser window, forcing the window/tab that opened this
1078 * popup to reload itself. */
1079function close_window_reloading_opener() {
1080 if (window.opener) {
1081 window.opener.location.reload(1);
1082 close_window();
1083 // Intentionally, only try to close the window if there is some evidence we are in a popup.
1084 }
8e7cebb0 1085}
9f319372 1086
1087/**
1088 * Used in a couple of modules to hide navigation areas when using AJAX
1089 */
1090function hide_item(itemid) {
1091 var item = document.getElementById(itemid);
1092 if (item) {
1093 item.style.display = "none";
1094 }
34a2777c 1095}
1096
2538037f 1097function show_item(itemid) {
1098 var item = document.getElementById(itemid);
1099 if (item) {
1100 item.style.display = "";
1101 }
1102}
1103
1104function destroy_item(itemid) {
1105 var item = document.getElementById(itemid);
1106 if (item) {
1107 item.parentNode.removeChild(item);
1108 }
1109}
34a2777c 1110/**
1111 * Tranfer keyboard focus to the HTML element with the given id, if it exists.
1112 * @param controlid the control id.
1113 */
1114function focuscontrol(controlid) {
1115 var control = document.getElementById(controlid);
1116 if (control) {
1117 control.focus();
1118 }
e29380f3 1119}
1120
e11a8328 1121/**
1122 * Transfers keyboard focus to an HTML element based on the old style style of focus
1123 * This function should be removed as soon as it is no longer used
1124 */
428acddb 1125function old_onload_focus(formid, controlname) {
1126 if (document.forms[formid]) {
1127 document.forms[formid].elements[controlname].focus();
e11a8328 1128 }
1129}
1130
e29380f3 1131function scroll_to_end() {
1132 window.scrollTo(0, 5000000);
1133}
1134
1135var scrolltoendtimeout;
1136function repeatedly_scroll_to_end() {
1137 scrolltoendtimeout = setInterval(scroll_to_end, 50);
1138}
1139
1140function cancel_scroll_to_end() {
1141 if (scrolltoendtimeout) {
1142 clearTimeout(scrolltoendtimeout);
1143 scrolltoendtimeout = null;
1144 }
1145}
4d49202f 1146
1147function create_UFO_object(eid) {
1148 UFO.create(FO, eid);
1149}
1bcb7eb5 1150function build_querystring(obj) {
1151 if (typeof obj !== 'object') {
1152 return null;
1153 }
1154 var list = [];
1155 for(var k in obj) {
1156 k = encodeURIComponent(k);
1157 var value = obj[k];
1158 if(obj[k] instanceof Array) {
1159 for(var i in value) {
1160 list.push(k+'[]='+encodeURIComponent(value[i]));
1161 }
1162 } else {
1163 list.push(k+'='+encodeURIComponent(value));
1164 }
1165 }
1166 return list.join('&');
1167}
d25e2ca3 1168
1169function stripHTML(str) {
1170 var re = /<\S[^><]*>/g;
1171 var ret = str.replace(re, "");
1172 return ret;
1173}
1174
1175function json_decode(json) {
1176 try {
1177 var obj = YAHOO.lang.JSON.parse(json);
1178 } catch (e) {
da964d22 1179 alert(e.toString() + "\n" + stripHTML(json));
d25e2ca3 1180 }
1181 return obj;
1182}
1183
1184function json_encode(data) {
1185 try {
1186 var json = YAHOO.lang.JSON.stringify(data);
1187 } catch (e) {
1188 alert(e.toString());
1189 }
1190 return json;
1191}
1192
f8065dd2 1193/**
1194 * Finds all help icons on the page and initiates YUI tooltips for
1195 * each of them, which load a truncated version of the help's content
1196 * on-the-fly asynchronously
1197 */
1198function init_help_icons() {
1199 // var logger = new YAHOO.widget.LogReader(document.body, {draggable: true});
1200
1201 var iconspans = YAHOO.util.Dom.getElementsByClassName('helplink', 'span');
1202
1203 var tooltip = new YAHOO.widget.Tooltip('help_icon_tooltip', {
1204 context: iconspans,
1205 showdelay: 100,
1206 hidedelay: 150,
1207 autodismissdelay: 50000,
1208 underlay: 'none'
1209 });
1210
1211 tooltip.contextTriggerEvent.subscribe(
1212 function(type, args) {
1213 // Fetch help page contents asynchronously
1214 // Load spinner icon while content is loading
1215 var spinner = document.createElement('img');
1216 spinner.src = moodle_cfg.loadingicon;
1217
1218 this.cfg.setProperty('text', spinner);
1219
1220 var context = args[0];
1221 context.title = '';
1222
1223 var link = context.getElementsByTagName('a')[0];
1224 link.title = '';
1225 YAHOO.util.Dom.getElementsByClassName('iconhelp', 'img', link)[0].title = '';
1226 var thistooltip = this;
1227 var ajaxurl = link.href + '&fortooltip=1';
1228
1229
1230 var callback = {
1231 success: function(o) {
1232 thistooltip.cfg.setProperty('text', o.responseText);
1233 },
1234 failure: function(o) {
1235 var debuginfo = o.statusText;
1236 if (moodle_cfg.developerdebug) {
1237 o.statusText += ' (' + ajaxurl + ')';
1238 }
1239 thistooltip.cfg.setProperty('text', debuginfo);
1240 }
1241 };
1242
1243 var conn = YAHOO.util.Connect.asyncRequest("get", ajaxurl, callback);
1244 }
1245 );
1246}
1247
1248/**
1249 * Prints a confirmation dialog in the style of DOM.confirm().
1250 * @param object event A DOM event
1251 * @param string message The message to show in the dialog
1252 * @param string url The URL to forward to if YES is clicked. Disabled if fn is given
1253 * @param function fn A JS function to run if YES is clicked.
1254 */
49690843 1255function confirm_dialog(event, args) {
1256 var message = args.message;
1257 var target = this;
5529f787 1258 target.args = args;
f8065dd2 1259 YAHOO.util.Event.preventDefault(event);
1260
1261 var simpledialog = new YAHOO.widget.SimpleDialog('confirmdialog',
1262 { width: '300px',
1263 fixedcenter: true,
1264 modal: true,
1265 visible: false,
1266 draggable: false
1267 }
1268 );
1269
5f56f0a8 1270 simpledialog.setHeader(mstr.admin.confirmation);
f8065dd2 1271 simpledialog.setBody(message);
1272 simpledialog.cfg.setProperty('icon', YAHOO.widget.SimpleDialog.ICON_WARN);
1273
5529f787 1274 this.handle_cancel = function() {
f8065dd2 1275 this.hide();
1276 };
1277
5529f787 1278 this.handle_yes = function() {
f8065dd2 1279 this.hide();
5529f787 1280
1281 if (target.args.callback) {
1282 // args comes from PHP, so callback will be a string, needs to be evaluated by JS
1283 var callback = eval('('+target.args.callback+')');
1284 callback.apply(this);
1285 }
1286
f8065dd2 1287 if (target.tagName.toLowerCase() == 'a') {
1288 window.location = target.href;
1289 } else if (target.tagName.toLowerCase() == 'input') {
1290 var parentelement = target.parentNode;
1291 while (parentelement.tagName.toLowerCase() != 'form' && parentelement.tagName.toLowerCase() != 'body') {
1292 parentelement = parentelement.parentNode;
1293 }
1294 if (parentelement.tagName.toLowerCase() == 'form') {
1295 parentelement.submit();
1296 }
1297 } else if(moodle_cfg.developerdebug) {
1298 alert("Element of type " + target.tagName + " is not supported by the confirm_dialog function. Use A or INPUT");
1299 }
1300 };
1301
5529f787 1302 var buttons = [ { text: mstr.moodle.cancel, handler: this.handle_cancel, isDefault: true },
1303 { text: mstr.moodle.yes, handler: this.handle_yes } ];
f8065dd2 1304
1305 simpledialog.cfg.queueProperty('buttons', buttons);
1306
1307 simpledialog.render(document.body);
1308 simpledialog.show();
5529f787 1309 return simpledialog;
1310}
1311
1312function dialog_callback() {
1313 console.debug(this);
1314 console.debug(this.args);
f8065dd2 1315}