Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(68)

Side by Side Diff: chrome/common/extensions/docs/examples/extensions/benchmark/options.js

Issue 280383008: Delete benchmarking extension, remove API's ability to enable/disable SPDY (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Remove benchmarking extension instead Created 6 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 var max_sample = 0;
6
7 Array.max = function(array) {
8 return Math.max.apply( Math, array );
9 }
10
11 Array.min = function(array) {
12 return Math.min.apply( Math, array );
13 };
14
15 // Compute the average of an array, removing the min/max.
16 Array.avg = function(array) {
17 var count = array.length;
18 var sum = 0;
19 var min = array[0];
20 var max = array[0];
21 for (var i = 0; i < count; i++) {
22 sum += array[i];
23 if (array[i] < min) {
24 min = array[i];
25 }
26 if (array[i] > max) {
27 max = array[i];
28 }
29 }
30 if (count >= 3) {
31 sum = sum - min - max;
32 count -= 2;
33 }
34 return sum / count;
35 }
36
37 // Compute the sample standard deviation of an array
38 Array.stddev = function(array) {
39 var count = array.length;
40 var mean = 0;
41 for (var i = 0; i < count; i++) {
42 mean += array[i];
43 }
44 mean /= count;
45 var variance = 0;
46 for (var i = 0; i < count; i++) {
47 var deviation = mean - array[i];
48 variance = variance + deviation * deviation;
49 }
50 variance = variance / (count - 1);
51 return Math.sqrt(variance);
52 }
53
54 function handleFileSelect(evt) {
55 var files = evt.target.files;
56 for (var i = 0, f; f = files[i]; i++) {
57 var reader = new FileReader();
58 reader.onload = function(evt) {
59 document.getElementById("testurl").value = evt.target.result;
60 }
61 reader.readAsText(f);
62 };
63 }
64
65 var THTAG = "th";
66 var TDTAG = "td";
67 var NONE_DISPLAY = "none";
68 var CELL_DISPLAY = "table-cell";
69 var BRIEF_VIEW = "Show More Details";
70 var FULL_VIEW = "Hide Details";
71
72 // Expand or shrink the result table.
73 // Called when clicking button "Show More Details/Hide Details".
74 function expand() {
75 if (document.getElementById("expand").value == BRIEF_VIEW) {
76 // From biref view to detailed view.
77 var headers = document.getElementsByTagName(THTAG);
78 var cells = document.getElementsByTagName(TDTAG);
79
80 // Display the hidden metrics (both headers and data cells).
81 for (var i = 0; i < headers.length; i++) {
82 if (headers[i].style.display == NONE_DISPLAY) {
83 headers[i].style.display = CELL_DISPLAY;
84 }
85 }
86
87 for (i = 0; i < cells.length; i++) {
88 if (cells[i].style.display == NONE_DISPLAY) {
89 cells[i].style.display = CELL_DISPLAY;
90 }
91 }
92
93 document.getElementById("expand").value = FULL_VIEW;
94 } else {
95 // From detailed view to brief view.
96 var headers = document.getElementsByTagName(THTAG);
97 var cells = document.getElementsByTagName(TDTAG);
98
99 // Hide some metrics.
100 for (var i = 0; i < headers.length; i++) {
101 if (headers[i].style.display == CELL_DISPLAY) {
102 headers[i].style.display = NONE_DISPLAY;
103 }
104 }
105
106 for (i = 0; i < cells.length; i++) {
107 if (cells[i].style.display == CELL_DISPLAY) {
108 cells[i].style.display = NONE_DISPLAY;
109 }
110 }
111
112 document.getElementById("expand").value = BRIEF_VIEW;
113 }
114
115 // Use cookie to store current expand/hide status.
116 var lastValue = document.getElementById("expand").value;
117 document.cookie = "lastValue=" + lastValue;
118 }
119
120 // Reloading the page causes table to shrink (default original status).
121 // Cookie remembers last status of table (in terms of expanded or shrunk).
122 function restoreTable() {
123 if (document.cookie == "lastValue=Hide Details") {
124 var headers = document.getElementsByTagName(THTAG);
125 var cells = document.getElementsByTagName(TDTAG);
126
127 for (var i = 0; i < headers.length; i++) {
128 if (headers[i].style.display == NONE_DISPLAY) {
129 headers[i].style.display = CELL_DISPLAY;
130 }
131 }
132 for (i = 0; i < cells.length; i++) {
133 if (cells[i].style.display == NONE_DISPLAY) {
134 cells[i].style.display = CELL_DISPLAY;
135 }
136 }
137 document.getElementById("expand").value = FULL_VIEW;
138 }
139 }
140
141 // A class to store the data to plot.
142 function PData() {
143 this.xAxis = "Iteration(s)";
144 this.yAxis = "";
145 this.A = []; // Two data sets for comparison.
146 this.B = [];
147 this.avgA = []; // Avg value is plotted as a line.
148 this.avgB = [];
149 this.maxA = 0;
150 this.maxB = 0;
151 this.countA = 0; // Size of the data sets.
152 this.countB = 0;
153
154 this.setYAxis = function(str) {
155 this.yAxis = str;
156 }
157
158 this.setAvg = function(arr, cha) {
159 if (cha == 'A') {
160 var avgA = Array.avg(arr);
161 for (var i = 1; i <= this.countA; i++) {
162 this.avgA.push([i, avgA]);
163 }
164 } else if (cha == 'B') {
165 var avgB = Array.avg(arr);
166 for (var i = 1; i <= this.countB; i++) {
167 this.avgB.push([i, avgB]);
168 }
169 }
170 }
171
172 this.setMax = function(arr, cha) {
173 if (cha == 'A') {
174 this.maxA = Array.max(arr);
175 } else if (cha == 'B') {
176 this.maxB = Array.max(arr);
177 }
178 }
179
180 // Add an entry to the array.
181 this.addArr = function(val, cha) {
182 if (cha == 'A') {
183 this.countA++;
184 this.A.push([this.countA, val]);
185 } else if (cha == 'B') {
186 this.countB++;
187 this.B.push([this.countB, val]);
188 }
189 }
190
191 // Plot the graph at the specified place.
192 this.plot = function(placeholder) {
193 $.plot(placeholder,
194 [// Line A
195 {
196 data: this.A,
197 label: "A's " + this.yAxis + " in " + this.countA + " " + this.xAxis,
198 points: {
199 show: true
200 },
201 lines: {
202 show: true
203 }
204 },
205
206 // Line B
207 {
208 data: this.B,
209 label: "B's " + this.yAxis + " in " + this.countB + " " + this.xAxis,
210 points: {
211 show: true
212 },
213 lines: {
214 show: true
215 }
216 },
217
218 // Line avgA
219 {
220 data: this.avgA,
221 label: "A's avg " + this.yAxis,
222 dashes: {
223 show: true
224 }
225 },
226
227 // Line avgB
228 {
229 data: this.avgB,
230 label: "B's avg " + this.yAxis,
231 dashes: {
232 show: true
233 }
234 }],
235
236 // Axis and legend setup.
237 { xaxis: {
238 max: this.countA > this.countB ? this.countA : this.countB,
239 tickSize: 1,
240 tickDecimals: 0
241 },
242 yaxis: {
243 // Leave some space for legend.
244 max: this.maxA > this.maxB ? this.maxA * 1.5 : this.maxB * 1.5
245 },
246 legend: {
247 backgroundOpacity: 0
248 }
249 });
250 }
251 }
252
253 // Compare the selected metric of the two selected data sets.
254 function compare() {
255 var checkboxArr = document.getElementsByName("checkboxArr");
256 var radioArr = document.getElementsByName("radioArr");
257
258 if (checkAmount(checkboxArr) != 2) {
259 alert("please select two rows to compare");
260 return;
261 }
262
263 var rowIndexArr = getSelectedIndex(checkboxArr);
264 var colIndexArr = getSelectedIndex(radioArr);
265 // To this point, it is for sure that rowIndexArr has two elements
266 // while colIndexArr has one.
267 var selectedRowA = rowIndexArr[0];
268 var selectedRowB = rowIndexArr[1];
269 var selectedCol = colIndexArr[0];
270
271 var extension = chrome.extension.getBackgroundPage();
272 var data = extension.results.data;
273 var selectedA = getSelectedResults(data,selectedRowA,selectedCol);
274 var selectedB = getSelectedResults(data,selectedRowB,selectedCol);
275 var yAxis = getMetricName(selectedCol);
276
277 // Indicate A and B on selected rows.
278 checkboxArr[selectedRowA].parentElement.firstChild.data = "A";
279 checkboxArr[selectedRowB].parentElement.firstChild.data = "B";
280
281 plot(selectedA, selectedB, yAxis);
282 }
283
284 // Show the comparison graph.
285 function plot(A, B, axis) {
286 var plotData = new PData();
287
288 plotData.setYAxis(axis);
289 for (var i = 0; i < A.length; i++) {
290 plotData.addArr(A[i],'A');
291 }
292 for (var i = 0; i < B.length; i++) {
293 plotData.addArr(B[i],'B');
294 }
295 plotData.setAvg(A,'A');
296 plotData.setAvg(B,'B');
297 plotData.setMax(A,'A');
298 plotData.setMax(B,'B');
299
300 var placeholder = document.getElementById("placeholder");
301 placeholder.style.display = "";
302 plotData.plot(placeholder);
303 }
304
305 var METRIC = {"STARTLOAD": 0, "COMMITLOAD": 1, "DOCLOAD": 2, "PAINT": 3,
306 "TOTAL": 4, "REQUESTS": 5, "CONNECTS": 6, "READKB": 7,
307 "WRITEKB": 8, "READKBPS": 9, "WRITEKBPS": 10};
308
309 // Retrieve the metric name from index.
310 function getMetricName(index) {
311 switch (index) {
312 case METRIC.STARTLOAD:
313 return "Start Load Time";
314 case METRIC.COMMITLOAD:
315 return "Commit Load Time";
316 case METRIC.DOCLOAD:
317 return "Doc Load Time";
318 case METRIC.PAINT:
319 return "Paint Time";
320 case METRIC.TOTAL:
321 return "Total Load Time";
322 case METRIC.REQUESTS:
323 return "# Requests";
324 case METRIC.CONNECTS:
325 return "# Connects";
326 case METRIC.READKB:
327 return "Read KB";
328 case METRIC.WRITEKB:
329 return "Write KB";
330 case METRIC.READKBPS:
331 return "Read KBps";
332 case METRIC.WRITEKBPS:
333 return "Write KBps";
334 default:
335 return "";
336 }
337 }
338
339 // Get the results with a specific row (data set) and column (metric).
340 function getSelectedResults(arr, rowIndex, colIndex) {
341 switch (colIndex) {
342 case METRIC.STARTLOAD:
343 return arr[rowIndex].startLoadResults;
344 case METRIC.COMMITLOAD:
345 return arr[rowIndex].commitLoadResults;
346 case METRIC.DOCLOAD:
347 return arr[rowIndex].docLoadResults;
348 case METRIC.PAINT:
349 return arr[rowIndex].paintResults;
350 case METRIC.TOTAL:
351 return arr[rowIndex].totalResults;
352 case METRIC.REQUESTS:
353 return arr[rowIndex].requests;
354 case METRIC.CONNECTS:
355 return arr[rowIndex].connects;
356 case METRIC.READKB:
357 return arr[rowIndex].KbytesRead;
358 case METRIC.WRITEKB:
359 return arr[rowIndex].KbytesWritten;
360 case METRIC.READKBPS:
361 return arr[rowIndex].readbpsResults;
362 case METRIC.WRITEKBPS:
363 return arr[rowIndex].writebpsResults;
364 default:
365 return undefined;
366 }
367 }
368
369 // Ensure only two data sets (rows) are selected.
370 function checkAmount(arr) {
371 var amount = 0;
372 for (var i = 0; i < arr.length; i++) {
373 if (arr[i].checked) {
374 amount++;
375 }
376 }
377 return amount;
378 }
379
380 // Get the index of selected row or column.
381 function getSelectedIndex(arr) {
382 var selectedArr = new Array();
383 for (var i = 0; i < arr.length; i++) {
384 if(arr[i].checked) {
385 selectedArr.push(i);
386 }
387 }
388 return selectedArr;
389 }
390
391 // Repaint or hide the chart.
392 function updateChart(caller) {
393 var placeholder = document.getElementById("placeholder");
394 if (caller.type == "radio") {
395 // Other radio button is clicked.
396 if (placeholder.style.display == "") {
397 compare();
398 }
399 } else {
400 // Other checkbox or clearing results is clicked.
401 if (placeholder.style.display == "") {
402 placeholder.style.display = "none";
403 }
404 }
405 }
406
407 // Clear indicators besides checkbox.
408 function clearIndicator() {
409 var checkboxArr = document.getElementsByName("checkboxArr");
410 for (var i = 0; i < checkboxArr.length; i++) {
411 checkboxArr[i].parentElement.firstChild.data = "";
412 }
413 }
414
415 // Enable/Disable buttons according to checkbox change.
416 function checkSelected() {
417 var checkboxArr = document.getElementsByName("checkboxArr");
418 if (checkAmount(checkboxArr) !=0) {
419 document.getElementById("clearSelected").disabled = false;
420 document.getElementById("compare").disabled = false;
421 } else {
422 document.getElementById("clearSelected").disabled = true;
423 document.getElementById("compare").disabled = true;
424 }
425 }
426
427 // Object to summarize everything
428 var totals = {};
429
430 // Compute the results for a data set.
431 function computeDisplayResults(data) {
432 var count = data.data.length;
433 for (var i = 0; i < count; i++) {
434 var obj = data.data[i];
435 obj.displayTime = setDisplayTime(obj.timestamp);
436 var resultList = obj.totalResults;
437 obj.mean = Array.avg(resultList);
438 obj.stddev = Array.stddev(resultList);
439 obj.stderr = obj.stddev / Math.sqrt(obj.iterations);
440 var ci = 1.96 * obj.stderr;
441 obj.cihigh = obj.mean + ci;
442 obj.cilow = obj.mean - ci;
443 obj.min = Array.min(resultList);
444 obj.max = Array.max(resultList);
445 obj.readbps = Array.avg(obj.readbpsResults);
446 obj.writebps = Array.avg(obj.writebpsResults);
447 obj.readKB = Array.avg(obj.KbytesRead);
448 obj.writeKB = Array.avg(obj.KbytesWritten);
449 obj.paintMean = Array.avg(obj.paintResults);
450 obj.startLoadMean = Array.avg(obj.startLoadResults);
451 obj.commitLoadMean = Array.avg(obj.commitLoadResults);
452 obj.docLoadMean = Array.avg(obj.docLoadResults);
453
454 obj.displayRequests = Array.avg(obj.requests);
455 obj.displayConnects = Array.avg(obj.connects);
456 obj.displaySpdySessions = Array.avg(obj.spdySessions);
457
458 obj.displayDomNum = obj.domNum;
459 obj.displayMaxDepth = obj.maxDepth;
460 obj.displayMinDepth = obj.minDepth;
461 obj.displayAvgDepth = obj.avgDepth;
462 }
463 return count;
464 }
465
466 // Convert timestamp to readable string.
467 function setDisplayTime(ts) {
468 var year = ts.getFullYear();
469 var mon = ts.getMonth()+1;
470 var date = ts.getDate();
471 var hrs = ts.getHours();
472 var mins = ts.getMinutes();
473 var secs = ts.getSeconds();
474
475 mon = ( mon < 10 ? "0" : "" ) + mon;
476 date = ( date < 10 ? "0" : "" ) + date;
477 mins = ( mins < 10 ? "0" : "" ) + mins;
478 secs = ( secs < 10 ? "0" : "" ) + secs;
479
480 return (year + "/" + mon + "/" + date + " " + hrs + ":" + mins + ":" + secs);
481 }
482
483 // Subtract the results from two data sets.
484 // This function could be smarter about what it subtracts,
485 // for now it just subtracts everything.
486 // Returns true if it was able to compare the two data sets.
487 function subtractData(data, baseline) {
488 var count = data.data.length;
489 if (baseline.data.length != count) {
490 return false;
491 }
492 for (var i = 0; i < count; i++) {
493 var obj = data.data[i];
494 var obj2 = baseline.data[i];
495
496 // The data sets are different.
497 if (obj.url != obj2.url ||
498 obj.iterations != obj2.iterations) {
499 return false;
500 }
501
502 obj.mean -= obj2.mean;
503 obj.stddev -= obj2.stddev;
504 obj.min -= obj2.min;
505 obj.max -= obj2.max;
506 obj.readbps -= obj2.readbps;
507 obj.writebps -= obj2.writebps;
508 obj.readKB -= obj2.readKB;
509 obj.writeKB -= obj2.writeKB;
510 obj.paintMean -= obj2.paintMean;
511 obj.startLoadMean -= obj2.startLoadMean;
512 obj.commitLoadMean -= obj2.commitLoadMean;
513 obj.docLoadMean -= obj2.docLoadMean;
514
515 obj.displayRequests -= obj2.displayRequests;
516 obj.displayConnects -= obj2.displayConnects;
517 obj.displaySpdySessions -= obj2.displaySpdySessions;
518 }
519 return true;
520 }
521
522 // Compute totals based on a data set.
523 function computeTotals(data) {
524 var count = data.data.length;
525 for (var i = 0; i < count; i++) {
526 var obj = data.data[i];
527 totals.mean += obj.mean;
528 totals.paintMean += obj.paintMean;
529 totals.startLoadMean += obj.startLoadMean;
530 totals.commitLoadMean += obj.commitLoadMean;
531 totals.docLoadMean += obj.docLoadMean;
532 }
533 }
534
535 // Compute results for the data with an optional baseline.
536 // If |baseline| is undefined, will compute the results of this
537 // run. Otherwise, computes the diff between this data and the baseline.
538 function computeResults(data, baseline) {
539 totals = {};
540 totals.mean = 0;
541 totals.paintMean = 0;
542 totals.startLoadMean = 0;
543 totals.commitLoadMean = 0;
544 totals.docLoadMean = 0;
545
546 var count = computeDisplayResults(data);
547
548 if (baseline) {
549 computeDisplayResults(baseline);
550 if (!subtractData(data, baseline)) {
551 alert("These data sets are different");
552 document.getElementById("baseline").value = "";
553 return;
554 }
555 }
556
557 computeTotals(data);
558 totals.url = "(" + count + " urls)";
559 if (count > 0) {
560 totals.mean /= count;
561 totals.paintMean /= count;
562 totals.startLoadMean /= count;
563 totals.commitLoadMean /= count;
564 totals.docLoadMean /= count;
565 }
566
567 // Find the biggest average for our bar graph.
568 max_sample = 0;
569 for (var i = 0; i < data.data.length; i++) {
570 if (data.data[i].max > max_sample) {
571 max_sample = data.data[i].mean;
572 }
573 }
574 }
575
576 function jsinit() {
577 var extension = chrome.extension.getBackgroundPage();
578
579 // Run the template to show results
580 var data = extension.results;
581
582 // Get the baseline results
583 var elt = document.getElementById("baseline");
584 var baseline_json = document.getElementById("baseline").value;
585 var baseline;
586 if (baseline_json) {
587 try {
588 baseline = JSON.parse(baseline_json);
589 } catch (e) {
590 alert("JSON parse error: " + e);
591 }
592 }
593
594 // Compute
595 computeResults(data, baseline);
596
597 var context = new JsEvalContext(data);
598 context.setVariable('$width', 0);
599 context.setVariable('$samples', 0);
600 var template = document.getElementById("t");
601 jstProcess(context, template);
602
603 // Set the options
604 document.getElementById("iterations").value = extension.iterations;
605 document.getElementById("clearconns").checked = extension.clearConnections;
606 document.getElementById("clearcache").checked = extension.clearCache;
607 document.getElementById("enablespdy").checked = extension.enableSpdy;
608 setUrl(extension.testUrl);
609
610 if (!baseline) {
611 var json_data = JSON.stringify(data);
612 document.getElementById("json").value = json_data;
613 }
614
615 // Activate loading Urls from local file.
616 document.getElementById('files').addEventListener('change',
617 handleFileSelect, false);
618 }
619
620 function getWidth(mean, obj) {
621 var kMinWidth = 200;
622 var max_width = obj.offsetWidth;
623 if (max_width < kMinWidth) {
624 max_width = kMinWidth;
625 }
626 return Math.floor(max_width * (mean / max_sample));
627 }
628
629 // Apply configuration back to our extension
630 function config() {
631 var extension = chrome.extension.getBackgroundPage();
632 var iterations = parseInt(document.getElementById("iterations").value);
633 var clearConnections = document.getElementById("clearconns").checked;
634 var clearCache = document.getElementById("clearcache").checked;
635 var enableSpdy = document.getElementById("enablespdy").checked;
636 if (iterations > 0) {
637 extension.iterations = iterations;
638 extension.clearConnections = clearConnections;
639 extension.clearCache = clearCache;
640 extension.enableSpdy = enableSpdy;
641 }
642 }
643
644 // Set the url in the benchmark url box.
645 function setUrl(url) {
646 document.getElementById("testurl").value = url;
647 }
648
649 // Start the benchmark.
650 function run() {
651 if (!chrome.benchmarking) {
652 alert("Warning: Looks like you forgot to run chrome with " +
653 " --enable-benchmarking set.");
654 return;
655 }
656 var extension = chrome.extension.getBackgroundPage();
657 var testUrl = document.getElementById("testurl").value;
658 extension.testUrl = testUrl;
659 extension.run();
660 }
661
662 function showConfirm() {
663 var r = confirm("Are you sure to clear results?");
664 if (r) {
665 // Find out the event source element.
666 var evtSrc = window.event.srcElement;
667 if (evtSrc.value == "Clear Selected") {
668 clearSelected();
669 } else if (evtSrc.value == "Clear All") {
670 clearResults();
671 }
672 }
673 }
674
675 // Clear the selected results
676 function clearSelected() {
677 var extension = chrome.extension.getBackgroundPage();
678 var checkboxArr = document.getElementsByName("checkboxArr");
679 var rowIndexArr = getSelectedIndex(checkboxArr);
680 var currIndex;
681 for (var i = 0; i < rowIndexArr.length; i++) {
682 currIndex = rowIndexArr[i];
683 // Update the index of the original row in the modified array.
684 currIndex -= i;
685 extension.results.data.splice(currIndex, 1);
686 document.location.reload(true);
687 updateChart(this);
688 jsinit();
689 }
690 }
691
692 // Clear all the results
693 function clearResults() {
694 var extension = chrome.extension.getBackgroundPage();
695 extension.results = {};
696 extension.results.data = new Array();
697 document.getElementById("json").value = "";
698 document.getElementById("baseline").value = "";
699 updateChart(this);
700 jsinit();
701 }
702
703 // Export html table into CSV format.
704 function exportHtml() {
705 var checkboxArr = document.getElementsByName("checkboxArr");
706 var rowNum = checkboxArr.length + 1; // # of data rows plus total-stats row.
707 $('#t').table2CSV(rowNum);
708 }
709
710 // Toggle display of an element
711 function toggle(id) {
712 var elt = document.getElementById(id);
713 if (elt.style.display == "none") {
714 elt.style.display = "block";
715 } else {
716 elt.style.display = "none";
717 }
718 }
719
720 document.addEventListener("DOMContentLoaded", function() {
721 jsinit();
722 restoreTable();
723
724 document.querySelector('form').addEventListener('click', function() {
725 config();
726 run();
727 });
728 $('#expand')[0].addEventListener('click', function() { expand(); });
729 $('#clearSelected')[0].addEventListener('click',
730 function() { showConfirm(); });
731 $('#clearAll')[0].addEventListener('click', function() { showConfirm(); });
732 $('#exportCsv')[0].addEventListener('click', function() { exportHtml(); });
733 var checkboxArrs = document.getElementsByName('checkboxArr');
734 for (var i = 0; i < checkboxArrs.length; ++i) {
735 checkboxArrs[i].addEventListener('click', function() {
736 updateChart(this);
737 clearIndicator();
738 checkSelected();
739 });
740 }
741 var radioArrs = document.getElementsByName('radioArr');
742 for (i = 0; i < radioArrs.length; ++i) {
743 radioArrs[i].addEventListener('click', function() { updateChart(this); });
744 }
745 $('#compare')[0].addEventListener('click', function() { compare(); });
746 $('#toggle-json')[0].addEventListener('click',
747 function() { toggle('json'); });
748 $('#toggle-baseline')[0].addEventListener('click',
749 function() { toggle('baseline'); });
750 $('#baseline')[0].addEventListener('change', function() { jsinit(); });
751 });
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698