Annotation of loncom/homework/task_grading.js, revision 1.2
1.1 albertel 1: // JavaScript Document
2:
3: if (! Node) {
4: //If the node Type constants are not set, set the ones I need
5: var Node = new Object;
6: Node.TEXT_NODE = 3;
7: }
8:
9: //Detect IE
10: var isIE = (navigator.appName.indexOf("Explorer") > -1);
11:
12: //Attach to the onLoad event
13: window.onload = setEvents;
14: if (window.captureEvents) {
15: window.captureEvents(Event.LOAD);
16: }
17:
18: /*
19: * Utilitity Functions
20: */
21: //Generic tool for getting all tags of a specific type and class
22: //tagName - Name of tag to search for
23: //withClass - Name of Class to search for
24: //expCnt - OPTIONAL max number of elements to find
25: function myGetElementsByClass(tagName, withClass, expCnt) {
26: var tags = document.getElementsByTagName(tagName);
27: var rtn = new Array();
28: expCnt = expCnt || false; //Default value for expCnt
29:
30: //Find only the ones with the right class
31: for(var i=0; i < tags.length; i++) {
32: if (tags[i].className == withClass) {
33: rtn.push(tags[i]);
34: if (expCnt > 0 && rtn.length > expCnt) { break; }
35: }
36: }
37: return rtn;
38: }
39:
40: //Find the first text Node under current node
41: //Returns the node itself, not the text
42: //NOTE: Do not call this on a node that may have multiple text Nodes
43: // as children
44: function getTextNode(node) {
45: if (node.nodeType == Node.TEXT_NODE) {
46: return node;
47: }
48:
49: for(var i=0; i < node.childNodes.length; i++) {
50: var rtn = getTextNode(node.childNodes[i]);
51: if (rtn) { return rtn; }
52: }
53: return false;
54: }
55:
56: //Get object that raised event
57: function getEventObject(e) {
58: //Make sure I have the event
59: if (!e) { e = window.event; }
60:
61: //Get the object that raised the event
62: if (e.target) {
63: return e.target;
64: } else if (e.srcElement) {
65: return e.srcElement;
66: }
67: return false;
68: }
69:
70: //Attach an onClick event handler to a node
1.2 ! albertel 71: function attachEvent(node, eventName, func) {
! 72: node[eventName] = func; //Add event
! 73:
1.1 albertel 74: if (!isIE) {
75: //Allow me to raise events
1.2 ! albertel 76: node.addEventListener(eventName, func, true); //false to get it in bubble not capture
! 77: }
! 78: if (node.captureEvents) {
! 79: var eventMap = new Object;
! 80: eventMap["onclick"] = Event.CLICK;
! 81: eventMap["onchange"] = Event.CHANGE;
! 82: eventMap["onsubmit"] = Event.SUBMIT;
! 83: if (! eventMap[eventName]) { return false; }
! 84: node.captureEvents(eventMap[eventName]);
1.1 albertel 85: }
86: }
87:
1.2 ! albertel 88:
1.1 albertel 89: //Fire an event on a given node
90: function dispatchEvent(node, eventName) {
91: if (document.createEvent) {
92: var evt = document.createEvent("Events"); //Simple event object
93: evt.initEvent(eventName, true, true); //true for can bubble, true for cancelable
94: node.dispatchEvent(evt);
95: } else {
96: //IE version
97: var evt = document.createEventObject();
98: node.fireEvent(eventName,evt);
99: evt.cancelBubble = true;
100: }
101: }
102:
103: /*
104: * Setup Functions
105: */
106: //Master setup function
107: function setEvents() {
108: setupHandin();
109: setupGrading();
110: setupButtons();
111: }
112:
113: //Setup the File handin list
114: function setupHandin() {
115: var handin;
116:
117: //Create the 'Collapse' button
118: var li = document.createElement('li');
119: var a = document.createElement('a');
120: var txt = document.createTextNode('Collapse');
121: a.setAttribute('href', '#');
1.2 ! albertel 122: attachEvent(a, "onchange", onSlideDrawer);
1.1 albertel 123: a.appendChild(txt);
124: li.appendChild(a);
125:
126: //Find the handin list
127: var lists = myGetElementsByClass('ul', 'LC_GRADING_handininfo', 1);
128: if (lists.length > 0) {
129: handin = lists[0];
130: } else {
131: return false;
132: }
133:
134: //Trim the displayed file paths
135: for(var i=0; i < handin.childNodes.length; i++) {
136: var txt = getTextNode(handin.childNodes[i]);
137: if (txt) {
138: var j = txt.nodeValue.indexOf('portfolio/');
139: if (j > 0) {
140: txt.nodeValue = txt.nodeValue.substr(j + 'portfolio/'.length);
141: }
142: }
143: }
144:
145: //Add the button
146: handin.insertBefore(li, handin.firstChild);
147:
148: //Adjust height of the list
149: var item_cnt = handin.getElementsByTagName('li').length * 1.3; //Lines take about 1.3em ea.
150: handin.style.height = item_cnt + 'em';
151: }
152:
153: //Add events to all grading radio buttons
154: function setupGrading() {
155: var inputs = document.getElementsByTagName('input');
156:
157: for (var i = 0; i < inputs.length; i++) {
158: if (inputs[i].type == "radio") {
159: var val = inputs[i].value;
1.2 ! albertel 160: if (val == "pass" || val == "fail" || val == "review" || val == "ungraded") {
! 161: attachEvent(inputs[i], "onchange", onSetGrade);
! 162: attachEvent(inputs[i], "onclick", onSetGrade);
1.1 albertel 163: }
164: if (inputs[i].checked) {
165: dispatchEvent(inputs[i], 'onclick');
166: }
167: }
168: }
169: }
170:
171: //Adjust the Done/Stop/Fail All button set
172: function setupButtons() {
1.2 ! albertel 173: //Setup the onSubmit validation
! 174: var frms = document.getElementsByTagName('form');
! 175: for(var i=0; i < frms.length; i++ ) {
! 176: if (frms[i].name == "lonhomework") {
! 177: attachEvent(frms[i], "onsubmit", onValidate);
! 178: }
! 179: }
1.1 albertel 180: }
181:
182: /*
183: * Events
184: */
185: //Slide the Handin list up and down like a drawer
186: function onSlideDrawer(e) {
187: var obj = getEventObject(e);
188: var txt = getTextNode(obj);
189: txt.nodeValue = (txt.nodeValue == 'Collapse') ? 'Expand':'Collapse';
190:
191: var list = obj.parentNode.parentNode;
192: var item_cnt = (txt.nodeValue == 'Collapse') ? list.getElementsByTagName('li').length : 1;
193: list.style.height = (item_cnt*1.3) + 'em'; //Lines take about 1.3em ea.
194: return false;
195: }
196:
197: //Fail all ungraded criteria
1.2 ! albertel 198: function onFailRest() {
1.1 albertel 199: var inputs = document.getElementsByTagName('input');
200:
201: var graded = false;
202: for (var i = 0; i < inputs.length; i++) {
203: if (inputs[i].type == "radio") {
204: var val = inputs[i].value;
205: if (val == "ungraded" ) {
206: //Flag whether this criteria is graded or not
207: //I depend on 'ungraded' being the first radio button in each set
208: graded = ! inputs[i].checked;
209: } else if (val == "fail" && !graded) {
210: inputs[i].checked = true;
211:
212: //Fire the onclick event to get colors
213: dispatchEvent(inputs[i], 'onclick');
214: }
215: }
216: }
217: }
218:
1.2 ! albertel 219: //Set background for grade chosen
1.1 albertel 220: function onSetGrade( e ) {
221: var obj = getEventObject(e);
222: var grade;
223: var gradediv;
224:
225: //Search for parent DIV
226: gradediv = obj;
227: while (gradediv.tagName != 'DIV') {
228: gradediv = gradediv.parentNode;
229: }
1.2 ! albertel 230:
! 231: rdo = gradediv.getElementsByTagName('INPUT');
! 232: for(var i=0; i < rdo.length; i++) {
! 233: if ( rdo[i].checked ) {
! 234: grade = rdo[i].value;
! 235: break;
! 236: }
! 237: }
1.1 albertel 238:
239: gradediv.className = "LC_GRADING_grade LC_GRADING_" + grade;
240: }
1.2 ! albertel 241:
! 242: //Validate form before submit
! 243: function onValidate(e) {
! 244: var obj = getEventObject(e);
! 245: var ok = true;
! 246: var inputs = document.getElementsByTagName('input');
! 247:
! 248: var cnt = 0;
! 249: for (var i = 0; i < inputs.length; i++) {
! 250: if (inputs[i].type == "radio") {
! 251: var val = inputs[i].value;
! 252: if (val == "ungraded" && inputs[i].checked) {
! 253: cnt++;
! 254: }
! 255: }
! 256: }
! 257: if (cnt) {
! 258: ok = confirm("You have " + cnt + " questions still ungraded.\nThis will return an ungraded task to the queue?");
! 259: }
! 260: return ok;
! 261: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>