comparison analysis/analysis.js @ 654:37f3359709bd

Merge
author Nicholas Jillings <n.g.r.jillings@se14.qmul.ac.uk>
date Thu, 31 Mar 2016 15:48:57 +0100
parents 9f0999472b91
children
comparison
equal deleted inserted replaced
605:716c05000a6e 654:37f3359709bd
1 /* 1 /*
2 * Analysis script for WAET 2 * Analysis script for WAET
3 */ 3 */
4 4
5 var chartContext; 5 // Firefox does not have an XMLDocument.prototype.getElementsByName
6 // and there is no searchAll style command, this custom function will
7 // search all children recusrively for the name. Used for XSD where all
8 // element nodes must have a name and therefore can pull the schema node
9 XMLDocument.prototype.getAllElementsByName = function(name)
10 {
11 name = String(name);
12 var selected = this.documentElement.getAllElementsByName(name);
13 return selected;
14 }
15
16 Element.prototype.getAllElementsByName = function(name)
17 {
18 name = String(name);
19 var selected = [];
20 var node = this.firstElementChild;
21 while(node != null)
22 {
23 if (node.getAttribute('name') == name)
24 {
25 selected.push(node);
26 }
27 if (node.childElementCount > 0)
28 {
29 selected = selected.concat(node.getAllElementsByName(name));
30 }
31 node = node.nextElementSibling;
32 }
33 return selected;
34 }
35
36 XMLDocument.prototype.getAllElementsByTagName = function(name)
37 {
38 name = String(name);
39 var selected = this.documentElement.getAllElementsByTagName(name);
40 return selected;
41 }
42
43 Element.prototype.getAllElementsByTagName = function(name)
44 {
45 name = String(name);
46 var selected = [];
47 var node = this.firstElementChild;
48 while(node != null)
49 {
50 if (node.nodeName == name)
51 {
52 selected.push(node);
53 }
54 if (node.childElementCount > 0)
55 {
56 selected = selected.concat(node.getAllElementsByTagName(name));
57 }
58 node = node.nextElementSibling;
59 }
60 return selected;
61 }
62
63 // Firefox does not have an XMLDocument.prototype.getElementsByName
64 if (typeof XMLDocument.prototype.getElementsByName != "function") {
65 XMLDocument.prototype.getElementsByName = function(name)
66 {
67 name = String(name);
68 var node = this.documentElement.firstElementChild;
69 var selected = [];
70 while(node != null)
71 {
72 if (node.getAttribute('name') == name)
73 {
74 selected.push(node);
75 }
76 node = node.nextElementSibling;
77 }
78 return selected;
79 }
80 }
81
82 var chartContext, testData;
6 window.onload = function() { 83 window.onload = function() {
7 // Load the Visualization API and the corechart package. 84 // Load the Visualization API and the corechart package.
8 google.charts.load('current', {'packages':['corechart']}); 85 google.charts.load('current', {'packages':['corechart']});
9 chartContext = new Chart(); 86 chartContext = new Chart();
87 testData = new Data();
88 }
89
90 function get(url) {
91 // Return a new promise.
92 return new Promise(function(resolve, reject) {
93 // Do the usual XHR stuff
94 var req = new XMLHttpRequest();
95 req.open('GET', url);
96 req.onload = function() {
97 // This is called even on 404 etc
98 // so check the status
99 if (req.status == 200) {
100 // Resolve the promise with the response text
101 resolve(req.response);
102 }
103 else {
104 // Otherwise reject with the status text
105 // which will hopefully be a meaningful error
106 reject(Error(req.statusText));
107 }
108 };
109
110 // Handle network errors
111 req.onerror = function() {
112 reject(Error("Network Error"));
113 };
114
115 // Make the request
116 req.send();
117 });
10 } 118 }
11 119
12 function arrayMean(values) { 120 function arrayMean(values) {
13 var mean = 0; 121 var mean = 0;
14 for (var value of values) { 122 for (var value of values) {
16 } 124 }
17 mean /= values.length; 125 mean /= values.length;
18 return mean; 126 return mean;
19 } 127 }
20 128
21 function percentile(values, n) { 129 function percentile(values, p) {
130 //http://web.stanford.edu/class/archive/anthsci/anthsci192/anthsci192.1064/handouts/calculating%20percentiles.pdf
22 values.sort( function(a,b) {return a - b;} ); 131 values.sort( function(a,b) {return a - b;} );
23 // get ordinal rank 132 // get ordinal rank
24 var rank = Math.min(Math.floor(values.length*n/100), values.length-1); 133 var index = values.length*p/100;
25 return values[rank]; 134 var k = Math.floor(index);
135 if (k == index) {
136 return values[k];
137 } else {
138 var f = index-k;
139 var x_int = (1-f)*values[k]+f*values[k+1];
140 return x_int;
141 }
26 } 142 }
27 143
28 function arrayMin(array) { 144 function arrayMin(array) {
29 // Return the minimum value of an array 145 // Return the minimum value of an array
30 var min = array[0]; 146 var min = array[0];
43 if (value > max) { 159 if (value > max) {
44 max = value; 160 max = value;
45 } 161 }
46 } 162 }
47 return max; 163 return max;
164 }
165
166 function boxplotRow(array) {
167 // Take an array of element values and return array of computed intervals
168 var result = {
169 median : percentile(array,50),
170 pct25 : percentile(array,25),
171 pct75 : percentile(array,75),
172 IQR : null,
173 min: null,
174 max: null,
175 outliers: new Array()
176 }
177 result.IQR = result.pct75-result.pct25;
178 var rest = [];
179 var pct75_IQR = result.pct75+1.5*result.IQR;
180 var pct25_IQR = result.pct25-1.5*result.IQR;
181 for (var i=0; i<array.length; i++) {
182 //outliers, ranger above pct75+1.5*IQR or below pct25-1.5*IQR
183 var point = array[i];
184 if (point > pct75_IQR || point < pct25_IQR) {
185 result.outliers.push(point);
186 } else {
187 rest.push(point);
188 }
189 }
190 result.max = arrayMax(rest);
191 result.min = arrayMin(rest);
192 return result;
193
48 } 194 }
49 195
50 function arrayHistogram(values,steps,min,max) { 196 function arrayHistogram(values,steps,min,max) {
51 if (steps == undefined) { 197 if (steps == undefined) {
52 steps = 0.25; 198 steps = 0.25;
75 } 221 }
76 return histogram; 222 return histogram;
77 } 223 }
78 224
79 function Chart() { 225 function Chart() {
80 this.valueData = null; 226 this.valueData;
81 this.commentData = null;
82 this.loadStatus = 0;
83 this.charts = []; 227 this.charts = [];
84
85 var XMLHttp = new XMLHttpRequest();
86 XMLHttp.parent = this;
87 XMLHttp.open("GET","../scripts/score_parser.php?format=JSON",true);
88 XMLHttp.onload = function() {
89 // Now we have the JSON data, extract
90 this.parent.valueData = JSON.parse(this.responseText);
91 this.parent.loadStatus++;
92 }
93 XMLHttp.send();
94 var XMLHttp2 = new XMLHttpRequest();
95 XMLHttp2.parent = this;
96 XMLHttp2.open("GET","../scripts/comment_parser.php?format=JSON",true);
97 XMLHttp2.onload = function() {
98 // Now we have the JSON data, extract
99 this.parent.commentData = JSON.parse(this.responseText);
100 this.parent.loadStatus++;
101 }
102 XMLHttp2.send();
103 228
104 this.chartObject = function(name) { 229 this.chartObject = function(name) {
105 // Create the charting object 230 // Create the charting object
106 this.name = name; 231 this.name = name;
107 this.root = document.createElement("div"); 232 this.root = document.createElement("div");
130 this.buildTable(); 255 this.buildTable();
131 this.writeLatex(); 256 this.writeLatex();
132 this.chart.draw(this.data,this.options); 257 this.chart.draw(this.data,this.options);
133 } 258 }
134 this.sortData = function() { 259 this.sortData = function() {
135 260 this.data.sort(1);
136 var map = this.data.Jf.map(function(el,i){
137 return {index: i, value: el.c[1].v};
138 });
139
140 map.sort(function(a,b){
141 if (a.value > b.value) {return -1;}
142 if (a.value < b.value) {return 1;}
143 return 0;
144 })
145
146 var Jf = [];
147 var cc = [];
148 for (var i=0; i<map.length; i++) {
149 Jf.push(this.data.Jf[map[i].index]);
150 cc.push(this.data.cc[map[i].index]);
151 }
152 this.data.Jf = Jf;
153 this.data.cc = cc;
154 } 261 }
155 this.sortName = function() { 262 this.sortName = function() {
156 var map = this.data.Jf.map(function(el,i){ 263 this.data.sort(0);
157 return {index: i, value: el.c[0].v};
158 });
159
160 map.sort(function(a,b){
161 if (a.value < b.value) {return -1;}
162 if (a.value > b.value) {return 1;}
163 return 0;
164 })
165
166 var Jf = [];
167 var cc = [];
168 for (var i=0; i<map.length; i++) {
169 Jf.push(this.data.Jf[map[i].index]);
170 cc.push(this.data.cc[map[i].index]);
171 }
172 this.data.Jf = Jf;
173 this.data.cc = cc;
174 } 264 }
175 this.handleEvent = function() { 265 this.handleEvent = function() {
176 // Only used to handle the chart.event.addListener(this,'ready') callback 266 // Only used to handle the chart.event.addListener(this,'ready') callback
177 switch(event.currentTarget.getAttribute("name")) 267 switch(event.currentTarget.getAttribute("name"))
178 { 268 {
201 this.print.addEventListener("click",this); 291 this.print.addEventListener("click",this);
202 this.root.appendChild(this.downloadDOM); 292 this.root.appendChild(this.downloadDOM);
203 this.buildTable = function() { 293 this.buildTable = function() {
204 var table = document.createElement("table"); 294 var table = document.createElement("table");
205 table.border = "1"; 295 table.border = "1";
206 for (var rowIndex=0; rowIndex<this.data.If.length; rowIndex++) { 296 var numRows = this.data.getNumberOfRows();
207 var row = document.createElement("tr"); 297 var numColumns = this.data.getNumberOfColumns();
208 table.appendChild(row); 298 for (var columnIndex=0; columnIndex<numColumns; columnIndex++)
209 var rowTitle = document.createElement("td"); 299 {
210 rowTitle.textContent = this.data.If[rowIndex].label; 300 var tableTitle = this.data.getColumnLabel(columnIndex);
211 row.appendChild(rowTitle); 301 if (tableTitle != "") {
212 for (var cIndex=0; cIndex<this.data.cc.length; cIndex++) { 302 var table_row = document.createElement('tr');
213 var column = document.createElement("td"); 303 table.appendChild(table_row);
214 column.textContent = this.data.cc[cIndex][rowIndex].tf; 304 var row_title = document.createElement('td');
215 row.appendChild(column); 305 table_row.appendChild(row_title);
306 row_title.textContent = tableTitle;
307 for (var rowIndex=0; rowIndex<numRows; rowIndex++)
308 {
309 var row_entry = document.createElement('td');
310 table_row.appendChild(row_entry);
311 var entry = this.data.getValue(rowIndex,columnIndex);
312 if (isFinite(Number(entry)))
313 {
314 entry = String(Number(entry).toFixed(4));
315 }
316 row_entry.textContent = entry;
317 }
216 } 318 }
217 } 319 }
218 this.tableDOM.appendChild(table); 320 this.tableDOM.appendChild(table);
219 }; 321 };
220 this.writeLatex = function() { 322 this.writeLatex = function() {
323 var numRows = this.data.getNumberOfRows();
324 var numColumns = this.data.getNumberOfColumns();
221 var root = document.createElement("div"); 325 var root = document.createElement("div");
222 root.className = "code"; 326 root.className = "code";
223 var holder = document.createElement("pre"); 327 var holder = document.createElement("pre");
224 // Table start 328 // Table start
225 var start = document.createElement("p"); 329 var start = document.createElement("p");
226 start.textContent = "\\" + "begin{tabular}{|l|"; 330 start.textContent = "\\" + "begin{tabular}{|l|";
227 holder.appendChild(start); 331 holder.appendChild(start);
228 for (var i=0; i<this.data.cc.length; i++) { 332 for (var i=0; i<numRows; i++) {
229 start.textContent = start.textContent+"c|"; 333 start.textContent = start.textContent+"c|";
230 } 334 }
231 start.textContent = start.textContent.concat("}"); 335 start.textContent = start.textContent.concat("}");
232 // Now write the rows: 336 // Now write the rows:
233 for (var rIndex=0; rIndex<this.data.If.length; rIndex++) { 337 for (var rIndex=0; rIndex<numColumns; rIndex++) {
234 var row = document.createElement("p"); 338 var tableTitle = this.data.getColumnLabel(rIndex);
235 row.textContent = this.data.If[rIndex].label.concat(" & "); 339 if(tableTitle != "")
236 for (var cIndex=0; cIndex<this.data.cc.length; cIndex++) { 340 {
237 row.textContent = row.textContent.concat(this.data.cc[cIndex][rIndex].tf); 341 var row = document.createElement("p");
238 if (cIndex < this.data.cc.length-1) { 342 row.textContent = tableTitle.concat(" & ");
239 row.textContent = row.textContent.concat(" & "); 343 for (var cIndex=0; cIndex<numRows; cIndex++) {
344 var entry = this.data.getValue(cIndex,rIndex);
345 if (isFinite(Number(entry)))
346 {
347 entry = String(Number(entry).toFixed(4));
348 }
349 row.textContent = row.textContent.concat(entry);
350 if (cIndex < numRows-1) {
351 row.textContent = row.textContent.concat(" & ");
352 } else {
353 row.textContent = row.textContent.concat(" \\\\ \\hline");
354 }
240 } 355 }
241 } 356 holder.appendChild(row);
242 holder.appendChild(row); 357 }
243 } 358 }
244 // Table end 359 // Table end
245 var end = document.createElement("p"); 360 var end = document.createElement("p");
246 end.textContent = "\\" + "end{tabular}"; 361 end.textContent = "\\" + "end{tabular}";
247 holder.appendChild(end); 362 holder.appendChild(end);
271 for (var element of page.elements) { 386 for (var element of page.elements) {
272 for (var axis of element.axis) { 387 for (var axis of element.axis) {
273 // Find the axis 388 // Find the axis
274 var axisChart = chartList.find(function(element,index,array){ 389 var axisChart = chartList.find(function(element,index,array){
275 if (element.name == this) {return true;} else {return false;} 390 if (element.name == this) {return true;} else {return false;}
276 },"mean-test-"+axis.id); 391 },"mean-test-"+axis.name);
277 if (axisChart == null) { 392 if (axisChart == null) {
278 axisChart = new this.chartObject("mean-test-"+axis.id); 393 axisChart = new this.chartObject("mean-test-"+axis.name);
279 axisChart.options = { 394 axisChart.options = {
280 'title':'Mean of axis: '+axis.name, 395 'title':'Mean of axis: '+axis.name,
281 'width':window.innerWidth*0.9, 396 'width':window.innerWidth*0.9,
282 'height':(window.innerWidth*0.9)/1.77 397 'height':(window.innerWidth*0.9)/1.77
283 } 398 }
300 chart.writeLatex(); 415 chart.writeLatex();
301 this.charts.push(chart); 416 this.charts.push(chart);
302 } 417 }
303 } 418 }
304 419
420 this.drawTestBoxplot = function() {
421 if (this.valueData == null) {
422 console.log("Error - Data not loaded");
423 return;
424 }
425 var chartList = [];
426
427 // Creates one chart per axis
428
429 // Create the data table
430 for (var page of this.valueData.pages) {
431 for (var element of page.elements) {
432 for (var axis of element.axis) {
433 // Find the axis
434 var axisChart = chartList.find(function(element,index,array){
435 if (element.name == this) {return true;} else {return false;}
436 },"boxplot-test-"+axis.name);
437 if (axisChart == null) {
438 // Axis chart doesn't exist
439 axisChart = new this.chartObject("boxplot-test-"+axis.name);
440 axisChart.options = {
441 'title':'Boxplot of axis '+axis.name,
442 'width':window.innerWidth*0.9,
443 'height':(window.innerWidth*0.9)/1.77,
444 legend: {position: 'none'},
445 lineWidth: 0,
446 series: [{'color': '#D3362D'}],
447 intervals: {
448 barWidth: 1,
449 boxWidth: 1,
450 lineWidth: 2,
451 style: 'boxes'
452 },
453 interval: {
454 max: {
455 style: 'bars',
456 fillOpacity: 1,
457 color: '#777'
458 },
459 min: {
460 style: 'bars',
461 fillOpacity: 1,
462 color: '#777'
463 }
464 }
465 };
466 axisChart.data.addColumn('string','id');
467 axisChart.data.addColumn('number','median');
468 axisChart.data.addColumn({id:'max',type:'number',role:'interval'});
469 axisChart.data.addColumn({id:'min',type:'number',role:'interval'});
470 axisChart.data.addColumn({id:'firstQuartile',type:'number',role:'interval'});
471 axisChart.data.addColumn({id:'median',type:'number',role:'interval'});
472 axisChart.data.addColumn({id:'thirdQuartile',type:'number',role:'interval'});
473 chartList.push(axisChart);
474 document.getElementById("test-pages").appendChild(axisChart.root);
475 }
476 var result = boxplotRow(axis.values);
477 axisChart.data.addRow([element.id,result.median,result.max,result.min,result.pct25,result.median,result.pct75]);
478 }
479 }
480 }
481 // Build and push charts
482 for (var chart of chartList) {
483 chart.chart = new google.visualization.LineChart(chart.chartDOM);
484 chart.chart.draw(chart.data,chart.options);
485 chart.buildTable();
486 chart.writeLatex();
487 this.charts.push(chart);
488 }
489 }
490
305 this.drawPageMean = function() { 491 this.drawPageMean = function() {
306 // First we must get the value data 492 // First we must get the value data
307 if (this.valueData == null) { 493 if (this.valueData == null) {
308 console.log("Error - Data not loaded"); 494 console.log("Error - Data not loaded");
309 return; 495 return;
391 this.charts.push(chart); 577 this.charts.push(chart);
392 } 578 }
393 } 579 }
394 } 580 }
395 } 581 }
582
583 function Data() {
584 // This holds the link between the server side calculations and the client side visualisation of the data
585
586 // Dynamically generate the test filtering / page filterting tools
587 var self = this;
588 // Collect the test types and counts
589 this.testSavedDiv = document.getElementById("test-saved");
590 this.testSaves = null;
591 this.selectURL = null;
592
593 this.specification = new Specification();
594 get("../test-schema.xsd").then(function(response){
595 var parse = new DOMParser();
596 self.specification.schema = parse.parseFromString(response,'text/xml');
597 },function(error){
598 console.log("ERROR: Could not get Test Schema");
599 });
600 this.update = function(url) {
601 var self = this;
602 }
603
604 this.updateData = function(req_str) {
605 // Now go get that data
606 get(req_str).then(function(response){
607 // Returns the data
608 chartContext.valueData = JSON.parse(response);
609 },function(error){console.error(error);});
610 }
611 }
612
613 var interfaceContext = new function() {
614 // This creates the interface for the user to connect with the dynamic back-end to retrieve data
615 this.rootDOM = document.createElement("div");
616 this.getDataButton = {
617 button: document.createElement("button"),
618 parent: this,
619 handleEvent: function(event) {
620 // Get the list of files:
621 var req_str = "../scripts/get_filtered_score.php"+this.parent.getFilterString();
622 testData.updateData(req_str);
623 }
624 }
625 this.getDataButton.button.textContent = "Get Filtered Data";
626 this.getDataButton.button.addEventListener("click",this.getDataButton);
627
628 this.testSaves = {
629 json: null,
630 selectedURL: null,
631 inputs: [],
632 parent: this
633 };
634 this.init = function() {
635 var self = this;
636 get('../scripts/get_tests.php?format=JSON').then(function(response){
637 document.getElementById("test-saved").innerHTML = null;
638 var table = document.createElement("table");
639 table.innerHTML = "<tr><td>Test Filename</td><td>Count</td><td>Include</td></tr>";
640 self.testSaves.json = JSON.parse(response);
641 for (var test of self.testSaves.json.tests) {
642 var tableRow = document.createElement("tr");
643 var tableRowFilename = document.createElement("td");
644 tableRowFilename.textContent = test.testName;
645 var tableRowCount = document.createElement("td");
646 tableRowCount.textContent = test.files.length;
647 tableRow.appendChild(tableRowFilename);
648 tableRow.appendChild(tableRowCount);
649 var tableRowInclude = document.createElement("td");
650 var obj = {
651 root: document.createElement("input"),
652 parent: self.testSaves,
653 handleEvent: function(event) {
654 this.parent.selectedURL = event.currentTarget.getAttribute("source");
655 var self = this;
656 get(this.parent.selectedURL).then(function(response){
657 var parse = new DOMParser();
658 testData.specification.decode(parse.parseFromString(response,'text/xml'));
659 self.parent.parent.generateFilters(testData.specification);
660 self.parent.parent.getFileCount();
661 return true;
662 },function(error){
663 console.log("ERROR: Could not get"+url);
664 return false;
665 });
666 }
667 }
668 obj.root.type = "radio";
669 obj.root.name = "test-include";
670 obj.root.setAttribute("source",test.testName);
671 obj.root.addEventListener("change",obj);
672 tableRowInclude.appendChild(obj.root);
673 tableRow.appendChild(tableRowInclude);
674 table.appendChild(tableRow);
675 self.testSaves.inputs.push(obj);
676 }
677 document.getElementById("test-saved").appendChild(table);
678 },function(error){console.error(error);});
679 }
680
681 this.filterDOM = document.createElement("div");
682 this.filterDOM.innerHTML = "<p>PreTest Filters</p><div id='filter-count'></div>";
683 this.filterObjects = [];
684 this.generateFilters = function(specification) {
685 // Filters are based on the pre and post global surverys
686 var FilterObject = function(parent,specification) {
687 this.parent = parent;
688 this.specification = specification;
689 this.rootDOM = document.createElement("div");
690 this.rootDOM.innerHTML = "<span>ID: "+specification.id+", Type: "+specification.type+"</span>";
691 this.rootDOM.className = "filter-entry";
692 this.handleEvent = function(event) {
693 switch(this.specification.type) {
694 case "number":
695 var name = event.currentTarget.name;
696 eval("this."+name+" = event.currentTarget.value");
697 break;
698 case "checkbox":
699 break;
700 case "radio":
701 break;
702 }
703 this.parent.getFileCount();
704 }
705 this.getFilterPairs = function() {
706 var pairs = [];
707 switch(this.specification.type) {
708 case "number":
709 if (this.min != "") {
710 pairs.push([specification.id+"-min",this.min]);
711 }
712 if (this.max != "") {
713 pairs.push([specification.id+"-max",this.max]);
714 }
715 break;
716 case "radio":
717 case "checkbox":
718 for (var i=0; i<this.options.length; i++) {
719 if (!this.options[i].checked) {
720 pairs.push([specification.id+"-exclude-"+i,specification.options[i].name]);
721 }
722 }
723 break;
724 }
725 return pairs;
726 }
727 switch(specification.type) {
728 case "number":
729 // Number can be ranged by min/max levels
730 this.min = "";
731 this.max = "";
732 this.minDOM = document.createElement("input");
733 this.minDOM.type = "number";
734 this.minDOM.name = "min";
735 this.minDOM.addEventListener("change",this);
736 this.minDOMText = document.createElement("span");
737 this.minDOMText.textContent = "Minimum: ";
738 var pairHolder = document.createElement("div");
739 pairHolder.appendChild(this.minDOMText);
740 pairHolder.appendChild(this.minDOM);
741 this.rootDOM.appendChild(pairHolder);
742
743 this.maxDOM = document.createElement("input");
744 this.maxDOM.type = "number";
745 this.maxDOM.name = "max";
746 this.maxDOM.addEventListener("change",this);
747 this.maxDOMText = document.createElement("span");
748 this.maxDOMText.textContent = "Maximum: ";
749 var pairHolder = document.createElement("div");
750 pairHolder.appendChild(this.maxDOMText);
751 pairHolder.appendChild(this.maxDOM);
752 this.rootDOM.appendChild(pairHolder);
753 break;
754 case "radio":
755 case "checkbox":
756 this.options = [];
757 for (var i=0; i<specification.options.length; i++) {
758 var option = specification.options[i];
759 var pairHolder = document.createElement("div");
760 var text = document.createElement("span");
761 text.textContent = option.text;
762 var check = document.createElement("input");
763 check.type = "checkbox";
764 check.setAttribute("option-index",i);
765 check.checked = true;
766 check.addEventListener("click",this);
767 this.options.push(check);
768 pairHolder.appendChild(text);
769 pairHolder.appendChild(check);
770 this.rootDOM.appendChild(pairHolder);
771 }
772 break;
773 default:
774 break;
775 }
776 }
777 for (var survey_entry of specification.preTest.options.concat(specification.postTest.options)) {
778 switch(survey_entry.type) {
779 case "number":
780 case "radio":
781 case "checkbox":
782 var node = new FilterObject(this,survey_entry);
783 this.filterObjects.push(node);
784 this.filterDOM.appendChild(node.rootDOM);
785 break;
786 default:
787 break;
788 }
789 }
790 document.getElementById("test-saved").appendChild(this.filterDOM);
791 document.getElementById("test-saved").appendChild(this.getDataButton.button);
792 }
793 this.getFilterString = function() {
794 var pairs = [];
795 for (var obj of this.filterObjects) {
796 pairs = pairs.concat(obj.getFilterPairs());
797 }
798 var req_str = "?url="+this.testSaves.selectedURL;
799 var index = 0;
800 while(pairs[index] != undefined) {
801 req_str += '&';
802 req_str += pairs[index][0]+"="+pairs[index][1];
803 index++;
804 }
805 return req_str;
806 }
807 this.getFilteredUrlArray = function() {
808 var req_str = "../scripts/get_filtered_count.php"+this.getFilterString();
809 return get(req_str).then(function(response){
810 var urls = JSON.parse(response);
811 return urls.urls;
812 },function(error){
813 console.error(error);
814 });
815 }
816 this.getFileCount = function() {
817 // First we must get the filter pairs
818 this.getFilteredUrlArray().then(function(response){
819 var str = "Filtered to "+response.length+" file";
820 if (response.length != 1) {
821 str += "s.";
822 } else {
823 str += ".";
824 }
825 document.getElementById("filter-count").textContent = str;
826 },function(error){});
827 }
828
829 this.init();
830 }