revised adobe XSS protection SC#346
[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');
5 if (testwindow == null)
6 {alert(msg);}
7 else {
8 testwindow.close();
9 }
10}
11
63d28811 12function popUpProperties(inobj) {
13 op = window.open();
14 op.document.open('text/plain');
15 for (objprop in inobj) {
16 op.document.write(objprop + ' => ' + inobj[objprop] + '\n');
17 }
18 op.document.close();
19}
20
21function fillmessagebox(text) {
22 document.form.message.value = text;
23}
24
25function copyrichtext(textname) {
26/// Legacy stub for old editor - to be removed soon
27 return true;
28}
29
30function checkall() {
31 void(d=document);
32 void(el=d.getElementsByTagName('INPUT'));
33 for(i=0;i<el.length;i++)
34 void(el[i].checked=1)
35}
36
03f9425f 37function checknone() {
38 void(d=document);
39 void(el=d.getElementsByTagName('INPUT'));
40 for(i=0;i<el.length;i++)
41 void(el[i].checked=0)
42}
43
63d28811 44function lockoptions(form, master, subitems) {
027d0485 45 // Subitems is an array of names of sub items.
46 // Optionally, each item in subitems may have a
63d28811 47 // companion hidden item in the form with the
027d0485 48 // same name but prefixed by "h".
63d28811 49 if (eval("document."+form+"."+master+".checked")) {
50 for (i=0; i<subitems.length; i++) {
51 unlockoption(form, subitems[i]);
52 }
53 } else {
54 for (i=0; i<subitems.length; i++) {
55 lockoption(form, subitems[i]);
56 }
57 }
58 return(true);
59}
60
f07b9627 61function lockoption(form,item) {
62 eval("document."+form+"."+item+".disabled=true");/* IE thing */
63 if(document.forms[form].elements['h'+item]) {
64 eval("document."+form+".h"+item+".value=1");
65 }
66}
67
68function unlockoption(form,item) {
69 eval("document."+form+"."+item+".disabled=false");/* IE thing */
70 if(document.forms[form].elements['h'+item]) {
71 eval("document."+form+".h"+item+".value=0");
72 }
73}
50ef8eb9 74function lockoptionsall(formid) {
f07b9627 75 var lock = new Object();
76 var varname = formid.replace(/\-/g, '_');
77 var items = eval(varname+'items');
78 var form = document.forms[formid];
50ef8eb9 79 for (var master in items){
80 var subitems=items[master].dependents;
81 var thislock;
9c03bbaa 82 if (items[master].condition=='notchecked'){
50ef8eb9 83 thislock=!form.elements[master].checked;
9c03bbaa 84 } else if (items[master].condition=='checked'){
85 thislock=form.elements[master].checked;
a23f0aaf 86 } else if (items[master].condition=='noitemselected'){
87 thislock=(form.elements[master].selectedIndex==-1);
e24b7f85 88 } else if (items[master].condition=='eq'){
89 thislock=(form.elements[master].value==items[master].value);
9c03bbaa 90 } else {
e24b7f85 91 thislock=(form.elements[master].value!=items[master].value);
92
50ef8eb9 93 }
94
95 for (var i=0; i<subitems.length; i++) {
96 if (lock[subitems[i]]!=null){
97 lock[subitems[i]] = thislock || lock[subitems[i]];
98 }else{
99 lock[subitems[i]] = thislock;
100 }
101 }
102
103 for (var item in lock) {
104 form.elements[item].disabled=lock[item];
105 }
106 }
107 return(true);
108}
109
d01a38cb 110function lockoptionsallsetup(formid) {
f07b9627 111 var varname = formid.replace(/\-/g, '_');
112 var items=eval(varname+'items');
d01a38cb 113 var form=document.forms[formid];
19110c57 114 for (var i = 0; i < form.elements.length; i++){
115 var found=false;
116 var formelement = form.elements[i];
117 if (formelement.type=='reset'){
118 formelement.onclick = function(){this.form.reset();return lockoptionsall(this.form.getAttribute('id'));};
119 formelement.onblur = function(){this.form.reset();return lockoptionsall(this.form.getAttribute('id'));};
120 formelement.onchange = function(){this.form.reset();return lockoptionsall(this.form.getAttribute('id'));};
121 } else {
122 for (var master in items){
123 if (master==formelement.name){
124 formelement.onclick = function(){return lockoptionsall(this.form.getAttribute('id'));};
125 formelement.onblur = function(){return lockoptionsall(this.form.getAttribute('id'));};
126 formelement.onchange = function(){return lockoptionsall(this.form.getAttribute('id'));};
127 break;
128 }
129 }
130 }
d01a38cb 131 }
19110c57 132
d01a38cb 133 return lockoptionsall(formid);
134}
50ef8eb9 135
7678e65c 136
137function submitFormById(id) {
138 var theform = document.getElementById(id);
139 if(!theform) {
140 return false;
141 }
142 if(theform.tagName != 'FORM') {
143 return false;
144 }
145 if(!theform.onsubmit || theform.onsubmit()) {
146 return theform.submit();
147 }
148}
363cb62c 149
8ceb09e0 150function select_all_in(elTagName, elClass, elId) {
363cb62c 151 var inputs = document.getElementsByTagName('INPUT');
8ceb09e0 152 inputs = filterByParent(inputs, function(el) {return findParentNode(el, elTagName, elClass, elId);});
363cb62c 153 for(var i = 0; i < inputs.length; ++i) {
bee40515 154 if(inputs[i].type == 'checkbox' || inputs[i].type == 'radio') {
363cb62c 155 inputs[i].checked = 'checked';
156 }
157 }
158}
159
8ceb09e0 160function deselect_all_in(elTagName, elClass, elId) {
363cb62c 161 var inputs = document.getElementsByTagName('INPUT');
8ceb09e0 162 inputs = filterByParent(inputs, function(el) {return findParentNode(el, elTagName, elClass, elId);});
363cb62c 163 for(var i = 0; i < inputs.length; ++i) {
bee40515 164 if(inputs[i].type == 'checkbox' || inputs[i].type == 'radio') {
363cb62c 165 inputs[i].checked = '';
166 }
167 }
168}
169
170function confirm_if(expr, message) {
171 if(!expr) {
172 return true;
173 }
174 return confirm(message);
175}
47aa42e2 176
177
178/*
179 findParentNode (start, elementName, elementClass, elementID)
50ef8eb9 180
47aa42e2 181 Travels up the DOM hierarchy to find a parent element with the
182 specified tag name, class, and id. All conditions must be met,
183 but any can be ommitted. Returns the BODY element if no match
184 found.
185*/
186function findParentNode(el, elName, elClass, elId) {
187 while(el.nodeName != 'BODY') {
188 if(
189 (!elName || el.nodeName == elName) &&
190 (!elClass || el.className.indexOf(elClass) != -1) &&
191 (!elId || el.id == elId))
192 {
193 break;
194 }
195 el = el.parentNode;
196 }
197 return el;
198}
19194f82 199/*
200 findChildNode (start, elementName, elementClass, elementID)
201
202 Travels down the DOM hierarchy to find all child elements with the
203 specified tag name, class, and id. All conditions must be met,
204 but any can be ommitted.
a23f0aaf 205 Doesn't examine children of matches.
19194f82 206*/
207function findChildNodes(start, tagName, elementClass, elementID, elementName) {
208 var children = new Array();
209 for (var childIndex in start.childNodes) {
a23f0aaf 210 var classfound = false;
19194f82 211 var child = start.childNodes[childIndex];
a23f0aaf 212 if((child.nodeType == 1) &&//element node type
213 (elementClass && (typeof(child.className)=='string'))){
214 var childClasses = child.className.split(/\s+/);
215 for (var childClassIndex in childClasses){
216 if (childClasses[childClassIndex]==elementClass){
217 classfound = true;
218 break;
219 }
220 }
221 }
f07b9627 222 if(child.nodeType == 1) { //element node type
223 if ( (!tagName || child.nodeName == tagName) &&
224 (!elementClass || classfound)&&
225 (!elementID || child.id == elementID) &&
226 (!elementName || child.name == elementName))
227 {
228 children = children.concat(child);
229 } else {
230 children = children.concat(findChildNodes(child, tagName, elementClass, elementID, elementName));
231 }
19194f82 232 }
19194f82 233 }
234 return children;
235}
236/*
237 elementSetHide (elements, hide)
238
239 Adds or removes the "hide" class for the specified elements depending on boolean hide.
240*/
241function elementShowAdvanced(elements, show) {
242 for (var elementIndex in elements){
243 element = elements[elementIndex];
244 element.className = element.className.replace(new RegExp(' ?hide'), '')
245 if(!show) {
246 element.className += ' hide';
247 }
248 }
249}
250
251function showAdvancedOnClick(button, hidetext, showtext){
252 var toSet=findChildNodes(button.form, null, 'advanced');
253 var buttontext = '';
254 if (button.form.elements['mform_showadvanced_last'].value == '0') {
255 elementShowAdvanced(toSet, true);
256 buttontext = hidetext;
257 button.form.elements['mform_showadvanced_last'].value = '1';
258 } else {
259 elementShowAdvanced(toSet, false);
260 buttontext = showtext;
261 button.form.elements['mform_showadvanced_last'].value = '0';
262 }
263 var formelements = button.form.elements;
264 for (var i in formelements){
265 if (formelements[i].name=='mform_showadvanced'){
266 formelements[i].value = buttontext;
267 }
268 }
269 //never submit the form if js is enabled.
270 return false;
271}
47aa42e2 272
273/*
274 elementToggleHide (element, elementFinder)
275
276 If elementFinder is not provided, toggles the "hidden" class for the specified element.
277 If elementFinder is provided, then the "hidden" class will be toggled for the object
278 returned by the function call elementFinder(element).
279
280 If persistent == true, also sets a cookie for this.
281*/
19194f82 282function elementToggleHide(el, persistent, elementFinder) {
47aa42e2 283 if(!elementFinder) {
284 var obj = el;
285 }
286 else {
287 var obj = elementFinder(el);
288 }
289 if(obj.className.indexOf('hidden') == -1) {
290 obj.className += ' hidden';
19194f82 291 var shown = 0;
47aa42e2 292 }
293 else {
19194f82 294 obj.className = obj.className.replace(new RegExp(' ?hidden'), '')
295 var shown = 1;
47aa42e2 296 }
19194f82 297
47aa42e2 298 if(persistent == true) {
299 new cookie('hide:' + obj.id, 1, (shown ? -1 : 356), '/').set();
300 }
301}
302
303
304function elementCookieHide(id) {
305 var obj = document.getElementById(id);
306 var cook = new cookie('hide:' + id).read();
307 if(cook != null) {
308 elementToggleHide(obj, false);
309 }
310}
311
312function filterByParent(elCollection, parentFinder) {
313 var filteredCollection = [];
314 for(var i = 0; i < elCollection.length; ++i) {
315 var findParent = parentFinder(elCollection[i]);
316 if(findParent.nodeName != 'BODY') {
317 filteredCollection.push(elCollection[i]);
318 }
319 }
320 return filteredCollection;
321}
322
7979105c 323/*
324 All this is here just so that IE gets to handle oversized blocks
325 in a visually pleasing manner. It does a browser detect. So sue me.
326*/
327
328function fix_column_widths() {
329 var agt = navigator.userAgent.toLowerCase();
330 if ((agt.indexOf("msie") != -1) && (agt.indexOf("opera") == -1)) {
331 fix_column_width('left-column');
332 fix_column_width('right-column');
333 }
334}
335
336function fix_column_width(colName) {
337 if(column = document.getElementById(colName)) {
338 if(!column.offsetWidth) {
339 setTimeout("fix_column_width('" + colName + "')", 20);
340 return;
341 }
342
343 var width = 0;
344 var nodes = column.childNodes;
345
346 for(i = 0; i < nodes.length; ++i) {
347 if(nodes[i].className.indexOf("sideblock") != -1 ) {
348 if(width < nodes[i].offsetWidth) {
349 width = nodes[i].offsetWidth;
350 }
351 }
352 }
353
354 for(i = 0; i < nodes.length; ++i) {
355 if(nodes[i].className.indexOf("sideblock") != -1 ) {
356 nodes[i].style.width = width + 'px';
357 }
358 }
359 }
360}
d13c5938 361
362
363/*
364 Insert myValue at current cursor position
365*/
366function insertAtCursor(myField, myValue) {
367 // IE support
368 if (document.selection) {
369 myField.focus();
370 sel = document.selection.createRange();
371 sel.text = myValue;
372 }
373 // Mozilla/Netscape support
374 else if (myField.selectionStart || myField.selectionStart == '0') {
375 var startPos = myField.selectionStart;
376 var endPos = myField.selectionEnd;
377 myField.value = myField.value.substring(0, startPos)
378 + myValue + myField.value.substring(endPos, myField.value.length);
379 } else {
380 myField.value += myValue;
381 }
382}