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
|
/**
* Copyright (c) 2016 Weitian LI <liweitianux@live.com>
* MIT license
*
* JavaScript codes for the Web UI of "fg21sim"
*/
"use strict";
/**
* jQuery settings
*/
jQuery.ajaxSetup({
error: function (error) {
console.error("AJAX request failed: code:", error.status,
", reason:", error.statusText); }
});
/**
* Common functions that will be used by other scripts
*/
/**
* Get the value of a key stored in the cookie
*
* @param {String} name - Name of the key
*
* @return {String} - The value of the key; `undefined` if the key not exists
*
* Credit:
* http://www.tornadoweb.org/en/stable/guide/security.html
*/
var getCookie = function (name) {
var m = document.cookie.match("\\b" + name + "=([^;]*)\\b");
return m ? m[1] : undefined;
};
/**
* jQuery extension for easier AJAX JSON post
*
* NOTE: The XSRF token is extracted from the cookie and posted together.
*
* @param {String} url - The URL that handles the AJAX requests
* @param {Object} data - Data of key-value pairs to be posted
* @param {Function} callback - Function to be called when AJAX succeeded
*/
jQuery.postJSON = function (url, data, callback) {
return jQuery.ajax({
url: url,
type: "POST",
contentType: "application/json; charset=utf-8",
// Tornado: `check_xsrf_cookie()`
// Credit: https://stackoverflow.com/a/28924601/4856091
headers: {"X-XSRFToken": getCookie("_xsrf")},
data: JSON.stringify(data),
success: function (response) {
if (callback) {
callback(response);
}
}
});
};
/**
* Scroll the page to adjust for the fixed navigation banner
*/
var scrollTarget = function (height) {
if ($(":target").length) {
var offset = $(":target").offset();
var scroll_to = offset.top - height * 1.2;
$("html, body").animate({scrollTop: scroll_to}, 100);
}
};
/**
* Toggle the display of the target block
*/
var toggleBlock = function (toggle, targetBlock) {
if (targetBlock.is(":visible")) {
targetBlock.slideUp("fast");
toggle.removeClass("fa-chevron-circle-up")
.addClass("fa-chevron-circle-down")
.attr("title", "Expand contents");
} else {
targetBlock.slideDown("fast");
toggle.removeClass("fa-chevron-circle-down")
.addClass("fa-chevron-circle-up")
.attr("title", "Collapse contents");
}
};
$(document).ready(function () {
// Scroll the page to adjust for the fixed navigation banner
$(window).on("hashchange", function () {
var nav_height = $("nav.navigation").outerHeight();
scrollTarget(nav_height);
});
// Toggle section contents/body
$(".heading > .toggle").on("click", function () {
var toggle = $(this);
var body = toggle.closest(".heading").next(".body");
toggleBlock(toggle, body);
});
// Panel toggle control
$(".panel-title > .toggle").on("click", function () {
var toggle = $(this);
var body = toggle.closest(".panel").find(".panel-body");
toggleBlock(toggle, body);
});
});
|