aboutsummaryrefslogtreecommitdiffstats
path: root/fg21sim/webui/static/js/main.js
blob: 7f5b582523bc7300d755bd5a455c66d544a2627c (plain)
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
/**
 * 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);
  }
};


$(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);
  });

  // Panel toggle control
  $(".panel-title > .toggle").on("click", function () {
    var toggle = $(this);
    var body = toggle.closest(".panel").find(".panel-body");
    if (body.is(":visible")) {
      body.slideUp("fast");
      toggle.removeClass("fa-chevron-circle-up")
        .addClass("fa-chevron-circle-down")
        .attr("title", "Expand contents");
    } else {
      body.slideDown("fast");
      toggle.removeClass("fa-chevron-circle-down")
        .addClass("fa-chevron-circle-up")
        .attr("title", "Collapse contents");
    }
  });
});