forked from lishid/MarmoUI
-
Notifications
You must be signed in to change notification settings - Fork 0
/
marmo-ui.user.js
587 lines (531 loc) · 30.2 KB
/
marmo-ui.user.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
// __ __ _ _ _____
// | \/ | | | | |_ _|
// | \ / | __ _ _ __ _ __ ___ ___ | | | | | |
// | |\/| |/ _` | '__| '_ ` _ \ / _ \| | | | | |
// | | | | (_| | | | | | | | | (_) | |__| |_| |_
// |_| |_|\__,_|_| |_| |_| |_|\___/ \____/|_____|
//
// Created by Shida Li and Erica Xu
//
// Installation procedures:
// Chrome:
// Go to Wrench-Menu -> Tools -> Extensions
// Drag and drop "marmo-ui.user.js" into the extensions page
// Click on "Add" button
// Firefox:
// Download GreaseMonkey from
// https://addons.mozilla.org/en-US/firefox/addon/greasemonkey/
// Drag and drop "marmo-ui.user.js" into the browser
// Alternatively, open the js from userscript.org
// Wait and click on "Install" button
//
// ==UserScript==
// @name MarmoUI
// @description Marmoset Improved! Better UI and functionality
// @author Erica Xu (www.ericaxu.com) and Shida Li (www.lishid.com)
// @version 1.1
// @include https://marmoset.student.cs.uwaterloo.ca*
// ==/UserScript==
//
// Some functionalities are inspired by Marmoset Plus from http://userscripts.org/scripts/show/134262
//
//Variables here are volatile. They are not usable from within the page, but only within this script
var global_css = "body{font-family:'Droid Sans',helvetica,arial,sans-serif;color:#eee;background:#022d49;margin:0}h1{font-family:'Droid Sans',helvetica,arial,sans-serif;font-size:1.7em;font-weight:normal;margin:1em 0 .5em 7.5%}h2{font-family:'Droid Sans',helvetica,arial,sans-serif;font-size:1.5em;font-weight:normal;margin:1em 0 .5em 7.5%}h3{font-family:'Droid Sans',helvetica,arial,sans-serif;font-size:1.3em;font-weight:normal;margin:1em 0 .5em 7.5%;color:#eee}p{margin:1em 7.5%}a:link{color:#fc3;-webkit-transition:all .3s ease-in-out;-moz-transition:all .3s ease-in-out;-o-transition:all .3s ease-in-out;transition:all .3s ease-in-out}a:visited{color:#3e90c6}a:hover{color:#ff8700}div.header{background:#022d49;padding:4em 0 3em 0;margin:0;color:white;border:0}div.header p{text-align:center;font:4em 'Lobster',helvetica,sans-serif;padding:.3em;margin:0}div.breadcrumb{background:inherit;width:85%;margin:0 6% 0 7.5%;padding:0}div.breadcrumb p{background:inherit;font-family:'Droid Sans',helvetica,arial,sans-serif;font-variant:normal;width:80%;margin:0 6% 0 0;padding:.5em 0 0 0}div.logout,div.submit-button{background:#fc3;font-family:'Droid Sans',helvetica,arial,sans-serif;color:#03426a;width:7em;padding:.1em .5em;margin:0;text-align:center;font-weight:normal;-moz-border-radius:50px;-webkit-border-radius:50px;border-radius:50px;-ms-filter:progid:DXImageTransform.Microsoft.Alpha(Opacity = 91);filter:alpha(opacity = 91);-webkit-transition:all .3s ease-in-out;-moz-transition:all .3s ease-in-out;-o-transition:all .3s ease-in-out;transition:all .3s ease-in-out;cursor:pointer}div.logout p,div.submit-button p{font-size:1.5em;font-variant:normal;padding:0;margin:.1em auto}div.logout:hover,div.submit-button:hover{background:#eee;color:#03426a}div.logout a{font-family:inherit!important;font-weight:normal;color:#03426a!important;text-decoration:none!important}div.submit-button a{font-family:inherit;font-weight:normal;color:#111;text-decoration:none}div.submit-button{margin:1.5em 0 0 7.5%}div.breadcrumb p.nav{font-family:'Droid Sans',helvetica,arial,sans-serif;font-size:1.5em;font-variant:normal;font-weight:normal;display:inline-block;padding:0;margin:0}div.breadcrumb p a:link,div.breadcrumb p a:visited{color:#fc3;text-decoration:underline}div.breadcrumb p a:hover{color:#ff8700}div.footer{border-top:0;text-align:center;padding:.5em;margin:1em}div.footer a:visited{color:#fc3}div.footer a:hover{color:#ff8700}.notifier-update{background:#fc3;text-align:center}.notifier-text{line-height:3em;display:block}.notifier-update a,.notifier-update a:visited{color:#022d49;font-weight:bold}.notifier-close{position:absolute;top:0;right:.5em;font-size:2.0em;color:#000;text-decoration:none}ul.my-courses,ul.all-courses{margin:0 0 0 5%;list-style:none;font-size:1.1em}ul.my-courses li,ul.all-courses li{margin:.3em 0}ul.release-tokens{margin:0 0 0 5%;list-style:none}ul.release-tokens li{margin:0 0 0 2%}table{border-style:ridge;border:0;border-collapse:collapse;width:100%;margin:2em 0 0 0;font-size:1em}table.submissions,table.stacktrace{width:85%;margin:2em auto 0 auto}form[name='submitform']{background:#fc3;color:#111;width:45%;margin:2em auto 0 auto;padding:.5em;-webkit-border-radius:1em;-moz-border-radius:1em;border-radius:1em;font-size:1.2em;text-align:center}form[name='submitform'] p{text-align:center;font-weight:bold}form[name='submitform'] input[type='submit']{color:#eee;background:#022d49;height:2em;width:6em;-webkit-border-radius:1em;-moz-border-radius:1em;border-radius:1em;border:0;cursor:pointer;-webkit-transition:all .3s ease-in-out;-moz-transition:all .3s ease-in-out;-o-transition:all .3s ease-in-out;transition:all .3s ease-in-out}form[name='submitform'] input[type='submit']:hover{background:#25a0ca}div.submission-bg{background:#fff;opacity:.7;position:fixed;width:100%;height:100%;top:0;left:0}div.submission-popup{background-color:#fc3;color:#111;display:block;border:0;position:fixed;text-align:left;width:50%;left:25%;top:30%;padding:1.5em}div.submission-popup a:link,div.submission-popup a:visited{color:#022d49}div.submission-popup h2{text-align:center}div.submission-popup h2,div.submission-popup p{color:#111;margin:.5em 0 1em 0}div.submission-popup form{margin:1em auto}a#submission-close{margin:0;width:50%;display:inline-block;position:inherit;text-align:right;color:#111;text-decoration:underline}div.submission-popup div.submit-button{margin:.5em auto;background:#c1dbed}div.submission-popup div.submit-button a:link{color:#fc3;text-decoration:none}div.submission-popup div.submit-button p{margin:.1em auto}div.submission-popup div.submit-button:hover{background:#eee}table a:link{color:#03426a;font-weight:bold}table a:visited{color:#03426a}table a:hover{color:#ff8700}th{background:#2c6b94;color:#eee;font-size:1.1em;font-weight:normal;text-transform:capitalize!important;text-align:center;vertical-align:center;padding:1em .5em;border:0;margin:0}td{text-align:center;vertical-align:middle;padding:.5em;margin:0;border:0}th.description,td.description{text-align:center}td.left{text-align:left}td.long-result{text-align:left}th.number,td.number{text-align:right}col.right{border-right:0 solid black}div.build-output{margin:1em 7.5%;width:85%;background:#ffe799;color:#111;overflow-x:scroll}div.build-output pre{padding:1em 2em;letter-spacing:1px;font-family:monospace;white-space:pre;letter-spacing:1px}form{padding:0;margin:0}table.stacktrace td{padding-left:3em}input[type='file'],input[type='submit'],input[type='hidden']{font-family:'Droid Sans',helvetica,arial,sans-serif!important;font-size:1em}table.form td{padding:.25em;text-align:left}table.form td.label{font-weight:bold;text-align:right;background:#fff9e5;padding-left:3em;padding-right:.5em}table.form tr.submit td{background:#fc3;text-align:center}tr{color:#111;-webkit-transition:all .3s ease-in-out;-moz-transition:all .3s ease-in-out;-o-transition:all .3s ease-in-out;transition:all .3s ease-in-out}table tr:hover{background:#9ac5e1}tr.r0{background:#f5fbff}tr.r1{background:#e4f4fe}tr.selected,tr.selected:hover{background:#fc3}tr.highlight{background:#00ffaf}td.passed{background:#5fbf5f}td.failed{background:#9f3f3f}td.error{background:#c00}td.huh{background:#fc3}td.timeout{background:#f0f}td.not_implemented{background:#fff}td.could_not_run{background:#808080}td.warning{background:#0000df}table.codetable{border-style:none;border-width:0;border-collapse:collapse;margin:0}table.codetable td{text-align:left;vertical-align:baseline;padding:0;border:0;margin:0}table.codetable td.codecoveredcount{text-align:right;background:#abcabd;vertical-align:baseline;padding:0 2px;border:0;margin:0}table.codetable td.codeuncoveredcount{text-align:right;background:#f0c8c8;vertical-align:baseline;padding:0 2px;border:0;margin:0}table.codetable td.codeuncovered{text-align:left;background:#f0c8c8;vertical-align:baseline;padding:0 2px;border:0;margin:0}table.codetable td.linenumber{text-align:right;background:#fff;vertical-align:baseline;padding:0 2px;border:0;margin:0}.codehighlight{background:#fff3cc}.codekeyword{color:green;font-weight:bold}.codestring{color:fuchsia}.codeliteral{color:fuchsia}.codecomment{color:blue;font-style:italic}.statusmessage{border:1px solid #cedff2;background-color:#f5faff;color:#039;padding:7px}";
var global_fonts = "WebFontConfig = { google: { families: ['Droid+Sans::latin', 'Lobster::latin'] } };";
function loadMarmoUI(run)
{
//Utility functions
function getProtocol()
{
return "https:" == document.location.protocol ? "https" : "http";
}
function appendToHead(element)
{
document.getElementsByTagName("head")[0].appendChild(element);
}
function loadCSS()
{
var style = document.createElement("style");
style.type = "text/css";
if (style.styleSheet) style.styleSheet.cssText = global_css;
else style.appendChild(document.createTextNode(global_css));
appendToHead(style);
}
//Import fonts from google. Provided by Google Web Fonts
function loadFonts()
{
//Create a script to pass data to Google's script
var script = document.createElement("script");
script.type = "text/javascript";
script.textContent = global_fonts;
appendToHead(script);
//Load the Google's script asynchronously
var script = document.createElement("script");
script.type = "text/javascript";
script.src = getProtocol() + "://ajax.googleapis.com/ajax/libs/webfont/1/webfont.js";
script.async = "true";
appendToHead(script);
}
//Load jQuery from Google CDN
function loadJQuery(run)
{
//Don't load twice
if(typeof jquery != 'undefined' && jQuery)
{
var script = document.createElement("script");
script.type = "text/javascript";
script.textContent = "(" + run.toString() + ")()";
document.body.appendChild(script);
return;
}
//Load jQuery
var script = document.createElement("script");
script.type = "text/javascript";
script.src = getProtocol() + "://ajax.googleapis.com/ajax/libs/jquery/1.9.0/jquery.min.js";
script.addEventListener("load", function ()
{
var script = document.createElement("script");
script.type = "text/javascript";
script.textContent = "(" + run.toString() + ")()";
document.body.appendChild(script);
}, false);
appendToHead(script);
}
loadFonts();
loadCSS();
loadJQuery(run);
}
function runMarmoUI()
{
//Script-wise global variables that we can use here
var reload_time = 5; // Time to wait until reload, in seconds
var update_location = "https://raw.github.com/lishd/MarmoUI/master/updater.css"; //latest version inside a CSS
var update_download = "http://userscripts.org/scripts/source/157749.user.js"; //Download page
var current_version = "marmo_ui_1_1"; //Current version to check updates
//Add a jquery highlight function
jQuery.fn.highlight = function() {
$(this).each(function() {
var el = $(this);
$("<div/>")
.width(el.outerWidth())
.height(el.outerHeight())
.css({
"position": "absolute",
"left": el.offset().left,
"top": el.offset().top,
"background-color": "#ffff99",
"opacity": "1",
"z-index": "9999999"
}).appendTo('body').fadeOut(500).queue(function () { $(this).remove(); });
});};
//Utilities
var PAGE = {
LOGIN: {value: 0, link: "marmoset"},
COURSE_LIST: {value: 1, link: "view/index.jsp"},
PROBLEM_LIST: {value: 2, link: "view/course.jsp?coursePK="},
SUBMISSION_LIST: {value: 3, link: "view/project.jsp?projectPK="},
SUBMISSION_DETAILS: {value: 4, link: "view/submission.jsp?submissionPK="},
SUBMISSION_PAGE: {value: 5, link: "view/submitProject.jsp?projectPK="},
CONFIRM_RELEASE: {value: 6, link: "view/confirmReleaseRequest.jsp?submissionPK="},
ERROR: {value: 7, link: "action/SubmitProjectViaWeb"},
LOGIN_ERROR: {value: 8, link: "authenticate/PerformLogin"}};
function addTableHighlight()
{
//Add highlight to table rows
$("table tr").click(function ()
{
$(this).siblings().removeClass("selected");
$(this).addClass("selected");
});
}
//Load a page asynchronously and call "callback" when done
function asyncLoadPage(element, requestURL, callback, retry)
{
if(retry < 0) retry = 10;
if(retry == 0) return;
$.ajax({ url: requestURL, cache: false })
//Done then callback
.done(function(html){ callback(element, html, requestURL); })
//Failed then retry
.fail(function(){ asyncLoadPage(element, requestURL, callback, retry - 1); });
}
//Queue an asynchronous reload, should contain a <span class='update'></span> for updating the countdown
function queueAsyncReload(element, requestURL, callback, countdown)
{
element.find(".update").html(countdown);
if(countdown == 0)
{
asyncLoadPage(element, requestURL, callback, -1);
}
else
{
window.setTimeout(function() { queueAsyncReload(element, requestURL, callback, countdown - 1); }, 1000);
}
}
function applyChangesAll(current_page)
{
//Change page (browser) title
document.title = "MarmoUI - " + document.title;
//Change page title
$("p:contains('Marmoset Submission and Testing Server')").html("Marmoset");
//Add the favicon
$("head").append("<link href='data:image/x-icon;base64,AAABAAEAEBAAAAAAAABoBAAAFgAAACgAAAAQAAAAIAAAAAEAIAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAzzP9TM8z/gTPM/4EzzP/JM8z//zPM//8zzP/JM8z/gTPM/4EzzP9TAAAAAAAAAAAAAAAAAAAAAAAAAAAzzP9TM8z/qTPM//8zzP//M8z//zPM//8zzP//M8z//zPM//8zzP//M8z/qTPM/1MAAAAAAAAAAAAAAAAzzP9TM8z//zPM//8zzP//M8z//zPM//8zzP//M8z//zPM//8zzP//Q1VB/0ktAv9DVUH/M8z/UwAAAAAzzP9TM8z/qT58gP9JLQL/M8z//zPM//8+fID/SS0C/zPM//8zzP//Q1VB/0ktAv8+fID/SS0C/0NVQf8zzP9TM8z/gTPM//9JLQL/SS0C/zPM//8zzP//SS0C/0ktAv8zzP//M8z//0ktAv9JLQL/M8z//zPM//8+fID/M8z/gTPM/4EzzP//SS0C/0ktAv8zzP//M8z//0ktAv9JLQL/M8z//zPM//9JLQL/SS0C/zPM//8zzP//OKTA/zPM/8kzzP/JM8z//0ktAv9JLQL/M8z//zPM//9JLQL/SS0C/zPM//8zzP//SS0C/0ktAv8zzP//M8z//zPM//8zzP/JM8z//zPM//9JLQL/SS0C/zPM//8zzP//SS0C/0ktAv8zzP//M8z//0ktAv9JLQL/M8z//zPM//8zzP//M8z//zPM//8zzP//SS0C/0ktAv8zzP//M8z//0ktAv9JLQL/M8z//zPM//9JLQL/SS0C/zPM//8zzP//M8z//zPM//8zzP/JM8z//0ktAv9JLQL/M8z//zPM//9JLQL/SS0C/zPM//8zzP//SS0C/0ktAv8zzP//M6r//zPM//8zzP/JM8z/gUNVQf9JLQL/SS0C/z58gP84pMD/SS0C/0ktAv8+fID/OKTA/0ktAv9JLQL/M8z//zOF//8zzP//M8z/yTPM/4E+fID/SS0C/z58gP9DVUH/SS0C/0ktAv8+fID/Q1VB/0NVQf9JLQL/PnyA/zPM//8tLeD/M8z//zPM/4EzzP9TM8z/qTPM/9czzP//M8z//zPM//8zzP//M8z//zPM//8zzP//M8z//zPM//8zzP//LS3g/zPM/4EzzP+BAAAAADPM/1MzzP+0M8z//zPM//8zzP//M8z//zPM//8zzP//M6r//zOF//8tLeD/LS3g/y0t4P8tLeD/LS3g/wAAAAAAAAAAM8z/UzPM/6kzzP//M8z//zPM//8zzP//M8z//zPM//8zzP//M8z//zPM/4EtLeD/AAAAAAAAAAAAAAAAAAAAAAAAAAAzzP9TM8z/gTPM/4EzzP/JM8z//zPM//8zzP/JM8z/gTPM/4EzzP+BLS3g/wAAAAAAAAAA8A8AAOAHAADAAwAAgAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAMAAAADgAwAA8AMAAA==' rel='icon' type='image/x-icon'>");
//Add navigation CSS
var nav = $("div.breadcrumb p:not(:contains('Logout'))").addClass("nav");
$.each(nav.find("a"), function(index, value){$(value).text($.trim($(value).text()));});
var navText = nav.html();
if(typeof navText != "undefined" && current_page != PAGE.LOGIN.value)
{
navText = navText.substring(navText.indexOf(":") + 1);
navText = "<a href='/'>Marmoset</a> | " + navText;
navText = navText.replace(/\|/g, "›");
nav.html(navText);
}
//Capitalize the table header for consistency
$("th").css("text-transform", "capitalize");
//Remove inconsistent (and useless) greeting message
$("p:contains('Welcome')").remove();
//Remove current time
$(".footer").html("MarmoUI - Created by <a href='http://www.lishid.com'>Shida Li</a> and <a href='http://www.ericaxu.com'>Erica Xu</a>.");
//Redirect logout
$("div.logout a").attr("href", "/");
//Load the updater
$("head").append("<link href='" + update_location + "' type='text/css' rel='stylesheet'/>");
$("body").prepend("<div style='display:none;' class='notifier-update'>" +
"<a class='notifier-text' href='" + update_download + "'>Update available: <span class='notifier-text-inner'></span></a>" +
"<a class='notifier-close' href='#' onclick='$(\".notifier-update\").fadeOut().queue(function(){$(this).remove();}); return false;'>x</a></div>");
$("body").addClass(current_version);
//Google analytics helps for statistics
$("body").append("<script type='text/javascript'>var _gaq = _gaq || []; _gaq.push(['_setAccount', 'UA-38018139-1']); _gaq.push(['_trackPageview']);(function() { var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true; ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js'; var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s); })();</script>");
}
function applyChangesProblemsList()
{
//When async callbacks, decrypt the result from the page and integrate into the page
function loadSubmission(tableCell, requestResult, requestURL)
{
//Highlight the cell since we just updated it
tableCell.highlight();
//Get the page from the request
var page = $(requestResult.trim());
//Get the first line of submission
var firstLine = page.find("tr:eq(1)");
//No submission yet
if(firstLine.length == 0)
{
tableCell.html("No submission");
return;
}
//Find Link to the first submission and put an anchor linking to it
var link = firstLine.find("a:contains('view')").attr("href");
tableCell.html("<a href='" + link + "'></a>");
//Check if latest solution is untested
var untested = firstLine.find("td:contains('tested yet')");
//Check if latest solution failed to compile
var uncompiled = firstLine.find("td:contains('not compile')");
//If untested, show it as untested and queue an async reload
if(untested.length > 0)
{
tableCell.find("a").html("Not tested (reload in <span class='update'></span> s)");
queueAsyncReload(tableCell, requestURL, loadSubmission, reload_time);
}
//If failed to compile, show it as uncompiled and exits
else if(uncompiled.length > 0)
{
tableCell.find("a").html("Compilation failed");
return;
}
else
{
//Get the scores
var scores = firstLine.find("td:contains('/')");
var anchor = tableCell.find("a");
//Should match Public test and Release test
scores.each(function(index, item) {
//Match all int/int
var matches = $(item).html().match(/(\d+)\s\/\s(\d+)/);
//Put an & sign in between
if(anchor.html() != "") anchor.append(" & ");
anchor.append(matches[1] + " / " + matches[2]);
});
}
}
function loadTokensFromSubmission(tableCell, requestResult, requestURL)
{
//Get the page from the request
var page = $(requestResult.trim());
//Get the first line of submission
var firstLine = page.find("tr:not(:contains('not compile')):eq(1)");
//No submission yet
if(firstLine.length == 0)
{
tableCell.html("3 tokens");
}
else
{
//Find Link to the first submission and put an anchor linking to it
var link = firstLine.find("a:contains('view')").attr("href");
//async load the latest submission to find the tokens
asyncLoadPage(tableCell, link, loadTokens, -1);
}
}
//When async callbacks, decrypt the result from the page and integrate into the page
function loadTokens(tableCell, requestResult, requestURL)
{
//Highlight the cell since we just updated it
tableCell.highlight();
try
{
//Grab the token from the page
var tokens = requestResult.match(/You currently have \d+ release/)[0].match(/\d+/)[0];
//Show the tokens
tableCell.html(tokens + " tokens");
}
catch(error)
{
//Set to 3 tokens if we can't find the token string
tableCell.html("3 tokens");
}
//TODO Find the time for each token and try to parse the time
}
//Remove useless breadcrumb
$("h1").remove();
//Remove "Projects"
$("h2").remove();
//Change submit button
$("input[type='submit']").attr("value", "Submit");
//Change "web <br> submission" to something better
$("th:contains('web')").html("Submit Solution");
//Add the submission column
$("tr th:nth-child(2)").after("<th>Last submission</th>");
$("tr td:nth-child(2)").after("<td>Loading...</td>");
//Add the tokens column
$("tr th:nth-child(3)").after("<th>Tokens</th>");
$("tr td:nth-child(3)").after("<td>Loading...</td>");
//Load the tokens and submission results asychronously via ajax
$("tr").each(function(index, row){
if(index == 0) return;
var link = $(row).find("a:contains('view')").attr("href");
asyncLoadPage($(row).find("td:eq(2)"), link, loadSubmission, -1);
asyncLoadPage($(row).find("td:eq(3)"), link, loadTokensFromSubmission, -1);
});
//Add the click events for the submission popups
var submit = $("a:contains('submit')").click(function(event){
//Prevent redirection
event.preventDefault();
//Prevent closing
event.stopPropagation();
//The table row
var row = $(this.parentNode.parentNode);
//The project PK number
var projectPK = $(this).attr("href").match("projectPK=([0-9]+)")[1];
//Reset popup html
var popup = $(".submission-popup").html("");
//Add Close, Project, Submissions and Deadline
popup.append("<a id='submission-close' href='#' onclick='$(\"#submission-box\").hide();return false;'>Close</a>");
popup.append("<h2>Project: " + row.find("td:eq(0)").html() + " (" + row.find("td:eq(5)").html() + ")</h2>");
popup.append("<p>Submissions: <a href='" + row.find("td:eq(1) a").attr("href") + "'>view</a></p>");
popup.append("<p>Due: " + row.find("td:eq(4)").html() + "</p>");
//Add the submission form
popup.append("<form target='sumbission-loader' enctype='multipart/form-data' action='/action/SubmitProjectViaWeb' method='POST'>" +
"<input type='hidden' name='projectPK' value='" + projectPK + "'>" +
"<input type='hidden' name='submitClientTool' value='web'>" +
"<input type='file' name='file' size='20'></form>" +
"<div class='submit-button'><p><a onclick='$(\"form\").submit();'>Submit</a></p></div>");
//Fix the anchor having an extra space at the end
$("h2 a").each(function (index, row) {$(row).text($(row).text().trim());});
//Show the popup box
$("#submission-box").show();
});
//Add the submission box
$("body").append("<div id='submission-box'><div class='submission-bg'></div><div class='submission-wrapper'><div class='submission-cell'><div class='submission-popup'></div></div></div></div>");
$("#submission-box").hide();
//Event for closing the submission popup
$(".submission-bg").click(function(event){ $("#submission-box").hide(); });
$(document).keydown(function(e){ if(e.keyCode == 27){ $("#submission-box").hide(); }});
//Add the iframe for submission
$("body").append("<iframe id='sumbission-loader' name='sumbission-loader' style='display:none;'></iframe>");
$("#sumbission-loader").load(function(){ document.location.reload(true); });
//Add highlight to table rows
addTableHighlight();
}
function applyChangesSubmissionList()
{
//When async callbacks, refresh the page if can't find not tested yet
function checkReload(tableCell, requestResult, requestURL)
{
//Highlight the cell since we just updated it
tableCell.highlight();
//Get the page from the request
var page = $(requestResult.trim());
//Get the first line of submission
var linesWithUntested = page.find("tr:contains('tested yet')");
//Retry async load since there's still untested stuff
if(linesWithUntested.length > 0 || requestResult == "")
{
tableCell.html("Not tested (reload in <span class='update'></span> s)");
queueAsyncReload(tableCell, requestURL, checkReload, reload_time);
}
else
{
document.location.reload(true);
}
}
//Add CSS class
$("table").addClass("submissions");
var submitLink = $("h3").eq(0).html();
$("h3").eq(0).replaceWith("<div class='submit-button'><p>" + submitLink + "</p></div>");
//Remove useless header for project. It's already in breadcrumb anyways
$("h1").remove();
//Remove "Submissions"
$("h2").remove();
//Change "detailed <br> test results" to something better
$("th:contains('detailed')").html("Details");
//Check if there are any untested submissions
$("td:contains('tested yet')").each(function(index, cell){
checkReload($(cell), "", window.location);
});
//Add the click events for the submission popups
var submit = $("a:contains('Submit')").click(function(event){
//Prevent redirection
event.preventDefault();
//Prevent closing
event.stopPropagation();
//The project PK number
var projectPK = $(this).attr("href").match("projectPK=([0-9]+)")[1];
//Reset popup html
var popup = $(".submission-popup").html("");
//Add Close, Project, Submissions and Deadline
popup.append("<a id='submission-close' href='#' onclick='$(\"#submission-box\").hide();return false;'>Close</a>");
popup.append("<p>Due: " + $("p:contains('Deadline')").html().replace("<b>Deadline:</b>", "").trim() + "</p>");
//Add the submission form
popup.append("<form target='sumbission-loader' enctype='multipart/form-data' action='/action/SubmitProjectViaWeb' method='POST'>" +
"<input type='hidden' name='projectPK' value='" + projectPK + "'>" +
"<input type='hidden' name='submitClientTool' value='web'>" +
"<input type='file' name='file' size='20'></form>" +
"<div class='submit-button'><p><a onclick='$(\"form\").submit();'>Submit</a></p></div>");
//Show the popup box
$("#submission-box").show();
});
//Add the submission box
$("body").append("<div id='submission-box'><div class='submission-bg'></div><div class='submission-wrapper'><div class='submission-cell'><div class='submission-popup'></div></div></div></div>");
$("#submission-box").hide();
//Event for closing the submission popup
$(".submission-bg").click(function(event){ $("#submission-box").hide(); });
$(document).keydown(function(e){ if(e.keyCode == 27){ $("#submission-box").hide(); }});
//Add the iframe for submission
$("body").append("<iframe id='sumbission-loader' name='sumbission-loader' style='display:none;'></iframe>");
$("#sumbission-loader").load(function(){ document.location.reload(true); });
//Add highlight to table rows
addTableHighlight();
}
function applyChangesSubmissionPage()
{
//Add CSS class
$(".description").has("span").addClass("long-result");
//Remove useless header for project. It's already in breadcrumb anyways
$("h1").remove();
//Remove name and user
$("h2")[0].remove();
//Remove Test results
$("h2")[1].remove();
$("h3").eq(0).replaceWith("<p>Note: failed = wrong, error = crashed.</p>");
//Remove deadline
$("p:contains('Deadline')").remove();
$("th:contains('test')").text("Test");
//For those who failed the test, change the pre to a normal p
var pre = $("pre").eq(0).text();
$("pre").eq(0).replaceWith("<div class='build-output'><pre>" + pre + "</pre></div>");
//Add highlight to table rows
addTableHighlight();
//Release test
var releaseTestElement = $("h3").has("a").eq(0);
//Change the release test link to a button that actually release tests it with a popup confirm
if(releaseTestElement.length)
{
var link = releaseTestElement.find("a").attr("href");
var submissionPK = releaseTestElement.find("a").attr("href").match("submissionPK=([0-9]+)")[1];
releaseTestElement.replaceWith(
// <input type='submit' value='OK'>
"<form method='POST' action='/action/RequestReleaseTest'><div class='submit-button' style='width:10em'><p>" +
"<input type='hidden' name='submissionPK' value='" + submissionPK + "'>" +
"<a href='" + link + "' onclick='if(confirm(\"Are you sure you want to release test this?\")){$(\"form\").submit();} return false;'>" +
"Release Test" +
"</a></p><div></form>");
}
//Release tokens
$("ul").eq(0).addClass("release-tokens");
}
//Load page
var path = $(location).attr("href");
var current_page = PAGE.LOGIN.value; //Default is LOGIN page
//Check which page we're on
for(var page in PAGE)
{
if(path.indexOf(PAGE[page].link) >= 0)
{
current_page = PAGE[page].value;
}
}
//Universial pages changes
applyChangesAll(current_page);
//Page specific changes
switch(current_page)
{
case PAGE.LOGIN.value:
//Remove Logout button
$("div.logout").remove();
//Chang submit button
$("input[type='submit']").attr("value", "Use this account");
$("p:contains('please login as')").remove();
break;
case PAGE.COURSE_LIST.value:
//TODO: make this into a table?
//Add class to lists
$("ul").eq(0).addClass("my-courses");
//Remove the colon at the end of the links
$("ul a").each(function (index, row) {$(row).text($(row).text().replace(":", ""));});
break;
case PAGE.PROBLEM_LIST.value:
applyChangesProblemsList();
break;
case PAGE.SUBMISSION_LIST.value:
applyChangesSubmissionList();
break;
case PAGE.SUBMISSION_DETAILS.value:
applyChangesSubmissionPage();
break;
case PAGE.SUBMISSION_PAGE.value:
//Change the weirdly written title
$("h1").text("Web Submission");
//Replace the form with something better looking
$("table.form").eq(0).replaceWith("<p><input type='file' name='file' size='40'></p><p><input type='submit' value='Submit'></p>");
break;
case PAGE.CONFIRM_RELEASE.value:
//Completely bypass this page and clicks the button for the user (This page shouldn't occur anyways)
//There will be a confirmation popup in the previous page
$("body").append("<div style='position:fixed;left:0;top:0;height:100%;width:100%;background:#fff;z-index:99999;text-align:center;font-size:3em;color:#000;'>Please wait patiently while we submit this for you</div>");
$("input[type='submit']").click();
break;
case PAGE.ERROR.value:
//Change navigation for a go back button
$(".nav").html("<a href='#' onclick='history.back(); return false;'>Go back</a>");
//Remove the ugly image
$("p img").remove();
//Add something more constructive inside the title
$("h1").text("Oops, Marmoset has encountered an error!");
//jQuery for the hide/show effect
$("table tr th").click(function() {
$("table tr").has("td").toggle();
}).append(" (Click for details)").css("cursor", "pointer");
$("table tr").has("td").hide();
//Remove the logout button as it's completely useless
$(".logout").remove();
break;
case PAGE.LOGIN_ERROR.value:
//If we get to this page, then something is wrong
//First check if the page contains an error, if so, redirect back to homepage
if($("h3:contains('Apache Tomcat')").length > 0) window.location = "/";
break;
}
}
loadMarmoUI(runMarmoUI);