Initial commit
This commit is contained in:
56
client/SEAWebClient.html
Normal file
56
client/SEAWebClient.html
Normal file
@ -0,0 +1,56 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<link rel="shortcut icon" type="image/x-icon" href="/favicon.ico">
|
||||
<link rel="icon" type="image/png" href="/favicon192.png" sizes=192x192>
|
||||
<meta name="viewport"
|
||||
content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no" />
|
||||
<meta name="apple-mobile-web-app-capable" content="yes" />
|
||||
<meta name="apple-mobile-web-app-status-bar-style"
|
||||
content="black-translucent" />
|
||||
<title>SEAWebClient</title>
|
||||
<!-- CSS-Files -->
|
||||
<link rel="stylesheet" href="externalFiles/alertify.css">
|
||||
<link rel="stylesheet" href="externalFiles/swiper.min.css">
|
||||
<link rel="stylesheet" href="cssFiles/SEAWebClientSwiper.css">
|
||||
<link rel="stylesheet" href="cssFiles/SEAWebClientGroup.css">
|
||||
<link rel="stylesheet" href="cssFiles/SEAWebClientConsole.css">
|
||||
<link rel="stylesheet" href="cssFiles/SEAWebClientGraphics.css">
|
||||
<link rel="stylesheet" href="cssFiles/SEAWebClientMain.css">
|
||||
<!-- JS-Files -->
|
||||
<script src="externalFiles/alertify.js"></script>
|
||||
<script src="externalFiles/eventsource.js"></script>
|
||||
<script src="externalFiles/d3.min.js"></script>
|
||||
<script src="externalFiles/swiper.min.js"></script>
|
||||
<script src="externalFiles/Chart.bundle.min.js"></script>
|
||||
<script src="externalFiles/hammer.js"></script>
|
||||
<script src="externalFiles/chartjs-zoom.js"></script>
|
||||
<script src="jsFiles/SEAWebClientResponsivity.js"></script>
|
||||
<script src="jsFiles/SEAWebClientSwiper.js"></script>
|
||||
<script src="jsFiles/SEAWebClientGroup.js"></script>
|
||||
<script src="jsFiles/SEAWebClientConsole.js"></script>
|
||||
<script src="jsFiles/SEAWebClientGraph.js"></script>
|
||||
<script src="jsFiles/SEAWebClientCommunication.js"></script>
|
||||
<script src="jsFiles/SEAWebClientMain.js"></script>
|
||||
</head>
|
||||
|
||||
<body onresize="sizeChange()">
|
||||
<div class="loading-div">
|
||||
<span class="loading-span"><br><br>connecting ...</span>
|
||||
</div>
|
||||
<div id="main-panel-frame" onclick="toggleHeader()">
|
||||
<div id="main-panel">
|
||||
<span id="home-button">
|
||||
<svg class="interactive" id="home-icon" fill="#000000" height="16" viewBox="0 0 16 16" width="16">
|
||||
<path d="M8 1 L15 8 13.6 9.4 12.9 8.7 12.9 15 10.9 15 10.9 6.7 8 3.8 5.1 6.7 5.1 15 3.1 15 3.1 8.7 2.4 9.4 1 8 8 1z"/>
|
||||
<path d="M0 0h16v16H0z" fill="none"/>
|
||||
</svg>
|
||||
</span>
|
||||
<span id="header"></span>
|
||||
</div>
|
||||
</div>
|
||||
<div id="center"></div>
|
||||
</body>
|
||||
|
||||
</html>
|
89
client/SEAWebClientStart.html
Normal file
89
client/SEAWebClientStart.html
Normal file
@ -0,0 +1,89 @@
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
|
||||
<meta name="viewport"
|
||||
content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no" />
|
||||
<meta name="apple-mobile-web-app-capable" content="yes" />
|
||||
<meta name="apple-mobile-web-app-status-bar-style"
|
||||
content="black-translucent" />
|
||||
<title>SEAWebClient_SelectInstrument</title>
|
||||
<!-- CSS-Files -->
|
||||
<link rel="stylesheet" href="cssFiles/SEAWebClientStart.css">
|
||||
<!-- javascript-Files -->
|
||||
<script src="jsFiles/SEAWebClientStart.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div class="start-panel">
|
||||
<span class="start-text-wrapper">select instrument</span>
|
||||
</div>
|
||||
<div class="start-content">
|
||||
<div class="start-row-links start-link" tabindex = 0 onclick = followLink("http://samenv.psi.ch:8850/SEAWebClient.html")>DMC</div>
|
||||
<div class="start-row-links start-link" tabindex = 0 onclick = followLink("http://samenv.psi.ch:8851/SEAWebClient.html")>HRPT</div>
|
||||
<div class="start-row-links start-link" tabindex = 0 onclick = followLink("http://samenv.psi.ch:8852/SEAWebClient.html")>ZEBRA</div>
|
||||
<div class="start-row-links start-link" tabindex = 0 onclick = followLink("http://samenv.psi.ch:8853/SEAWebClient.html")>POLDI</div>
|
||||
<div class="start-row-links start-link" tabindex = 0 onclick = followLink("http://samenv.psi.ch:8854/SEAWebClient.html")>FOCUS</div>
|
||||
<div class="start-row-links start-link" tabindex = 0 onclick = followLink("http://samenv.psi.ch:8855/SEAWebClient.html")>TASP</div>
|
||||
<div class="start-row-links start-link" tabindex = 0 onclick = followLink("http://samenv.psi.ch:8856/SEAWebClient.html")>RITA2</div>
|
||||
<div class="start-row-links start-link" tabindex = 0 onclick = followLink("http://samenv.psi.ch:8857/SEAWebClient.html")>EIGER</div>
|
||||
<div class="start-row-links start-link" tabindex = 0 onclick = followLink("http://samenv.psi.ch:8858/SEAWebClient.html")>SANS 1</div>
|
||||
<div class="start-row-links start-link" tabindex = 0 onclick = followLink("http://samenv.psi.ch:8859/SEAWebClient.html")>SANS 2</div>
|
||||
<div class="start-row-links start-link" tabindex = 0 onclick = followLink("http://samenv.psi.ch:8860/SEAWebClient.html")>AMOR</div>
|
||||
<div class="start-row-links start-link" tabindex = 0 onclick = followLink("http://samenv.psi.ch:8861/SEAWebClient.html")>BOA</div>
|
||||
<div class="start-row-links start-link" tabindex = 0 onclick = followLink("http://samenv.psi.ch:8849/SEAWebClient.html")>PREP0</div>
|
||||
<div class="start-row-links start-link" tabindex = 0 onclick = followLink("http://samenv.psi.ch:8801/SEAWebClient.html")>PREP1</div>
|
||||
<div class="start-row-links start-link" tabindex = 0 onclick = followLink("http://samenv.psi.ch:8802/SEAWebClient.html")>PREP2</div>
|
||||
<div class="start-row-links start-link" tabindex = 0 onclick = followLink("http://samenv.psi.ch:8803/SEAWebClient.html")>PREP3</div>
|
||||
<div class="start-row-links start-link" tabindex = 0 onclick = followLink("http://samenv.psi.ch:8804/SEAWebClient.html")>PREP4</div>
|
||||
<div class="start-row-links start-link" tabindex = 0 onclick = followLink("http://samenv.psi.ch:8805/SEAWebClient.html")>PREP5</div>
|
||||
<div class="start-row-links start-link" tabindex = 0 onclick = followLink("http://samenv.psi.ch:8806/SEAWebClient.html")>PREP6</div>
|
||||
<div class="start-row-links start-link" tabindex = 0 onclick = followLink("http://samenv.psi.ch:8807/SEAWebClient.html")>PREP7</div>
|
||||
<div class="start-row-links start-link" tabindex = 0 onclick = followLink("http://samenv.psi.ch:8808/SEAWebClient.html")>PREP8</div>
|
||||
<div class="start-row-links start-link" tabindex = 0 onclick = followLink("http://samenv.psi.ch:8809/SEAWebClient.html")>PREP9</div>
|
||||
<div class="start-row-links start-link" tabindex = 0 onclick = followLink("http://samenv.psi.ch:8810/SEAWebClient.html")>LAB0</div>
|
||||
<div class="start-row-links start-link" tabindex = 0 onclick = followLink("http://samenv.psi.ch:8811/SEAWebClient.html")>LAB1</div>
|
||||
<div class="start-row-links start-link" tabindex = 0 onclick = followLink("http://samenv.psi.ch:8812/SEAWebClient.html")>LAB2</div>
|
||||
<div class="start-row-links start-link" tabindex = 0 onclick = followLink("http://samenv.psi.ch:8813/SEAWebClient.html")>LAB3</div>
|
||||
<div class="start-row-links start-link" tabindex = 0 onclick = followLink("http://samenv.psi.ch:8814/SEAWebClient.html")>LAB4</div>
|
||||
|
||||
<div class="start-settings">
|
||||
<div class = start-settings-label>
|
||||
<span>settings</span>
|
||||
<span class = "start-settings-show-hide" onclick = toggleSettings()>show</span>
|
||||
</div>
|
||||
<div class="start-settings-checkboxes">
|
||||
<div class="start-row start-row-checkboxes"> <span class="start-left">show graphics?
|
||||
</span> <span class="start-right"> <input id="check0" name = "sg"
|
||||
class="start-checkbox" type="checkbox"></input> <label for="check0"
|
||||
class="start-label"></label>
|
||||
</span> </div>
|
||||
<div class="start-row start-row-checkboxes"> <span class="start-left">show console?
|
||||
</span> <span class="start-right"> <input id="check1" name = "sc"
|
||||
class="start-checkbox" type="checkbox" checked></input> <label for="check1"
|
||||
class="start-label"></label>
|
||||
</span> </div>
|
||||
<div class="start-row start-row-checkboxes"> <span class="start-left">show overview?
|
||||
</span> <span class="start-right"> <input id="check2" name = "so"
|
||||
class="start-checkbox" type="checkbox" checked></input> <label for="check2"
|
||||
class="start-label"></label>
|
||||
</span> </div>
|
||||
<div class="start-row start-row-checkboxes"> <span class="start-left">show main?
|
||||
</span> <span class="start-right"> <input id="check3" name = "sm"
|
||||
class="start-checkbox" type="checkbox" checked></input> <label for="check3"
|
||||
class="start-label"></label>
|
||||
</span> </div>
|
||||
<div class="start-row start-row-checkboxes"> <span class="start-left">debug communication?
|
||||
</span> <span class="start-right"> <input id="check4" name = "dc"
|
||||
class="start-checkbox" type="checkbox"></input> <label for="check4"
|
||||
class="start-label"></label>
|
||||
</span> </div>
|
||||
<div class="start-row start-row-checkboxes"> <span class="start-left">debug graphics?
|
||||
</span> <span class="start-right"> <input id="check5" name = "dg"
|
||||
class="start-checkbox" type="checkbox"></input> <label for="check5"
|
||||
class="start-label"></label>
|
||||
</span> </div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
150
client/console.html
Normal file
150
client/console.html
Normal file
@ -0,0 +1,150 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link rel="icon" type="image/x-icon" href="favicon.ico">
|
||||
<style>
|
||||
.footer {
|
||||
background: #ccc;
|
||||
padding:5px;
|
||||
overflow: auto;
|
||||
height:30px;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="console" class=code>
|
||||
<br>
|
||||
<br>
|
||||
</div>
|
||||
<div class=footer>
|
||||
<form id="command_form" method="GET">
|
||||
<input type=input id=commandline size=80>
|
||||
</form>
|
||||
</div>
|
||||
<script type="text/javascript">
|
||||
|
||||
function getJSON(url, successHandler, errorHandler) {
|
||||
var xhr = typeof XMLHttpRequest != 'undefined'
|
||||
? new XMLHttpRequest()
|
||||
: new ActiveXObject('Microsoft.XMLHTTP');
|
||||
console.log("fired JSON request", url)
|
||||
xhr.open('get', url, true);
|
||||
xhr.onreadystatechange = function() {
|
||||
console.log(xhr)
|
||||
var status;
|
||||
var data;
|
||||
// https://xhr.spec.whatwg.org/#dom-xmlhttprequest-readystate
|
||||
if (xhr.readyState == 4) { // `DONE`
|
||||
status = xhr.status;
|
||||
if (status == 200) {
|
||||
data = JSON.parse(xhr.responseText);
|
||||
successHandler && successHandler(data);
|
||||
} else {
|
||||
errorHandler && errorHandler(status);
|
||||
}
|
||||
}
|
||||
};
|
||||
xhr.send();
|
||||
};
|
||||
|
||||
var historyElement = document.getElementById("console")
|
||||
// copy query
|
||||
var evtSrc = new EventSource("http://localhost:5000/update");
|
||||
|
||||
function htmlEscape(str) {
|
||||
return str
|
||||
.replace(/&/g, '&')
|
||||
.replace(/"/g, '"')
|
||||
.replace(/'/g, ''')
|
||||
.replace(/</g, '<')
|
||||
.replace(/>/g, '>');
|
||||
}
|
||||
|
||||
var our_id=""
|
||||
var oldtop = -1
|
||||
|
||||
evtSrc.onmessage = function(e) {
|
||||
var message = JSON.parse(e.data)
|
||||
console.log(message)
|
||||
if (message.type == "id") {
|
||||
our_id = message.id
|
||||
var test = "xxx"
|
||||
getJSON(
|
||||
"http://localhost:5000/console?id="+our_id,
|
||||
function(message) { console.log('msg', message, test); },
|
||||
function(status) { console.log('stat', status); }
|
||||
);
|
||||
} else if (message.type == 'command' || message.type == 'reply') {
|
||||
pre = ""
|
||||
post = ""
|
||||
if (message.type == 'command') {
|
||||
pre += "<font color='blue'><br>"
|
||||
post += "</font>"
|
||||
}
|
||||
if (message.origin == 'self') {
|
||||
pre += "<b>"
|
||||
post = "</b>" + post
|
||||
}
|
||||
historyElement.innerHTML += pre + htmlEscape(message.line) + post + "<br>\n"
|
||||
}
|
||||
/*
|
||||
var doc = document.documentElement
|
||||
var top = (window.pageYOffset || doc.scrollTop) - (doc.clientTop || 0)
|
||||
var h = window.innerHeight || window.clientHeight
|
||||
var d = document.body.scrollHeight
|
||||
*/
|
||||
window.scrollTo(0,document.body.scrollHeight)
|
||||
/*
|
||||
var top = (window.pageYOffset || doc.scrollTop) - (doc.clientTop || 0)
|
||||
var h = window.innerHeight
|
||||
var d = document.body.scrollHeight
|
||||
console.log(oldtop + oldh, top + h)
|
||||
*/
|
||||
};
|
||||
|
||||
evtSrc.onerror = function(e) {
|
||||
historyElement.innerHTML += "connection lost"
|
||||
evtSrc.close()
|
||||
};
|
||||
|
||||
function do_command() {
|
||||
celm = document.getElementById("commandline")
|
||||
cmd = encodeURI(celm.value);
|
||||
celm.value = ""
|
||||
oldtop = -1
|
||||
if (our_id != "") {
|
||||
cmd += "&id=" + our_id
|
||||
}
|
||||
console.log("http://localhost:5000/sendcommand?command="+cmd)
|
||||
getJSON(
|
||||
"http://localhost:5000/sendcommand?command="+cmd,
|
||||
function(message) { console.log('message', message); },
|
||||
function(status) { console.log('status', status); }
|
||||
);
|
||||
}
|
||||
|
||||
function handle_submit(evt) {
|
||||
evt.preventDefault()
|
||||
do_command()
|
||||
}
|
||||
|
||||
command_form = document.getElementById("command_form")
|
||||
if (command_form.addEventListener) {
|
||||
command_form.addEventListener("submit", handle_submit, true);
|
||||
} else {
|
||||
command_form.attachEvent('onsubmit', handle_submit);
|
||||
}
|
||||
|
||||
window.onbeforeunload = closingCode;
|
||||
function closingCode(){
|
||||
console.log("CLOSE")
|
||||
evtSrc.close()
|
||||
return null;
|
||||
}
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
38
client/cssFiles/SEAWebClientConsole.css
Normal file
38
client/cssFiles/SEAWebClientConsole.css
Normal file
@ -0,0 +1,38 @@
|
||||
@CHARSET "UTF-8";
|
||||
|
||||
/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% */
|
||||
/* CONSOLE */
|
||||
.commandline-wrapper {
|
||||
position: absolute;
|
||||
z-index: 1;
|
||||
width: 100%;
|
||||
padding: 26px 0px 0px 0px;
|
||||
background-color: darkgray;
|
||||
}
|
||||
|
||||
.commandline {
|
||||
font-family: monospace;
|
||||
font-size: 12px;
|
||||
width: 100%;
|
||||
text-align: left;
|
||||
padding-left: 8px;
|
||||
padding-top: 6px;
|
||||
padding-bottom: 6px;
|
||||
border: none;
|
||||
border-top: solid 8px dimgray;
|
||||
border-bottom: solid 5px dimgray;
|
||||
background-color: lightgray;
|
||||
color: black;
|
||||
}
|
||||
|
||||
.history {
|
||||
position: absolute;
|
||||
font-family: monospace;
|
||||
font-size: 12px;
|
||||
padding: 80px 8px 50px 8px;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow-y: auto;
|
||||
background-color: white;
|
||||
color: black;
|
||||
}
|
198
client/cssFiles/SEAWebClientGraphics.css
Normal file
198
client/cssFiles/SEAWebClientGraphics.css
Normal file
@ -0,0 +1,198 @@
|
||||
.swiper-pagination{
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.panel.graphics{
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
.panel.graphics span{
|
||||
margin: 0 1em;
|
||||
display: flex;
|
||||
user-select: none;
|
||||
-webkit-user-select: none;
|
||||
}
|
||||
|
||||
.panel.graphics div{
|
||||
margin-left: 1em;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
/*********************/
|
||||
.graphs-container{
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-flow: column;
|
||||
margin-top: 30px;
|
||||
}
|
||||
|
||||
.graph{
|
||||
height: 20%;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.graph-0 {
|
||||
height: 40%;
|
||||
}
|
||||
|
||||
.selection{
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow-x: hidden;
|
||||
height: 100%;
|
||||
/*align-items: center;*/
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.selection .select{
|
||||
margin: 0.2em;
|
||||
padding: 0.3em;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
border-bottom: 1px dashed black;
|
||||
}
|
||||
|
||||
.selection .select:last-of-type{
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.selection .select:hover{
|
||||
background-color: #eaeaea;
|
||||
}
|
||||
|
||||
.selection .select .title{
|
||||
font-weight: 900;
|
||||
}
|
||||
|
||||
.selection .params{
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.selection .param{
|
||||
white-space: nowrap;
|
||||
margin: 0 0.4em;
|
||||
}
|
||||
|
||||
.chart-container{
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
|
||||
.legend{
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex-wrap: wrap;
|
||||
position: absolute;
|
||||
background-color: rgb(255,255,255,0.8);
|
||||
color: #000000;
|
||||
padding: 0.3em;
|
||||
/*transition: left 0.5s, top 0.5s;*/
|
||||
top: 0px;
|
||||
left: 0px;
|
||||
user-select: none;
|
||||
-webkit-user-select: none;
|
||||
cursor: grab;
|
||||
border: 1px solid black;
|
||||
}
|
||||
|
||||
.legend:active{
|
||||
cursor: grabbing;
|
||||
}
|
||||
|
||||
body.black .legend{
|
||||
background-color: rgb(0,0,0,0.8);
|
||||
border: none;
|
||||
color: white;
|
||||
}
|
||||
|
||||
|
||||
.legend .controls{
|
||||
|
||||
}
|
||||
|
||||
.legend .control{
|
||||
cursor: pointer;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.legend .vcontrol{
|
||||
clear: both;
|
||||
float: left;
|
||||
border-bottom: 1px solid black;
|
||||
padding-bottom: 0.1em;
|
||||
padding-top: 0.1em;
|
||||
}
|
||||
|
||||
.legend .subcontrol{
|
||||
cursor: pointer;
|
||||
display: inline-block;
|
||||
padding-bottom: 0.1em;
|
||||
padding-top: 0.1em;
|
||||
color: #777777;
|
||||
}
|
||||
|
||||
.legend .subcontrol:hover{
|
||||
color: #000000;
|
||||
}
|
||||
|
||||
.legend .subspacer{
|
||||
display: inline-block;
|
||||
width: 0.2em;
|
||||
}
|
||||
|
||||
.legend .vcontrol:hover{
|
||||
color: #777777;
|
||||
}
|
||||
|
||||
.legend .control:last-of-type{
|
||||
border-bottom: none;
|
||||
padding-bottom: 0.3em;
|
||||
}
|
||||
|
||||
.legendel{
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
position: relative;
|
||||
|
||||
}
|
||||
|
||||
.legendel:hover{
|
||||
color: #777777;
|
||||
}
|
||||
|
||||
.legendel .color{
|
||||
width: 2em;
|
||||
height: 0.1em;
|
||||
margin-top: 0.45em;
|
||||
margin-right: 1em;
|
||||
}
|
||||
|
||||
.legendel .value{
|
||||
margin-left: 1em;
|
||||
}
|
||||
|
||||
.legendel.hidden .value{
|
||||
display: none;
|
||||
}
|
||||
|
||||
/*.legendel.hidden:before{
|
||||
content: '';
|
||||
width: 100%;
|
||||
height: 0.05em;
|
||||
top: 50%;
|
||||
margin-top: -0.025em;
|
||||
background-color: #FFF;
|
||||
position: absolute;
|
||||
}*/
|
||||
|
||||
.legendel.hidden{
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
.legendel.hidden .color{
|
||||
opacity: 0;
|
||||
}
|
178
client/cssFiles/SEAWebClientGroup.css
Normal file
178
client/cssFiles/SEAWebClientGroup.css
Normal file
@ -0,0 +1,178 @@
|
||||
/* GROUP */
|
||||
@CHARSET "UTF-8";
|
||||
|
||||
/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% */
|
||||
/* CONTENT */
|
||||
.content {
|
||||
padding: 60px 20px 20px 20px;
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.content-console {
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow-y: hidden;
|
||||
}
|
||||
|
||||
.link {
|
||||
transition: 0.4s;
|
||||
cursor: pointer;
|
||||
color: steelblue;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.link:focus {
|
||||
color: orangered;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.row {
|
||||
padding: 4px 0px 4px 0px;
|
||||
width: 100%;
|
||||
min-height: 24px;
|
||||
display: block;
|
||||
border-bottom: dotted darkgray 2px;
|
||||
overflow: hidden;
|
||||
transition: 0.2s;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.clickable:hover {
|
||||
background-color: lightgray;
|
||||
}
|
||||
|
||||
.link-static {
|
||||
padding-left: 4px;
|
||||
background-color: #303030;
|
||||
color: white;
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.info-box {
|
||||
margin: 4px 0px 4px 0px;
|
||||
padding: 4px;
|
||||
border-radius: 4px;
|
||||
background-color: darkslategray;
|
||||
color: white;
|
||||
display: none;
|
||||
width: 100%;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.col-left {
|
||||
min-height: 24px;
|
||||
line-height: 24px;
|
||||
float: left;
|
||||
}
|
||||
|
||||
.event-toggle-info {
|
||||
color: darkslategray;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.col-right {
|
||||
float: right;
|
||||
}
|
||||
|
||||
/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% */
|
||||
/* TEXT */
|
||||
.input-text {
|
||||
height: 24px;
|
||||
font-family: monospace;
|
||||
background-color: lightgray;
|
||||
border: solid 2px dimgray;
|
||||
color: black;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
::-ms-clear { /* remove the x in the input box on IE */
|
||||
width : 0;
|
||||
height: 0;
|
||||
}
|
||||
/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% */
|
||||
/* CHECKBOX */
|
||||
.parameter-checkbox {
|
||||
opacity: 0;
|
||||
float: left;
|
||||
}
|
||||
|
||||
.parameter-checkbox + .parameter-label {
|
||||
position: relative;
|
||||
cursor: pointer;
|
||||
float: left;
|
||||
}
|
||||
|
||||
.parameter-checkbox:focus+.parameter-label {
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
.parameter-checkbox+.parameter-label::before {
|
||||
content: ' ';
|
||||
position: absolute;
|
||||
left: -24px;
|
||||
top: -2px;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
display: block;
|
||||
background: lightgray;
|
||||
border: 2px solid dimgray;
|
||||
}
|
||||
|
||||
.parameter-checkbox+.parameter-label::after {
|
||||
content: ' ';
|
||||
position: absolute;
|
||||
left: -19px;
|
||||
top: 3px;
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
display: block;
|
||||
z-index: 1;
|
||||
background-color: dimgray;
|
||||
-ms-transition: all .2s ease;
|
||||
-webkit-transition: all .2s ease;
|
||||
transition: all .3s ease;
|
||||
-ms-transform: scale(0);
|
||||
-webkit-transform: scale(0);
|
||||
transform: scale(0);
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.parameter-checkbox:checked+.parameter-label::after {
|
||||
-ms-transform: scale(1);
|
||||
-webkit-transform: scale(1);
|
||||
transform: scale(1);
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% */
|
||||
/* RADIO */
|
||||
option {
|
||||
height: 24px;
|
||||
background-color: dimgray;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.select-params {
|
||||
height: 24px;
|
||||
border: none;
|
||||
background-color: dimgray;
|
||||
color: white;
|
||||
width: auto;
|
||||
min-width: 120px;
|
||||
}
|
||||
|
||||
.select-params:focus {
|
||||
opacity: 0.85;
|
||||
}
|
||||
|
||||
/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% */
|
||||
/* PUSH-BUTTON */
|
||||
|
||||
.push-button {
|
||||
border: 2px solid dimgray;
|
||||
border-radius: 4px;
|
||||
}
|
128
client/cssFiles/SEAWebClientMain.css
Normal file
128
client/cssFiles/SEAWebClientMain.css
Normal file
@ -0,0 +1,128 @@
|
||||
@CHARSET "UTF-8";
|
||||
|
||||
* {
|
||||
box-sizing: border-box; /* include margin into width and height calculation */
|
||||
}
|
||||
|
||||
|
||||
|
||||
meta, body {
|
||||
font-family: sans-serif;
|
||||
font-size: 16px;
|
||||
/* the following is about the ability to select text */
|
||||
/*-webkit-touch-callout: none;
|
||||
-webkit-user-select: none;
|
||||
-khtml-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;*/
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.loading-div {
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
background: #303030;
|
||||
z-index: 100;
|
||||
text-align: center;
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
||||
|
||||
.loading-span {
|
||||
height: 100vh;
|
||||
line-height: 36px;
|
||||
color: white;
|
||||
font-size: 32px;
|
||||
}
|
||||
|
||||
|
||||
/* class for links and buttons */
|
||||
.interactive {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.interactive:hover {
|
||||
background-color: lightgray;
|
||||
fill: gray;
|
||||
color: gray;
|
||||
}
|
||||
|
||||
.interactive:active {
|
||||
fill: orangered;
|
||||
color: orangered;
|
||||
}
|
||||
|
||||
/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% */
|
||||
/* HEADER (was main title bar) */
|
||||
#main-panel-frame {
|
||||
height: 30px;
|
||||
z-index: 50;
|
||||
top: 4px;
|
||||
left: 4px;
|
||||
position: fixed;
|
||||
border: solid 2px #303030;
|
||||
background-color: dimgray;
|
||||
border-bottom-right-radius: 12px;
|
||||
padding: 1px 9px 1px 9px;
|
||||
}
|
||||
|
||||
#main-panel {
|
||||
display: inline;
|
||||
cursor: pointer;
|
||||
/* position: fixed; */
|
||||
width: auto;
|
||||
height: 30px;
|
||||
vertical-align: top;
|
||||
line-height: 24px;
|
||||
}
|
||||
#header {
|
||||
display: inline;
|
||||
font-size: 16px;
|
||||
color: white;
|
||||
/* display: inline; */
|
||||
cursor: pointer;
|
||||
/* position: fixed; */
|
||||
width: auto;
|
||||
transition: 0.6s;
|
||||
padding: 0px 0px 0px 6px;
|
||||
}
|
||||
|
||||
#home-button {
|
||||
display: inline;
|
||||
cursor: pointer;
|
||||
height: 16px;
|
||||
}
|
||||
|
||||
#home-icon {
|
||||
display: inline;
|
||||
transition: 0.4s;
|
||||
cursor: pointer;
|
||||
/*float: right;*/
|
||||
fill: white;
|
||||
height: 24px;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% */
|
||||
/* CENTER */
|
||||
#center {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.grid-element {
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
display: none;
|
||||
overflow: hidden;
|
||||
border: solid 4px dimgray;
|
||||
}
|
190
client/cssFiles/SEAWebClientStart.css
Normal file
190
client/cssFiles/SEAWebClientStart.css
Normal file
@ -0,0 +1,190 @@
|
||||
@CHARSET "UTF-8";
|
||||
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
-webkit-touch-callout: none;
|
||||
-webkit-user-select: none;
|
||||
-khtml-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
meta, body {
|
||||
font-family: sans-serif;
|
||||
font-size: 16px;
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% */
|
||||
/* PANEL */
|
||||
.start-panel {
|
||||
position: fixed;
|
||||
top: 0px;
|
||||
left: 0px;
|
||||
z-index: 1;
|
||||
color: white;
|
||||
background: #303030;
|
||||
width: 100%;
|
||||
height: 30px;
|
||||
line-height: 30px;
|
||||
padding-left: 30px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.start-text-wrapper {
|
||||
height: 30px;
|
||||
}
|
||||
|
||||
/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% */
|
||||
/* CONTENT */
|
||||
.start-content {
|
||||
padding: 60px 40px 30px 40px;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.start-row-links {
|
||||
padding: 4px 0px 4px 0px;
|
||||
width: 100%;
|
||||
min-height: 24px;
|
||||
display: block;
|
||||
border-bottom: dotted darkgray 2px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
/* %%%%%%%%%% links %%%%%%%%%%*/
|
||||
.start-link {
|
||||
transition: 0.4s;
|
||||
cursor: pointer;
|
||||
color: steelblue;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.start-link:focus {
|
||||
color: orangered;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.start-link:hover {
|
||||
color: gray;
|
||||
}
|
||||
|
||||
.start-link:active {
|
||||
color: orangered;
|
||||
}
|
||||
|
||||
/* %%%%%%%%%% settings %%%%%%%%%%*/
|
||||
.start-settings {
|
||||
color: white;
|
||||
background: #303030;
|
||||
margin-top: 30px;
|
||||
padding: 10px 20px 10px 20px;
|
||||
border-radius: 6px;
|
||||
}
|
||||
|
||||
.start-settings-label {
|
||||
border-bottom: solid darkgray 2px;
|
||||
}
|
||||
|
||||
.start-settings-show-hide {
|
||||
float: right;
|
||||
color: lightgray;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.start-settings-show-hide:focus {
|
||||
color: orangered;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.start-settings-show-hide:hover {
|
||||
color: gray;
|
||||
}
|
||||
|
||||
.start-settings-show-hide:active {
|
||||
color: orangered;
|
||||
}
|
||||
|
||||
.start-settings-checkboxes {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.start-row-checkboxes {
|
||||
border-bottom: dotted darkgray 2px;
|
||||
height: 28px;
|
||||
padding-left: 4px;
|
||||
padding-right: 2px;
|
||||
}
|
||||
|
||||
.start-left {
|
||||
min-height: 24px;
|
||||
line-height: 24px;
|
||||
float: left;
|
||||
}
|
||||
|
||||
.start-right {
|
||||
min-height: 24px;
|
||||
line-height: 24px;
|
||||
float: right;
|
||||
}
|
||||
|
||||
/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% */
|
||||
/* CHECKBOX */
|
||||
.start-checkbox {
|
||||
opacity: 0;
|
||||
float: left;
|
||||
}
|
||||
|
||||
.start-checkbox + .start-label {
|
||||
position: relative;
|
||||
cursor: pointer;
|
||||
float: left;
|
||||
}
|
||||
|
||||
.start-checkbox:focus+.start-label {
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
.start-checkbox+.start-label::before {
|
||||
content: ' ';
|
||||
position: absolute;
|
||||
left: -24px;
|
||||
top: 2px;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
display: block;
|
||||
background: lightgray;
|
||||
border: 2px solid dimgray;
|
||||
}
|
||||
|
||||
.start-checkbox+.start-label::after {
|
||||
content: ' ';
|
||||
position: absolute;
|
||||
left: -19px;
|
||||
top: 7px;
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
display: block;
|
||||
z-index: 1;
|
||||
background-color: dimgray;
|
||||
-ms-transition: all .2s ease;
|
||||
-webkit-transition: all .2s ease;
|
||||
transition: all .3s ease;
|
||||
-ms-transform: scale(0);
|
||||
-webkit-transform: scale(0);
|
||||
transform: scale(0);
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.start-checkbox:checked+.start-label::after {
|
||||
-ms-transform: scale(1);
|
||||
-webkit-transform: scale(1);
|
||||
transform: scale(1);
|
||||
opacity: 1;
|
||||
}
|
41
client/cssFiles/SEAWebClientSwiper.css
Normal file
41
client/cssFiles/SEAWebClientSwiper.css
Normal file
@ -0,0 +1,41 @@
|
||||
@CHARSET "UTF-8";
|
||||
|
||||
.swiper-container-main {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.swiper-slide-main {
|
||||
background-color: white;
|
||||
overflow: hidden;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
padding-bottom: 30px;
|
||||
}
|
||||
|
||||
/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% */
|
||||
/* PANEL */
|
||||
.panel {
|
||||
text-align: center;
|
||||
background-color: #303030;
|
||||
color: white;
|
||||
padding: 6px 6px 6px 6px;
|
||||
position: absolute;
|
||||
z-index: 20;
|
||||
width: 100%;
|
||||
height: 30px;
|
||||
}
|
||||
|
||||
.slide-close-icon {
|
||||
transition: 0.4s;
|
||||
cursor: pointer;
|
||||
float: right;
|
||||
padding-right: 6px;
|
||||
height: 100%;
|
||||
fill: white;
|
||||
}
|
||||
|
||||
.toggle-updates-graphics {
|
||||
float: right;
|
||||
}
|
10
client/externalFiles/Chart.bundle.min.2.7.2.js
Normal file
10
client/externalFiles/Chart.bundle.min.2.7.2.js
Normal file
File diff suppressed because one or more lines are too long
7
client/externalFiles/Chart.bundle.min.2.8.4.js
Normal file
7
client/externalFiles/Chart.bundle.min.2.8.4.js
Normal file
File diff suppressed because one or more lines are too long
7
client/externalFiles/Chart.bundle.min.js
vendored
Normal file
7
client/externalFiles/Chart.bundle.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
20781
client/externalFiles/Chart.bundle.min.patched.js
Normal file
20781
client/externalFiles/Chart.bundle.min.patched.js
Normal file
File diff suppressed because it is too large
Load Diff
884
client/externalFiles/alertify.css
Normal file
884
client/externalFiles/alertify.css
Normal file
@ -0,0 +1,884 @@
|
||||
/**
|
||||
* alertifyjs 1.8.0 http://alertifyjs.com
|
||||
* AlertifyJS is a javascript framework for developing pretty browser dialogs and notifications.
|
||||
* Copyright 2016 Mohammad Younes <Mohammad@alertifyjs.com> (http://alertifyjs.com)
|
||||
* Licensed under GPL 3 <https://opensource.org/licenses/gpl-3.0>*/
|
||||
.alertify .ajs-dimmer {
|
||||
position: fixed;
|
||||
z-index: 1981;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
background-color: #252525;
|
||||
opacity: .5;
|
||||
}
|
||||
.alertify .ajs-modal {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
right: 0;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
padding: 0;
|
||||
overflow-y: auto;
|
||||
z-index: 1981;
|
||||
}
|
||||
.alertify .ajs-dialog {
|
||||
position: relative;
|
||||
margin: 5% auto;
|
||||
min-height: 110px;
|
||||
max-width: 500px;
|
||||
padding: 24px 24px 0 24px;
|
||||
outline: 0;
|
||||
background-color: #fff;
|
||||
}
|
||||
.alertify .ajs-dialog.ajs-capture:before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
display: block;
|
||||
z-index: 1;
|
||||
}
|
||||
.alertify .ajs-reset {
|
||||
position: absolute !important;
|
||||
display: inline !important;
|
||||
width: 0 !important;
|
||||
height: 0 !important;
|
||||
opacity: 0 !important;
|
||||
}
|
||||
.alertify .ajs-commands {
|
||||
position: absolute;
|
||||
right: 4px;
|
||||
margin: -14px 24px 0 0;
|
||||
z-index: 2;
|
||||
}
|
||||
.alertify .ajs-commands button {
|
||||
display: none;
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
margin-left: 10px;
|
||||
padding: 10px;
|
||||
border: 0;
|
||||
background-color: transparent;
|
||||
background-repeat: no-repeat;
|
||||
background-position: center;
|
||||
cursor: pointer;
|
||||
}
|
||||
.alertify .ajs-commands button.ajs-close {
|
||||
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAABZ0RVh0Q3JlYXRpb24gVGltZQAwNy8xMy8xNOrZqugAAAAcdEVYdFNvZnR3YXJlAEFkb2JlIEZpcmV3b3JrcyBDUzbovLKMAAAAh0lEQVQYlY2QsQ0EIQwEB9cBAR1CJUaI/gigDnwR6NBL/7/xWLNrZ2b8EwGotVpr7eOitWa1VjugiNB7R1UPrKrWe0dEAHBbXUqxMQbeewDmnHjvyTm7C3zDwAUd9c63YQdUVdu6EAJzzquz7HXvTiklt+H9DQFYaxFjvDqllFyMkbXWvfpXHjJrWFgdBq/hAAAAAElFTkSuQmCC);
|
||||
}
|
||||
.alertify .ajs-commands button.ajs-maximize {
|
||||
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAABZ0RVh0Q3JlYXRpb24gVGltZQAwNy8xMy8xNOrZqugAAAAcdEVYdFNvZnR3YXJlAEFkb2JlIEZpcmV3b3JrcyBDUzbovLKMAAAAOUlEQVQYlWP8//8/AzGAhYGBgaG4uBiv6t7eXkYmooxjYGAgWiELsvHYFMCcRX2rSXcjoSBiJDbAAeD+EGu+8BZcAAAAAElFTkSuQmCC);
|
||||
}
|
||||
.alertify .ajs-header {
|
||||
margin: -24px;
|
||||
margin-bottom: 0;
|
||||
padding: 16px 24px;
|
||||
background-color: #fff;
|
||||
}
|
||||
.alertify .ajs-body {
|
||||
min-height: 56px;
|
||||
}
|
||||
.alertify .ajs-body .ajs-content {
|
||||
padding: 16px 24px 16px 16px;
|
||||
}
|
||||
.alertify .ajs-footer {
|
||||
padding: 4px;
|
||||
margin-left: -24px;
|
||||
margin-right: -24px;
|
||||
min-height: 43px;
|
||||
background-color: #fff;
|
||||
}
|
||||
.alertify .ajs-footer .ajs-buttons.ajs-primary {
|
||||
text-align: right;
|
||||
}
|
||||
.alertify .ajs-footer .ajs-buttons.ajs-primary .ajs-button {
|
||||
margin: 4px;
|
||||
}
|
||||
.alertify .ajs-footer .ajs-buttons.ajs-auxiliary {
|
||||
float: left;
|
||||
clear: none;
|
||||
text-align: left;
|
||||
}
|
||||
.alertify .ajs-footer .ajs-buttons.ajs-auxiliary .ajs-button {
|
||||
margin: 4px;
|
||||
}
|
||||
.alertify .ajs-footer .ajs-buttons .ajs-button {
|
||||
min-width: 88px;
|
||||
min-height: 35px;
|
||||
}
|
||||
.alertify .ajs-handle {
|
||||
position: absolute;
|
||||
display: none;
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
z-index: 1;
|
||||
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAABZ0RVh0Q3JlYXRpb24gVGltZQAwNy8xMS8xNEDQYmMAAAAcdEVYdFNvZnR3YXJlAEFkb2JlIEZpcmV3b3JrcyBDUzbovLKMAAAAQ0lEQVQYlaXNMQoAIAxD0dT7H657l0KX3iJuUlBUNOsPPCGJm7VDp6ryeMxMuDsAQH7owW3pyn3RS26iKxERMLN3ugOaAkaL3sWVigAAAABJRU5ErkJggg==);
|
||||
-webkit-transform: scaleX(1) /*rtl:scaleX(-1)*/;
|
||||
transform: scaleX(1) /*rtl:scaleX(-1)*/;
|
||||
cursor: se-resize;
|
||||
}
|
||||
.alertify.ajs-no-overflow .ajs-body .ajs-content {
|
||||
overflow: hidden !important;
|
||||
}
|
||||
.alertify.ajs-no-padding.ajs-maximized .ajs-body .ajs-content {
|
||||
left: 0;
|
||||
right: 0;
|
||||
padding: 0;
|
||||
}
|
||||
.alertify.ajs-no-padding:not(.ajs-maximized) .ajs-body {
|
||||
margin-left: -24px;
|
||||
margin-right: -24px;
|
||||
}
|
||||
.alertify.ajs-no-padding:not(.ajs-maximized) .ajs-body .ajs-content {
|
||||
padding: 0;
|
||||
}
|
||||
.alertify.ajs-no-padding.ajs-resizable .ajs-body .ajs-content {
|
||||
left: 0;
|
||||
right: 0;
|
||||
}
|
||||
.alertify.ajs-maximizable .ajs-commands button.ajs-maximize,
|
||||
.alertify.ajs-maximizable .ajs-commands button.ajs-restore {
|
||||
display: inline-block;
|
||||
}
|
||||
.alertify.ajs-closable .ajs-commands button.ajs-close {
|
||||
display: inline-block;
|
||||
}
|
||||
.alertify.ajs-maximized .ajs-dialog {
|
||||
width: 100% !important;
|
||||
height: 100% !important;
|
||||
max-width: none !important;
|
||||
margin: 0 auto !important;
|
||||
top: 0 !important;
|
||||
left: 0 !important;
|
||||
}
|
||||
.alertify.ajs-maximized.ajs-modeless .ajs-modal {
|
||||
position: fixed !important;
|
||||
min-height: 100% !important;
|
||||
max-height: none !important;
|
||||
margin: 0 !important;
|
||||
}
|
||||
.alertify.ajs-maximized .ajs-commands button.ajs-maximize {
|
||||
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAABZ0RVh0Q3JlYXRpb24gVGltZQAwNy8xMy8xNOrZqugAAAAcdEVYdFNvZnR3YXJlAEFkb2JlIEZpcmV3b3JrcyBDUzbovLKMAAAASklEQVQYlZWQ0QkAMQhDtXRincOZX78KVtrDCwgqJNEoIB3MPLj7lRUROlpyVXGzby6zWuY+kz6tj5sBMTMAyVV3/595RbOh3cAXsww1raeiOcoAAAAASUVORK5CYII=);
|
||||
}
|
||||
.alertify.ajs-resizable .ajs-dialog,
|
||||
.alertify.ajs-maximized .ajs-dialog {
|
||||
padding: 0;
|
||||
}
|
||||
.alertify.ajs-resizable .ajs-commands,
|
||||
.alertify.ajs-maximized .ajs-commands {
|
||||
margin: 14px 24px 0 0;
|
||||
}
|
||||
.alertify.ajs-resizable .ajs-header,
|
||||
.alertify.ajs-maximized .ajs-header {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
margin: 0;
|
||||
padding: 16px 24px;
|
||||
}
|
||||
.alertify.ajs-resizable .ajs-body,
|
||||
.alertify.ajs-maximized .ajs-body {
|
||||
min-height: 224px;
|
||||
display: inline-block;
|
||||
}
|
||||
.alertify.ajs-resizable .ajs-body .ajs-content,
|
||||
.alertify.ajs-maximized .ajs-body .ajs-content {
|
||||
position: absolute;
|
||||
top: 50px;
|
||||
right: 24px;
|
||||
bottom: 50px;
|
||||
left: 24px;
|
||||
overflow: auto;
|
||||
}
|
||||
.alertify.ajs-resizable .ajs-footer,
|
||||
.alertify.ajs-maximized .ajs-footer {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
margin: 0;
|
||||
}
|
||||
.alertify.ajs-resizable:not(.ajs-maximized) .ajs-dialog {
|
||||
min-width: 548px;
|
||||
}
|
||||
.alertify.ajs-resizable:not(.ajs-maximized) .ajs-handle {
|
||||
display: block;
|
||||
}
|
||||
.alertify.ajs-movable:not(.ajs-maximized) .ajs-header {
|
||||
cursor: move;
|
||||
}
|
||||
.alertify.ajs-modeless .ajs-dimmer,
|
||||
.alertify.ajs-modeless .ajs-reset {
|
||||
display: none;
|
||||
}
|
||||
.alertify.ajs-modeless .ajs-modal {
|
||||
overflow: visible;
|
||||
max-width: none;
|
||||
max-height: 0;
|
||||
}
|
||||
.alertify.ajs-modeless.ajs-pinnable .ajs-commands button.ajs-pin {
|
||||
display: inline-block;
|
||||
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAABZ0RVh0Q3JlYXRpb24gVGltZQAwNy8xMy8xNOrZqugAAAAcdEVYdFNvZnR3YXJlAEFkb2JlIEZpcmV3b3JrcyBDUzbovLKMAAAAQklEQVQYlcWPMQ4AIAwCqU9u38GbcbHRWN1MvKQDhQFMEpKImGJA0gCgnYw0V0rwxseg5erT4oSkQVI5d9f+e9+xA0NbLpWfitPXAAAAAElFTkSuQmCC);
|
||||
}
|
||||
.alertify.ajs-modeless.ajs-unpinned .ajs-modal {
|
||||
position: absolute;
|
||||
}
|
||||
.alertify.ajs-modeless.ajs-unpinned .ajs-commands button.ajs-pin {
|
||||
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAABZ0RVh0Q3JlYXRpb24gVGltZQAwNy8xMy8xNOrZqugAAAAcdEVYdFNvZnR3YXJlAEFkb2JlIEZpcmV3b3JrcyBDUzbovLKMAAAAO0lEQVQYlWP8//8/AzGAiShV6AqLi4txGs+CLoBLMYbC3t5eRmyaWfBZhwwYkX2NTxPRvibKjRhW4wMAhxkYGbLu3pEAAAAASUVORK5CYII=);
|
||||
}
|
||||
.alertify.ajs-modeless:not(.ajs-unpinned) .ajs-body {
|
||||
max-height: 500px;
|
||||
overflow: auto;
|
||||
}
|
||||
.alertify.ajs-basic .ajs-header {
|
||||
opacity: 0;
|
||||
}
|
||||
.alertify.ajs-basic .ajs-footer {
|
||||
visibility: hidden;
|
||||
}
|
||||
.alertify.ajs-frameless .ajs-header {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
min-height: 60px;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
opacity: 0;
|
||||
z-index: 1;
|
||||
}
|
||||
.alertify.ajs-frameless .ajs-footer {
|
||||
display: none;
|
||||
}
|
||||
.alertify.ajs-frameless .ajs-body .ajs-content {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
}
|
||||
.alertify.ajs-frameless:not(.ajs-resizable) .ajs-dialog {
|
||||
padding-top: 0;
|
||||
}
|
||||
.alertify.ajs-frameless:not(.ajs-resizable) .ajs-dialog .ajs-commands {
|
||||
margin-top: 0;
|
||||
}
|
||||
.ajs-no-overflow {
|
||||
overflow: hidden !important;
|
||||
outline: none;
|
||||
}
|
||||
.ajs-no-overflow.ajs-fixed {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
overflow-y: scroll!important;
|
||||
}
|
||||
.ajs-no-selection,
|
||||
.ajs-no-selection * {
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
}
|
||||
@media screen and (max-width: 568px) {
|
||||
.alertify .ajs-dialog {
|
||||
min-width: 150px;
|
||||
}
|
||||
.alertify:not(.ajs-maximized) .ajs-modal {
|
||||
padding: 0 5%;
|
||||
}
|
||||
.alertify:not(.ajs-maximized).ajs-resizable .ajs-dialog {
|
||||
min-width: initial;
|
||||
min-width: auto /*IE fallback*/;
|
||||
}
|
||||
}
|
||||
@-moz-document url-prefix() {
|
||||
.alertify button:focus {
|
||||
outline: 1px dotted #3593D2;
|
||||
}
|
||||
}
|
||||
.alertify .ajs-dimmer,
|
||||
.alertify .ajs-modal {
|
||||
-webkit-transform: translate3d(0, 0, 0);
|
||||
transform: translate3d(0, 0, 0);
|
||||
transition-property: opacity, visibility;
|
||||
transition-timing-function: linear;
|
||||
transition-duration: 250ms;
|
||||
}
|
||||
.alertify.ajs-hidden .ajs-dimmer,
|
||||
.alertify.ajs-hidden .ajs-modal {
|
||||
visibility: hidden;
|
||||
opacity: 0;
|
||||
}
|
||||
.alertify.ajs-in:not(.ajs-hidden) .ajs-dialog {
|
||||
-webkit-animation-duration: 500ms;
|
||||
animation-duration: 500ms;
|
||||
}
|
||||
.alertify.ajs-out.ajs-hidden .ajs-dialog {
|
||||
-webkit-animation-duration: 250ms;
|
||||
animation-duration: 250ms;
|
||||
}
|
||||
.alertify .ajs-dialog.ajs-shake {
|
||||
-webkit-animation-name: ajs-shake;
|
||||
animation-name: ajs-shake;
|
||||
-webkit-animation-duration: .1s;
|
||||
animation-duration: .1s;
|
||||
-webkit-animation-fill-mode: both;
|
||||
animation-fill-mode: both;
|
||||
}
|
||||
@-webkit-keyframes ajs-shake {
|
||||
0%,
|
||||
100% {
|
||||
-webkit-transform: translate3d(0, 0, 0);
|
||||
transform: translate3d(0, 0, 0);
|
||||
}
|
||||
10%,
|
||||
30%,
|
||||
50%,
|
||||
70%,
|
||||
90% {
|
||||
-webkit-transform: translate3d(-10px, 0, 0);
|
||||
transform: translate3d(-10px, 0, 0);
|
||||
}
|
||||
20%,
|
||||
40%,
|
||||
60%,
|
||||
80% {
|
||||
-webkit-transform: translate3d(10px, 0, 0);
|
||||
transform: translate3d(10px, 0, 0);
|
||||
}
|
||||
}
|
||||
@keyframes ajs-shake {
|
||||
0%,
|
||||
100% {
|
||||
-webkit-transform: translate3d(0, 0, 0);
|
||||
transform: translate3d(0, 0, 0);
|
||||
}
|
||||
10%,
|
||||
30%,
|
||||
50%,
|
||||
70%,
|
||||
90% {
|
||||
-webkit-transform: translate3d(-10px, 0, 0);
|
||||
transform: translate3d(-10px, 0, 0);
|
||||
}
|
||||
20%,
|
||||
40%,
|
||||
60%,
|
||||
80% {
|
||||
-webkit-transform: translate3d(10px, 0, 0);
|
||||
transform: translate3d(10px, 0, 0);
|
||||
}
|
||||
}
|
||||
.alertify.ajs-slide.ajs-in:not(.ajs-hidden) .ajs-dialog {
|
||||
-webkit-animation-name: ajs-slideIn;
|
||||
animation-name: ajs-slideIn;
|
||||
-webkit-animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1.275);
|
||||
animation-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1.275);
|
||||
}
|
||||
.alertify.ajs-slide.ajs-out.ajs-hidden .ajs-dialog {
|
||||
-webkit-animation-name: ajs-slideOut;
|
||||
animation-name: ajs-slideOut;
|
||||
-webkit-animation-timing-function: cubic-bezier(0.6, -0.28, 0.735, 0.045);
|
||||
animation-timing-function: cubic-bezier(0.6, -0.28, 0.735, 0.045);
|
||||
}
|
||||
.alertify.ajs-zoom.ajs-in:not(.ajs-hidden) .ajs-dialog {
|
||||
-webkit-animation-name: ajs-zoomIn;
|
||||
animation-name: ajs-zoomIn;
|
||||
}
|
||||
.alertify.ajs-zoom.ajs-out.ajs-hidden .ajs-dialog {
|
||||
-webkit-animation-name: ajs-zoomOut;
|
||||
animation-name: ajs-zoomOut;
|
||||
}
|
||||
.alertify.ajs-fade.ajs-in:not(.ajs-hidden) .ajs-dialog {
|
||||
-webkit-animation-name: ajs-fadeIn;
|
||||
animation-name: ajs-fadeIn;
|
||||
}
|
||||
.alertify.ajs-fade.ajs-out.ajs-hidden .ajs-dialog {
|
||||
-webkit-animation-name: ajs-fadeOut;
|
||||
animation-name: ajs-fadeOut;
|
||||
}
|
||||
.alertify.ajs-pulse.ajs-in:not(.ajs-hidden) .ajs-dialog {
|
||||
-webkit-animation-name: ajs-pulseIn;
|
||||
animation-name: ajs-pulseIn;
|
||||
}
|
||||
.alertify.ajs-pulse.ajs-out.ajs-hidden .ajs-dialog {
|
||||
-webkit-animation-name: ajs-pulseOut;
|
||||
animation-name: ajs-pulseOut;
|
||||
}
|
||||
.alertify.ajs-flipx.ajs-in:not(.ajs-hidden) .ajs-dialog {
|
||||
-webkit-animation-name: ajs-flipInX;
|
||||
animation-name: ajs-flipInX;
|
||||
}
|
||||
.alertify.ajs-flipx.ajs-out.ajs-hidden .ajs-dialog {
|
||||
-webkit-animation-name: ajs-flipOutX;
|
||||
animation-name: ajs-flipOutX;
|
||||
}
|
||||
.alertify.ajs-flipy.ajs-in:not(.ajs-hidden) .ajs-dialog {
|
||||
-webkit-animation-name: ajs-flipInY;
|
||||
animation-name: ajs-flipInY;
|
||||
}
|
||||
.alertify.ajs-flipy.ajs-out.ajs-hidden .ajs-dialog {
|
||||
-webkit-animation-name: ajs-flipOutY;
|
||||
animation-name: ajs-flipOutY;
|
||||
}
|
||||
@-webkit-keyframes ajs-pulseIn {
|
||||
0%,
|
||||
20%,
|
||||
40%,
|
||||
60%,
|
||||
80%,
|
||||
100% {
|
||||
transition-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
|
||||
}
|
||||
0% {
|
||||
opacity: 0;
|
||||
-webkit-transform: scale3d(0.3, 0.3, 0.3);
|
||||
transform: scale3d(0.3, 0.3, 0.3);
|
||||
}
|
||||
20% {
|
||||
-webkit-transform: scale3d(1.1, 1.1, 1.1);
|
||||
transform: scale3d(1.1, 1.1, 1.1);
|
||||
}
|
||||
40% {
|
||||
-webkit-transform: scale3d(0.9, 0.9, 0.9);
|
||||
transform: scale3d(0.9, 0.9, 0.9);
|
||||
}
|
||||
60% {
|
||||
opacity: 1;
|
||||
-webkit-transform: scale3d(1.03, 1.03, 1.03);
|
||||
transform: scale3d(1.03, 1.03, 1.03);
|
||||
}
|
||||
80% {
|
||||
-webkit-transform: scale3d(0.97, 0.97, 0.97);
|
||||
transform: scale3d(0.97, 0.97, 0.97);
|
||||
}
|
||||
100% {
|
||||
opacity: 1;
|
||||
-webkit-transform: scale3d(1, 1, 1);
|
||||
transform: scale3d(1, 1, 1);
|
||||
}
|
||||
}
|
||||
@keyframes ajs-pulseIn {
|
||||
0%,
|
||||
20%,
|
||||
40%,
|
||||
60%,
|
||||
80%,
|
||||
100% {
|
||||
transition-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
|
||||
}
|
||||
0% {
|
||||
opacity: 0;
|
||||
-webkit-transform: scale3d(0.3, 0.3, 0.3);
|
||||
transform: scale3d(0.3, 0.3, 0.3);
|
||||
}
|
||||
20% {
|
||||
-webkit-transform: scale3d(1.1, 1.1, 1.1);
|
||||
transform: scale3d(1.1, 1.1, 1.1);
|
||||
}
|
||||
40% {
|
||||
-webkit-transform: scale3d(0.9, 0.9, 0.9);
|
||||
transform: scale3d(0.9, 0.9, 0.9);
|
||||
}
|
||||
60% {
|
||||
opacity: 1;
|
||||
-webkit-transform: scale3d(1.03, 1.03, 1.03);
|
||||
transform: scale3d(1.03, 1.03, 1.03);
|
||||
}
|
||||
80% {
|
||||
-webkit-transform: scale3d(0.97, 0.97, 0.97);
|
||||
transform: scale3d(0.97, 0.97, 0.97);
|
||||
}
|
||||
100% {
|
||||
opacity: 1;
|
||||
-webkit-transform: scale3d(1, 1, 1);
|
||||
transform: scale3d(1, 1, 1);
|
||||
}
|
||||
}
|
||||
@-webkit-keyframes ajs-pulseOut {
|
||||
20% {
|
||||
-webkit-transform: scale3d(0.9, 0.9, 0.9);
|
||||
transform: scale3d(0.9, 0.9, 0.9);
|
||||
}
|
||||
50%,
|
||||
55% {
|
||||
opacity: 1;
|
||||
-webkit-transform: scale3d(1.1, 1.1, 1.1);
|
||||
transform: scale3d(1.1, 1.1, 1.1);
|
||||
}
|
||||
100% {
|
||||
opacity: 0;
|
||||
-webkit-transform: scale3d(0.3, 0.3, 0.3);
|
||||
transform: scale3d(0.3, 0.3, 0.3);
|
||||
}
|
||||
}
|
||||
@keyframes ajs-pulseOut {
|
||||
20% {
|
||||
-webkit-transform: scale3d(0.9, 0.9, 0.9);
|
||||
transform: scale3d(0.9, 0.9, 0.9);
|
||||
}
|
||||
50%,
|
||||
55% {
|
||||
opacity: 1;
|
||||
-webkit-transform: scale3d(1.1, 1.1, 1.1);
|
||||
transform: scale3d(1.1, 1.1, 1.1);
|
||||
}
|
||||
100% {
|
||||
opacity: 0;
|
||||
-webkit-transform: scale3d(0.3, 0.3, 0.3);
|
||||
transform: scale3d(0.3, 0.3, 0.3);
|
||||
}
|
||||
}
|
||||
@-webkit-keyframes ajs-zoomIn {
|
||||
0% {
|
||||
opacity: 0;
|
||||
-webkit-transform: scale3d(0.25, 0.25, 0.25);
|
||||
transform: scale3d(0.25, 0.25, 0.25);
|
||||
}
|
||||
100% {
|
||||
opacity: 1;
|
||||
-webkit-transform: scale3d(1, 1, 1);
|
||||
transform: scale3d(1, 1, 1);
|
||||
}
|
||||
}
|
||||
@keyframes ajs-zoomIn {
|
||||
0% {
|
||||
opacity: 0;
|
||||
-webkit-transform: scale3d(0.25, 0.25, 0.25);
|
||||
transform: scale3d(0.25, 0.25, 0.25);
|
||||
}
|
||||
100% {
|
||||
opacity: 1;
|
||||
-webkit-transform: scale3d(1, 1, 1);
|
||||
transform: scale3d(1, 1, 1);
|
||||
}
|
||||
}
|
||||
@-webkit-keyframes ajs-zoomOut {
|
||||
0% {
|
||||
opacity: 1;
|
||||
-webkit-transform: scale3d(1, 1, 1);
|
||||
transform: scale3d(1, 1, 1);
|
||||
}
|
||||
100% {
|
||||
opacity: 0;
|
||||
-webkit-transform: scale3d(0.25, 0.25, 0.25);
|
||||
transform: scale3d(0.25, 0.25, 0.25);
|
||||
}
|
||||
}
|
||||
@keyframes ajs-zoomOut {
|
||||
0% {
|
||||
opacity: 1;
|
||||
-webkit-transform: scale3d(1, 1, 1);
|
||||
transform: scale3d(1, 1, 1);
|
||||
}
|
||||
100% {
|
||||
opacity: 0;
|
||||
-webkit-transform: scale3d(0.25, 0.25, 0.25);
|
||||
transform: scale3d(0.25, 0.25, 0.25);
|
||||
}
|
||||
}
|
||||
@-webkit-keyframes ajs-fadeIn {
|
||||
0% {
|
||||
opacity: 0;
|
||||
}
|
||||
100% {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
@keyframes ajs-fadeIn {
|
||||
0% {
|
||||
opacity: 0;
|
||||
}
|
||||
100% {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
@-webkit-keyframes ajs-fadeOut {
|
||||
0% {
|
||||
opacity: 1;
|
||||
}
|
||||
100% {
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
@keyframes ajs-fadeOut {
|
||||
0% {
|
||||
opacity: 1;
|
||||
}
|
||||
100% {
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
@-webkit-keyframes ajs-flipInX {
|
||||
0% {
|
||||
-webkit-transform: perspective(400px) rotate3d(1, 0, 0, 90deg);
|
||||
transform: perspective(400px) rotate3d(1, 0, 0, 90deg);
|
||||
transition-timing-function: ease-in;
|
||||
opacity: 0;
|
||||
}
|
||||
40% {
|
||||
-webkit-transform: perspective(400px) rotate3d(1, 0, 0, -20deg);
|
||||
transform: perspective(400px) rotate3d(1, 0, 0, -20deg);
|
||||
transition-timing-function: ease-in;
|
||||
}
|
||||
60% {
|
||||
-webkit-transform: perspective(400px) rotate3d(1, 0, 0, 10deg);
|
||||
transform: perspective(400px) rotate3d(1, 0, 0, 10deg);
|
||||
opacity: 1;
|
||||
}
|
||||
80% {
|
||||
-webkit-transform: perspective(400px) rotate3d(1, 0, 0, -5deg);
|
||||
transform: perspective(400px) rotate3d(1, 0, 0, -5deg);
|
||||
}
|
||||
100% {
|
||||
-webkit-transform: perspective(400px);
|
||||
transform: perspective(400px);
|
||||
}
|
||||
}
|
||||
@keyframes ajs-flipInX {
|
||||
0% {
|
||||
-webkit-transform: perspective(400px) rotate3d(1, 0, 0, 90deg);
|
||||
transform: perspective(400px) rotate3d(1, 0, 0, 90deg);
|
||||
transition-timing-function: ease-in;
|
||||
opacity: 0;
|
||||
}
|
||||
40% {
|
||||
-webkit-transform: perspective(400px) rotate3d(1, 0, 0, -20deg);
|
||||
transform: perspective(400px) rotate3d(1, 0, 0, -20deg);
|
||||
transition-timing-function: ease-in;
|
||||
}
|
||||
60% {
|
||||
-webkit-transform: perspective(400px) rotate3d(1, 0, 0, 10deg);
|
||||
transform: perspective(400px) rotate3d(1, 0, 0, 10deg);
|
||||
opacity: 1;
|
||||
}
|
||||
80% {
|
||||
-webkit-transform: perspective(400px) rotate3d(1, 0, 0, -5deg);
|
||||
transform: perspective(400px) rotate3d(1, 0, 0, -5deg);
|
||||
}
|
||||
100% {
|
||||
-webkit-transform: perspective(400px);
|
||||
transform: perspective(400px);
|
||||
}
|
||||
}
|
||||
@-webkit-keyframes ajs-flipOutX {
|
||||
0% {
|
||||
-webkit-transform: perspective(400px);
|
||||
transform: perspective(400px);
|
||||
}
|
||||
30% {
|
||||
-webkit-transform: perspective(400px) rotate3d(1, 0, 0, -20deg);
|
||||
transform: perspective(400px) rotate3d(1, 0, 0, -20deg);
|
||||
opacity: 1;
|
||||
}
|
||||
100% {
|
||||
-webkit-transform: perspective(400px) rotate3d(1, 0, 0, 90deg);
|
||||
transform: perspective(400px) rotate3d(1, 0, 0, 90deg);
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
@keyframes ajs-flipOutX {
|
||||
0% {
|
||||
-webkit-transform: perspective(400px);
|
||||
transform: perspective(400px);
|
||||
}
|
||||
30% {
|
||||
-webkit-transform: perspective(400px) rotate3d(1, 0, 0, -20deg);
|
||||
transform: perspective(400px) rotate3d(1, 0, 0, -20deg);
|
||||
opacity: 1;
|
||||
}
|
||||
100% {
|
||||
-webkit-transform: perspective(400px) rotate3d(1, 0, 0, 90deg);
|
||||
transform: perspective(400px) rotate3d(1, 0, 0, 90deg);
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
@-webkit-keyframes ajs-flipInY {
|
||||
0% {
|
||||
-webkit-transform: perspective(400px) rotate3d(0, 1, 0, 90deg);
|
||||
transform: perspective(400px) rotate3d(0, 1, 0, 90deg);
|
||||
transition-timing-function: ease-in;
|
||||
opacity: 0;
|
||||
}
|
||||
40% {
|
||||
-webkit-transform: perspective(400px) rotate3d(0, 1, 0, -20deg);
|
||||
transform: perspective(400px) rotate3d(0, 1, 0, -20deg);
|
||||
transition-timing-function: ease-in;
|
||||
}
|
||||
60% {
|
||||
-webkit-transform: perspective(400px) rotate3d(0, 1, 0, 10deg);
|
||||
transform: perspective(400px) rotate3d(0, 1, 0, 10deg);
|
||||
opacity: 1;
|
||||
}
|
||||
80% {
|
||||
-webkit-transform: perspective(400px) rotate3d(0, 1, 0, -5deg);
|
||||
transform: perspective(400px) rotate3d(0, 1, 0, -5deg);
|
||||
}
|
||||
100% {
|
||||
-webkit-transform: perspective(400px);
|
||||
transform: perspective(400px);
|
||||
}
|
||||
}
|
||||
@keyframes ajs-flipInY {
|
||||
0% {
|
||||
-webkit-transform: perspective(400px) rotate3d(0, 1, 0, 90deg);
|
||||
transform: perspective(400px) rotate3d(0, 1, 0, 90deg);
|
||||
transition-timing-function: ease-in;
|
||||
opacity: 0;
|
||||
}
|
||||
40% {
|
||||
-webkit-transform: perspective(400px) rotate3d(0, 1, 0, -20deg);
|
||||
transform: perspective(400px) rotate3d(0, 1, 0, -20deg);
|
||||
transition-timing-function: ease-in;
|
||||
}
|
||||
60% {
|
||||
-webkit-transform: perspective(400px) rotate3d(0, 1, 0, 10deg);
|
||||
transform: perspective(400px) rotate3d(0, 1, 0, 10deg);
|
||||
opacity: 1;
|
||||
}
|
||||
80% {
|
||||
-webkit-transform: perspective(400px) rotate3d(0, 1, 0, -5deg);
|
||||
transform: perspective(400px) rotate3d(0, 1, 0, -5deg);
|
||||
}
|
||||
100% {
|
||||
-webkit-transform: perspective(400px);
|
||||
transform: perspective(400px);
|
||||
}
|
||||
}
|
||||
@-webkit-keyframes ajs-flipOutY {
|
||||
0% {
|
||||
-webkit-transform: perspective(400px);
|
||||
transform: perspective(400px);
|
||||
}
|
||||
30% {
|
||||
-webkit-transform: perspective(400px) rotate3d(0, 1, 0, -15deg);
|
||||
transform: perspective(400px) rotate3d(0, 1, 0, -15deg);
|
||||
opacity: 1;
|
||||
}
|
||||
100% {
|
||||
-webkit-transform: perspective(400px) rotate3d(0, 1, 0, 90deg);
|
||||
transform: perspective(400px) rotate3d(0, 1, 0, 90deg);
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
@keyframes ajs-flipOutY {
|
||||
0% {
|
||||
-webkit-transform: perspective(400px);
|
||||
transform: perspective(400px);
|
||||
}
|
||||
30% {
|
||||
-webkit-transform: perspective(400px) rotate3d(0, 1, 0, -15deg);
|
||||
transform: perspective(400px) rotate3d(0, 1, 0, -15deg);
|
||||
opacity: 1;
|
||||
}
|
||||
100% {
|
||||
-webkit-transform: perspective(400px) rotate3d(0, 1, 0, 90deg);
|
||||
transform: perspective(400px) rotate3d(0, 1, 0, 90deg);
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
@-webkit-keyframes ajs-slideIn {
|
||||
0% {
|
||||
margin-top: -100%;
|
||||
}
|
||||
100% {
|
||||
margin-top: 5%;
|
||||
}
|
||||
}
|
||||
@keyframes ajs-slideIn {
|
||||
0% {
|
||||
margin-top: -100%;
|
||||
}
|
||||
100% {
|
||||
margin-top: 5%;
|
||||
}
|
||||
}
|
||||
@-webkit-keyframes ajs-slideOut {
|
||||
0% {
|
||||
margin-top: 5%;
|
||||
}
|
||||
100% {
|
||||
margin-top: -100%;
|
||||
}
|
||||
}
|
||||
@keyframes ajs-slideOut {
|
||||
0% {
|
||||
margin-top: 5%;
|
||||
}
|
||||
100% {
|
||||
margin-top: -100%;
|
||||
}
|
||||
}
|
||||
.alertify-notifier {
|
||||
position: fixed;
|
||||
width: 0;
|
||||
overflow: visible;
|
||||
z-index: 1982;
|
||||
-webkit-transform: translate3d(0, 0, 0);
|
||||
transform: translate3d(0, 0, 0);
|
||||
}
|
||||
.alertify-notifier .ajs-message {
|
||||
position: relative;
|
||||
width: 260px;
|
||||
max-height: 0;
|
||||
padding: 0;
|
||||
opacity: 0;
|
||||
margin: 0;
|
||||
-webkit-transform: translate3d(0, 0, 0);
|
||||
transform: translate3d(0, 0, 0);
|
||||
transition-duration: 250ms;
|
||||
transition-timing-function: linear;
|
||||
}
|
||||
.alertify-notifier .ajs-message.ajs-visible {
|
||||
transition-duration: 500ms;
|
||||
transition-timing-function: cubic-bezier(0.175, 0.885, 0.32, 1.275);
|
||||
opacity: 1;
|
||||
max-height: 100%;
|
||||
padding: 15px;
|
||||
margin-top: 10px;
|
||||
}
|
||||
.alertify-notifier .ajs-message.ajs-success {
|
||||
background: rgba(91, 189, 114, 0.95);
|
||||
}
|
||||
.alertify-notifier .ajs-message.ajs-error {
|
||||
background: rgba(217, 92, 92, 0.95);
|
||||
}
|
||||
.alertify-notifier .ajs-message.ajs-warning {
|
||||
background: rgba(252, 248, 215, 0.95);
|
||||
}
|
||||
.alertify-notifier.ajs-top {
|
||||
top: 10px;
|
||||
}
|
||||
.alertify-notifier.ajs-bottom {
|
||||
bottom: 10px;
|
||||
}
|
||||
.alertify-notifier.ajs-right {
|
||||
right: 10px;
|
||||
}
|
||||
.alertify-notifier.ajs-right .ajs-message {
|
||||
right: -320px;
|
||||
}
|
||||
.alertify-notifier.ajs-right .ajs-message.ajs-visible {
|
||||
right: 290px;
|
||||
}
|
||||
.alertify-notifier.ajs-left {
|
||||
left: 10px;
|
||||
}
|
||||
.alertify-notifier.ajs-left .ajs-message {
|
||||
left: -300px;
|
||||
}
|
||||
.alertify-notifier.ajs-left .ajs-message.ajs-visible {
|
||||
left: 0;
|
||||
}
|
3572
client/externalFiles/alertify.js
Normal file
3572
client/externalFiles/alertify.js
Normal file
File diff suppressed because it is too large
Load Diff
1650
client/externalFiles/alertify.min.css
vendored
Normal file
1650
client/externalFiles/alertify.min.css
vendored
Normal file
File diff suppressed because it is too large
Load Diff
3
client/externalFiles/alertify.min.js
vendored
Normal file
3
client/externalFiles/alertify.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
678
client/externalFiles/chartjs-zoom new.js
Normal file
678
client/externalFiles/chartjs-zoom new.js
Normal file
@ -0,0 +1,678 @@
|
||||
//'use strict';
|
||||
|
||||
import {Chart} from 'chart.js';
|
||||
import Hammer from 'hammerjs';
|
||||
|
||||
var helpers = Chart.helpers;
|
||||
|
||||
// Take the zoom namespace of Chart
|
||||
var zoomNS = Chart.Zoom = Chart.Zoom || {};
|
||||
|
||||
// Where we store functions to handle different scale types
|
||||
var zoomFunctions = zoomNS.zoomFunctions = zoomNS.zoomFunctions || {};
|
||||
var panFunctions = zoomNS.panFunctions = zoomNS.panFunctions || {};
|
||||
|
||||
function resolveOptions(chart, options) {
|
||||
var deprecatedOptions = {};
|
||||
if (typeof chart.options.pan !== 'undefined') {
|
||||
deprecatedOptions.pan = chart.options.pan;
|
||||
}
|
||||
if (typeof chart.options.zoom !== 'undefined') {
|
||||
deprecatedOptions.zoom = chart.options.zoom;
|
||||
}
|
||||
var props = chart.$zoom;
|
||||
options = props._options = helpers.merge({}, [options, deprecatedOptions]);
|
||||
|
||||
// Install listeners. Do this dynamically based on options so that we can turn zoom on and off
|
||||
// We also want to make sure listeners aren't always on. E.g. if you're scrolling down a page
|
||||
// and the mouse goes over a chart you don't want it intercepted unless the plugin is enabled
|
||||
var node = props._node;
|
||||
var zoomEnabled = options.zoom && options.zoom.enabled;
|
||||
var dragEnabled = options.zoom.drag;
|
||||
if (zoomEnabled && !dragEnabled) {
|
||||
node.addEventListener('wheel', props._wheelHandler);
|
||||
} else {
|
||||
node.removeEventListener('wheel', props._wheelHandler);
|
||||
}
|
||||
if (zoomEnabled && dragEnabled) {
|
||||
node.addEventListener('mousedown', props._mouseDownHandler);
|
||||
node.ownerDocument.addEventListener('mouseup', props._mouseUpHandler);
|
||||
} else {
|
||||
node.removeEventListener('mousedown', props._mouseDownHandler);
|
||||
node.removeEventListener('mousemove', props._mouseMoveHandler);
|
||||
node.ownerDocument.removeEventListener('mouseup', props._mouseUpHandler);
|
||||
}
|
||||
}
|
||||
|
||||
function storeOriginalOptions(chart) {
|
||||
var originalOptions = chart.$zoom._originalOptions;
|
||||
helpers.each(chart.scales, function(scale) {
|
||||
if (!originalOptions[scale.id]) {
|
||||
originalOptions[scale.id] = helpers.clone(scale.options);
|
||||
}
|
||||
});
|
||||
helpers.each(originalOptions, function(opt, key) {
|
||||
if (!chart.scales[key]) {
|
||||
delete originalOptions[key];
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} mode can be 'x', 'y' or 'xy'
|
||||
* @param {string} dir can be 'x' or 'y'
|
||||
* @param {Chart} chart instance of the chart in question
|
||||
*/
|
||||
function directionEnabled(mode, dir, chart) {
|
||||
if (mode === undefined) {
|
||||
return true;
|
||||
} else if (typeof mode === 'string') {
|
||||
return mode.indexOf(dir) !== -1;
|
||||
} else if (typeof mode === 'function') {
|
||||
return mode({chart: chart}).indexOf(dir) !== -1;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function rangeMaxLimiter(zoomPanOptions, newMax) {
|
||||
if (zoomPanOptions.scaleAxes && zoomPanOptions.rangeMax &&
|
||||
!helpers.isNullOrUndef(zoomPanOptions.rangeMax[zoomPanOptions.scaleAxes])) {
|
||||
var rangeMax = zoomPanOptions.rangeMax[zoomPanOptions.scaleAxes];
|
||||
if (newMax > rangeMax) {
|
||||
newMax = rangeMax;
|
||||
}
|
||||
}
|
||||
return newMax;
|
||||
}
|
||||
|
||||
function rangeMinLimiter(zoomPanOptions, newMin) {
|
||||
if (zoomPanOptions.scaleAxes && zoomPanOptions.rangeMin &&
|
||||
!helpers.isNullOrUndef(zoomPanOptions.rangeMin[zoomPanOptions.scaleAxes])) {
|
||||
var rangeMin = zoomPanOptions.rangeMin[zoomPanOptions.scaleAxes];
|
||||
if (newMin < rangeMin) {
|
||||
newMin = rangeMin;
|
||||
}
|
||||
}
|
||||
return newMin;
|
||||
}
|
||||
|
||||
function zoomCategoryScale(scale, zoom, center, zoomOptions) {
|
||||
var labels = scale.chart.data.labels;
|
||||
var minIndex = scale.min;
|
||||
var lastLabelIndex = labels.length - 1;
|
||||
var maxIndex = scale.max;
|
||||
var sensitivity = zoomOptions.sensitivity;
|
||||
var chartCenter = scale.isHorizontal() ? scale.left + (scale.width / 2) : scale.top + (scale.height / 2);
|
||||
var centerPointer = scale.isHorizontal() ? center.x : center.y;
|
||||
|
||||
zoomNS.zoomCumulativeDelta = zoom > 1 ? zoomNS.zoomCumulativeDelta + 1 : zoomNS.zoomCumulativeDelta - 1;
|
||||
|
||||
if (Math.abs(zoomNS.zoomCumulativeDelta) > sensitivity) {
|
||||
if (zoomNS.zoomCumulativeDelta < 0) {
|
||||
if (centerPointer >= chartCenter) {
|
||||
if (minIndex <= 0) {
|
||||
maxIndex = Math.min(lastLabelIndex, maxIndex + 1);
|
||||
} else {
|
||||
minIndex = Math.max(0, minIndex - 1);
|
||||
}
|
||||
} else if (centerPointer < chartCenter) {
|
||||
if (maxIndex >= lastLabelIndex) {
|
||||
minIndex = Math.max(0, minIndex - 1);
|
||||
} else {
|
||||
maxIndex = Math.min(lastLabelIndex, maxIndex + 1);
|
||||
}
|
||||
}
|
||||
zoomNS.zoomCumulativeDelta = 0;
|
||||
} else if (zoomNS.zoomCumulativeDelta > 0) {
|
||||
if (centerPointer >= chartCenter) {
|
||||
minIndex = minIndex < maxIndex ? minIndex = Math.min(maxIndex, minIndex + 1) : minIndex;
|
||||
} else if (centerPointer < chartCenter) {
|
||||
maxIndex = maxIndex > minIndex ? maxIndex = Math.max(minIndex, maxIndex - 1) : maxIndex;
|
||||
}
|
||||
zoomNS.zoomCumulativeDelta = 0;
|
||||
}
|
||||
scale.options.min = rangeMinLimiter(zoomOptions, labels[minIndex]);
|
||||
scale.options.max = rangeMaxLimiter(zoomOptions, labels[maxIndex]);
|
||||
}
|
||||
}
|
||||
|
||||
function zoomNumericalScale(scale, zoom, center, zoomOptions) {
|
||||
var range = scale.max - scale.min;
|
||||
var newDiff = range * (zoom - 1);
|
||||
|
||||
var centerPoint = scale.isHorizontal() ? center.x : center.y;
|
||||
var minPercent = (scale.getValueForPixel(centerPoint) - scale.min) / range;
|
||||
var maxPercent = 1 - minPercent;
|
||||
|
||||
var minDelta = newDiff * minPercent;
|
||||
var maxDelta = newDiff * maxPercent;
|
||||
|
||||
console.log("SCOPT", scale.options)
|
||||
scale.options.min = rangeMinLimiter(zoomOptions, scale.min + minDelta);
|
||||
scale.options.max = rangeMaxLimiter(zoomOptions, scale.max - maxDelta);
|
||||
}
|
||||
|
||||
function zoomScale(scale, zoom, center, zoomOptions) {
|
||||
var fn = zoomFunctions[scale.type];
|
||||
if (fn) {
|
||||
fn(scale, zoom, center, zoomOptions);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param chart The chart instance
|
||||
* @param {number} percentZoomX The zoom percentage in the x direction
|
||||
* @param {number} percentZoomY The zoom percentage in the y direction
|
||||
* @param {{x: number, y: number}} focalPoint The x and y coordinates of zoom focal point. The point which doesn't change while zooming. E.g. the location of the mouse cursor when "drag: false"
|
||||
* @param {string} whichAxes `xy`, 'x', or 'y'
|
||||
* @param {number} animationDuration Duration of the animation of the redraw in milliseconds
|
||||
*/
|
||||
function doZoom(chart, percentZoomX, percentZoomY, focalPoint, whichAxes, animationDuration) {
|
||||
var ca = chart.chartArea;
|
||||
if (!focalPoint) {
|
||||
focalPoint = {
|
||||
x: (ca.left + ca.right) / 2,
|
||||
y: (ca.top + ca.bottom) / 2,
|
||||
};
|
||||
}
|
||||
|
||||
var zoomOptions = chart.$zoom._options.zoom;
|
||||
|
||||
if (zoomOptions.enabled) {
|
||||
storeOriginalOptions(chart);
|
||||
// Do the zoom here
|
||||
var zoomMode = typeof zoomOptions.mode === 'function' ? zoomOptions.mode({chart: chart}) : zoomOptions.mode;
|
||||
|
||||
// Which axe should be modified when figers were used.
|
||||
var _whichAxes;
|
||||
if (zoomMode === 'xy' && whichAxes !== undefined) {
|
||||
// based on fingers positions
|
||||
_whichAxes = whichAxes;
|
||||
} else {
|
||||
// no effect
|
||||
_whichAxes = 'xy';
|
||||
}
|
||||
|
||||
helpers.each(chart.scales, function(scale) {
|
||||
if (scale.isHorizontal() && directionEnabled(zoomMode, 'x', chart) && directionEnabled(_whichAxes, 'x', chart)) {
|
||||
zoomOptions.scaleAxes = 'x';
|
||||
zoomScale(scale, percentZoomX, focalPoint, zoomOptions);
|
||||
} else if (!scale.isHorizontal() && directionEnabled(zoomMode, 'y', chart) && directionEnabled(_whichAxes, 'y', chart)) {
|
||||
// Do Y zoom
|
||||
zoomOptions.scaleAxes = 'y';
|
||||
zoomScale(scale, percentZoomY, focalPoint, zoomOptions);
|
||||
}
|
||||
});
|
||||
|
||||
if (animationDuration) {
|
||||
// needs to create specific animation mode
|
||||
if (!chart.options.animation.zoom) {
|
||||
chart.options.animation.zoom = {
|
||||
duration: animationDuration,
|
||||
easing: 'easeOutQuad',
|
||||
};
|
||||
}
|
||||
chart.update('zoom');
|
||||
} else {
|
||||
chart.update('none');
|
||||
}
|
||||
|
||||
if (typeof zoomOptions.onZoom === 'function') {
|
||||
zoomOptions.onZoom({chart: chart});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function panCategoryScale(scale, delta, panOptions) {
|
||||
var labels = scale.chart.data.labels;
|
||||
var lastLabelIndex = labels.length - 1;
|
||||
var offsetAmt = Math.max(scale.ticks.length, 1);
|
||||
var panSpeed = panOptions.speed;
|
||||
var minIndex = scale.min;
|
||||
var step = Math.round(scale.width / (offsetAmt * panSpeed));
|
||||
var maxIndex;
|
||||
|
||||
zoomNS.panCumulativeDelta += delta;
|
||||
|
||||
minIndex = zoomNS.panCumulativeDelta > step ? Math.max(0, minIndex - 1) : zoomNS.panCumulativeDelta < -step ? Math.min(lastLabelIndex - offsetAmt + 1, minIndex + 1) : minIndex;
|
||||
zoomNS.panCumulativeDelta = minIndex !== scale.min ? 0 : zoomNS.panCumulativeDelta;
|
||||
|
||||
maxIndex = Math.min(lastLabelIndex, minIndex + offsetAmt - 1);
|
||||
|
||||
scale.options.min = rangeMinLimiter(panOptions, labels[minIndex]);
|
||||
scale.options.max = rangeMaxLimiter(panOptions, labels[maxIndex]);
|
||||
}
|
||||
|
||||
function panNumericalScale(scale, delta, panOptions) {
|
||||
var scaleOpts = scale.options;
|
||||
var prevStart = scale.min;
|
||||
var prevEnd = scale.max;
|
||||
var newMin = scale.getValueForPixel(scale.getPixelForValue(prevStart) - delta);
|
||||
var newMax = scale.getValueForPixel(scale.getPixelForValue(prevEnd) - delta);
|
||||
var rangeMin = newMin;
|
||||
var rangeMax = newMax;
|
||||
var diff;
|
||||
|
||||
if (panOptions.scaleAxes && panOptions.rangeMin &&
|
||||
!helpers.isNullOrUndef(panOptions.rangeMin[panOptions.scaleAxes])) {
|
||||
rangeMin = panOptions.rangeMin[panOptions.scaleAxes];
|
||||
}
|
||||
if (panOptions.scaleAxes && panOptions.rangeMax &&
|
||||
!helpers.isNullOrUndef(panOptions.rangeMax[panOptions.scaleAxes])) {
|
||||
rangeMax = panOptions.rangeMax[panOptions.scaleAxes];
|
||||
}
|
||||
|
||||
console.log("SCOPT pan", scaleOpts);
|
||||
|
||||
if (newMin >= rangeMin && newMax <= rangeMax) {
|
||||
scaleOpts.min = newMin;
|
||||
scaleOpts.max = newMax;
|
||||
} else if (newMin < rangeMin) {
|
||||
diff = prevStart - rangeMin;
|
||||
scaleOpts.min = rangeMin;
|
||||
scaleOpts.max = prevEnd - diff;
|
||||
} else if (newMax > rangeMax) {
|
||||
diff = rangeMax - prevEnd;
|
||||
scaleOpts.max = rangeMax;
|
||||
scaleOpts.min = prevStart + diff;
|
||||
}
|
||||
}
|
||||
|
||||
function panScale(scale, delta, panOptions) {
|
||||
var fn = panFunctions[scale.type];
|
||||
if (fn) {
|
||||
fn(scale, delta, panOptions);
|
||||
}
|
||||
}
|
||||
|
||||
function doPan(chartInstance, deltaX, deltaY) {
|
||||
storeOriginalOptions(chartInstance);
|
||||
var panOptions = chartInstance.$zoom._options.pan;
|
||||
if (panOptions.enabled) {
|
||||
var panMode = typeof panOptions.mode === 'function' ? panOptions.mode({chart: chartInstance}) : panOptions.mode;
|
||||
|
||||
helpers.each(chartInstance.scales, function(scale) {
|
||||
if (scale.isHorizontal() && directionEnabled(panMode, 'x', chartInstance) && deltaX !== 0) {
|
||||
panOptions.scaleAxes = 'x';
|
||||
panScale(scale, deltaX, panOptions);
|
||||
} else if (!scale.isHorizontal() && directionEnabled(panMode, 'y', chartInstance) && deltaY !== 0) {
|
||||
panOptions.scaleAxes = 'y';
|
||||
panScale(scale, deltaY, panOptions);
|
||||
}
|
||||
});
|
||||
|
||||
chartInstance.update('none');
|
||||
|
||||
if (typeof panOptions.onPan === 'function') {
|
||||
panOptions.onPan({chart: chartInstance});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function getXAxis(chartInstance) {
|
||||
var scales = chartInstance.scales;
|
||||
var scaleIds = Object.keys(scales);
|
||||
for (var i = 0; i < scaleIds.length; i++) {
|
||||
var scale = scales[scaleIds[i]];
|
||||
|
||||
if (scale.isHorizontal()) {
|
||||
return scale;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function getYAxis(chartInstance) {
|
||||
var scales = chartInstance.scales;
|
||||
var scaleIds = Object.keys(scales);
|
||||
for (var i = 0; i < scaleIds.length; i++) {
|
||||
var scale = scales[scaleIds[i]];
|
||||
|
||||
if (!scale.isHorizontal()) {
|
||||
return scale;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Store these for later
|
||||
zoomNS.zoomFunctions.category = zoomCategoryScale;
|
||||
zoomNS.zoomFunctions.time = zoomNumericalScale;
|
||||
zoomNS.zoomFunctions.linear = zoomNumericalScale;
|
||||
zoomNS.zoomFunctions.logarithmic = zoomNumericalScale;
|
||||
zoomNS.panFunctions.category = panCategoryScale;
|
||||
zoomNS.panFunctions.time = panNumericalScale;
|
||||
zoomNS.panFunctions.linear = panNumericalScale;
|
||||
zoomNS.panFunctions.logarithmic = panNumericalScale;
|
||||
// Globals for category pan and zoom
|
||||
zoomNS.panCumulativeDelta = 0;
|
||||
zoomNS.zoomCumulativeDelta = 0;
|
||||
|
||||
// Chartjs Zoom Plugin
|
||||
var zoomPlugin = {
|
||||
id: 'zoom',
|
||||
|
||||
defaults: {
|
||||
pan: {
|
||||
enabled: false,
|
||||
mode: 'xy',
|
||||
speed: 20,
|
||||
threshold: 10
|
||||
},
|
||||
zoom: {
|
||||
enabled: false,
|
||||
mode: 'xy',
|
||||
sensitivity: 3,
|
||||
speed: 0.1
|
||||
}
|
||||
},
|
||||
|
||||
afterInit: function(chartInstance) {
|
||||
|
||||
chartInstance.resetZoom = function() {
|
||||
storeOriginalOptions(chartInstance);
|
||||
var originalOptions = chartInstance.$zoom._originalOptions;
|
||||
helpers.each(chartInstance.scales, function(scale) {
|
||||
|
||||
var options = scale.options;
|
||||
if (originalOptions[scale.id]) {
|
||||
options.min = originalOptions[scale.id].min;
|
||||
options.max = originalOptions[scale.id].max;
|
||||
} else {
|
||||
delete options.min;
|
||||
delete options.max;
|
||||
}
|
||||
});
|
||||
chartInstance.update();
|
||||
};
|
||||
|
||||
},
|
||||
|
||||
beforeUpdate: function(chart, args, options) {
|
||||
resolveOptions(chart, options);
|
||||
},
|
||||
|
||||
beforeInit: function(chartInstance, pluginOptions) {
|
||||
chartInstance.$zoom = {
|
||||
_originalOptions: {}
|
||||
};
|
||||
var node = chartInstance.$zoom._node = chartInstance.ctx.canvas;
|
||||
resolveOptions(chartInstance, pluginOptions);
|
||||
|
||||
var options = chartInstance.$zoom._options;
|
||||
var panThreshold = options.pan && options.pan.threshold;
|
||||
|
||||
chartInstance.$zoom._mouseDownHandler = function(event) {
|
||||
node.addEventListener('mousemove', chartInstance.$zoom._mouseMoveHandler);
|
||||
chartInstance.$zoom._dragZoomStart = event;
|
||||
};
|
||||
|
||||
chartInstance.$zoom._mouseMoveHandler = function(event) {
|
||||
if (chartInstance.$zoom._dragZoomStart) {
|
||||
chartInstance.$zoom._dragZoomEnd = event;
|
||||
chartInstance.update('none');
|
||||
}
|
||||
};
|
||||
|
||||
chartInstance.$zoom._mouseUpHandler = function(event) {
|
||||
if (!chartInstance.$zoom._dragZoomStart) {
|
||||
return;
|
||||
}
|
||||
|
||||
node.removeEventListener('mousemove', chartInstance.$zoom._mouseMoveHandler);
|
||||
|
||||
var beginPoint = chartInstance.$zoom._dragZoomStart;
|
||||
|
||||
var offsetX = beginPoint.target.getBoundingClientRect().left;
|
||||
var startX = Math.min(beginPoint.clientX, event.clientX) - offsetX;
|
||||
var endX = Math.max(beginPoint.clientX, event.clientX) - offsetX;
|
||||
|
||||
var offsetY = beginPoint.target.getBoundingClientRect().top;
|
||||
var startY = Math.min(beginPoint.clientY, event.clientY) - offsetY;
|
||||
var endY = Math.max(beginPoint.clientY, event.clientY) - offsetY;
|
||||
|
||||
var dragDistanceX = endX - startX;
|
||||
var dragDistanceY = endY - startY;
|
||||
|
||||
// Remove drag start and end before chart update to stop drawing selected area
|
||||
chartInstance.$zoom._dragZoomStart = null;
|
||||
chartInstance.$zoom._dragZoomEnd = null;
|
||||
|
||||
var zoomThreshold = (options.zoom && options.zoom.threshold) || 0;
|
||||
if (dragDistanceX <= zoomThreshold && dragDistanceY <= zoomThreshold) {
|
||||
return;
|
||||
}
|
||||
|
||||
var chartArea = chartInstance.chartArea;
|
||||
|
||||
var zoomOptions = chartInstance.$zoom._options.zoom;
|
||||
var chartDistanceX = chartArea.right - chartArea.left;
|
||||
var xEnabled = directionEnabled(zoomOptions.mode, 'x', chartInstance);
|
||||
var zoomX = xEnabled && dragDistanceX ? 1 + ((chartDistanceX - dragDistanceX) / chartDistanceX) : 1;
|
||||
|
||||
var chartDistanceY = chartArea.bottom - chartArea.top;
|
||||
var yEnabled = directionEnabled(zoomOptions.mode, 'y', chartInstance);
|
||||
var zoomY = yEnabled && dragDistanceY ? 1 + ((chartDistanceY - dragDistanceY) / chartDistanceY) : 1;
|
||||
|
||||
doZoom(chartInstance, zoomX, zoomY, {
|
||||
x: (startX - chartArea.left) / (1 - dragDistanceX / chartDistanceX) + chartArea.left,
|
||||
y: (startY - chartArea.top) / (1 - dragDistanceY / chartDistanceY) + chartArea.top
|
||||
}, undefined, zoomOptions.drag.animationDuration);
|
||||
|
||||
if (typeof zoomOptions.onZoomComplete === 'function') {
|
||||
zoomOptions.onZoomComplete({chart: chartInstance});
|
||||
}
|
||||
};
|
||||
|
||||
var _scrollTimeout = null;
|
||||
chartInstance.$zoom._wheelHandler = function(event) {
|
||||
// Prevent the event from triggering the default behavior (eg. Content scrolling).
|
||||
if (event.cancelable) {
|
||||
event.preventDefault();
|
||||
}
|
||||
|
||||
// Firefox always fires the wheel event twice:
|
||||
// First without the delta and right after that once with the delta properties.
|
||||
if (typeof event.deltaY === 'undefined') {
|
||||
return;
|
||||
}
|
||||
|
||||
var rect = event.target.getBoundingClientRect();
|
||||
var offsetX = event.clientX - rect.left;
|
||||
var offsetY = event.clientY - rect.top;
|
||||
|
||||
var center = {
|
||||
x: offsetX,
|
||||
y: offsetY
|
||||
};
|
||||
|
||||
var zoomOptions = chartInstance.$zoom._options.zoom;
|
||||
var speedPercent = zoomOptions.speed;
|
||||
|
||||
if (event.deltaY >= 0) {
|
||||
speedPercent = -speedPercent;
|
||||
}
|
||||
doZoom(chartInstance, 1 + speedPercent, 1 + speedPercent, center);
|
||||
|
||||
clearTimeout(_scrollTimeout);
|
||||
_scrollTimeout = setTimeout(function() {
|
||||
if (typeof zoomOptions.onZoomComplete === 'function') {
|
||||
zoomOptions.onZoomComplete({chart: chartInstance});
|
||||
}
|
||||
}, 250);
|
||||
};
|
||||
|
||||
if (Hammer) {
|
||||
var mc = new Hammer.Manager(node);
|
||||
mc.add(new Hammer.Pinch());
|
||||
mc.add(new Hammer.Pan({
|
||||
threshold: panThreshold
|
||||
}));
|
||||
|
||||
// Hammer reports the total scaling. We need the incremental amount
|
||||
var currentPinchScaling;
|
||||
var handlePinch = function(e) {
|
||||
var diff = 1 / (currentPinchScaling) * e.scale;
|
||||
var rect = e.target.getBoundingClientRect();
|
||||
var offsetX = e.center.x - rect.left;
|
||||
var offsetY = e.center.y - rect.top;
|
||||
var center = {
|
||||
x: offsetX,
|
||||
y: offsetY
|
||||
};
|
||||
|
||||
// fingers position difference
|
||||
var x = Math.abs(e.pointers[0].clientX - e.pointers[1].clientX);
|
||||
var y = Math.abs(e.pointers[0].clientY - e.pointers[1].clientY);
|
||||
|
||||
// diagonal fingers will change both (xy) axes
|
||||
var p = x / y;
|
||||
var xy;
|
||||
if (p > 0.3 && p < 1.7) {
|
||||
xy = 'xy';
|
||||
} else if (x > y) {
|
||||
xy = 'x'; // x axis
|
||||
} else {
|
||||
xy = 'y'; // y axis
|
||||
}
|
||||
|
||||
doZoom(chartInstance, diff, diff, center, xy);
|
||||
|
||||
var zoomOptions = chartInstance.$zoom._options.zoom;
|
||||
if (typeof zoomOptions.onZoomComplete === 'function') {
|
||||
zoomOptions.onZoomComplete({chart: chartInstance});
|
||||
}
|
||||
|
||||
// Keep track of overall scale
|
||||
currentPinchScaling = e.scale;
|
||||
};
|
||||
|
||||
mc.on('pinchstart', function() {
|
||||
currentPinchScaling = 1; // reset tracker
|
||||
});
|
||||
mc.on('pinch', handlePinch);
|
||||
mc.on('pinchend', function(e) {
|
||||
handlePinch(e);
|
||||
currentPinchScaling = null; // reset
|
||||
zoomNS.zoomCumulativeDelta = 0;
|
||||
});
|
||||
|
||||
var currentDeltaX = null;
|
||||
var currentDeltaY = null;
|
||||
var panning = false;
|
||||
var handlePan = function(e) {
|
||||
if (currentDeltaX !== null && currentDeltaY !== null) {
|
||||
panning = true;
|
||||
var deltaX = e.deltaX - currentDeltaX;
|
||||
var deltaY = e.deltaY - currentDeltaY;
|
||||
currentDeltaX = e.deltaX;
|
||||
currentDeltaY = e.deltaY;
|
||||
doPan(chartInstance, deltaX, deltaY);
|
||||
}
|
||||
};
|
||||
|
||||
mc.on('panstart', function(e) {
|
||||
currentDeltaX = 0;
|
||||
currentDeltaY = 0;
|
||||
handlePan(e);
|
||||
});
|
||||
mc.on('panmove', handlePan);
|
||||
mc.on('panend', function() {
|
||||
currentDeltaX = null;
|
||||
currentDeltaY = null;
|
||||
zoomNS.panCumulativeDelta = 0;
|
||||
setTimeout(function() {
|
||||
panning = false;
|
||||
}, 500);
|
||||
|
||||
var panOptions = chartInstance.$zoom._options.pan;
|
||||
if (typeof panOptions.onPanComplete === 'function') {
|
||||
panOptions.onPanComplete({chart: chartInstance});
|
||||
}
|
||||
});
|
||||
|
||||
chartInstance.$zoom._ghostClickHandler = function(e) {
|
||||
if (panning && e.cancelable) {
|
||||
e.stopImmediatePropagation();
|
||||
e.preventDefault();
|
||||
}
|
||||
};
|
||||
node.addEventListener('click', chartInstance.$zoom._ghostClickHandler);
|
||||
|
||||
chartInstance._mc = mc;
|
||||
}
|
||||
},
|
||||
|
||||
beforeDatasetsDraw: function(chartInstance) {
|
||||
var ctx = chartInstance.ctx;
|
||||
|
||||
if (chartInstance.$zoom._dragZoomEnd) {
|
||||
var xAxis = getXAxis(chartInstance);
|
||||
var yAxis = getYAxis(chartInstance);
|
||||
var beginPoint = chartInstance.$zoom._dragZoomStart;
|
||||
var endPoint = chartInstance.$zoom._dragZoomEnd;
|
||||
|
||||
var startX = xAxis.left;
|
||||
var endX = xAxis.right;
|
||||
var startY = yAxis.top;
|
||||
var endY = yAxis.bottom;
|
||||
|
||||
if (directionEnabled(chartInstance.$zoom._options.zoom.mode, 'x', chartInstance)) {
|
||||
var offsetX = beginPoint.target.getBoundingClientRect().left;
|
||||
startX = Math.min(beginPoint.clientX, endPoint.clientX) - offsetX;
|
||||
endX = Math.max(beginPoint.clientX, endPoint.clientX) - offsetX;
|
||||
}
|
||||
|
||||
if (directionEnabled(chartInstance.$zoom._options.zoom.mode, 'y', chartInstance)) {
|
||||
var offsetY = beginPoint.target.getBoundingClientRect().top;
|
||||
startY = Math.min(beginPoint.clientY, endPoint.clientY) - offsetY;
|
||||
endY = Math.max(beginPoint.clientY, endPoint.clientY) - offsetY;
|
||||
}
|
||||
|
||||
var rectWidth = endX - startX;
|
||||
var rectHeight = endY - startY;
|
||||
var dragOptions = chartInstance.$zoom._options.zoom.drag;
|
||||
|
||||
ctx.save();
|
||||
ctx.beginPath();
|
||||
ctx.fillStyle = dragOptions.backgroundColor || 'rgba(225,225,225,0.3)';
|
||||
ctx.fillRect(startX, startY, rectWidth, rectHeight);
|
||||
|
||||
if (dragOptions.borderWidth > 0) {
|
||||
ctx.lineWidth = dragOptions.borderWidth;
|
||||
ctx.strokeStyle = dragOptions.borderColor || 'rgba(225,225,225)';
|
||||
ctx.strokeRect(startX, startY, rectWidth, rectHeight);
|
||||
}
|
||||
ctx.restore();
|
||||
}
|
||||
},
|
||||
|
||||
destroy: function(chartInstance) {
|
||||
if (!chartInstance.$zoom) {
|
||||
return;
|
||||
}
|
||||
var props = chartInstance.$zoom;
|
||||
var node = props._node;
|
||||
|
||||
node.removeEventListener('mousedown', props._mouseDownHandler);
|
||||
node.removeEventListener('mousemove', props._mouseMoveHandler);
|
||||
node.ownerDocument.removeEventListener('mouseup', props._mouseUpHandler);
|
||||
node.removeEventListener('wheel', props._wheelHandler);
|
||||
node.removeEventListener('click', props._ghostClickHandler);
|
||||
|
||||
delete chartInstance.$zoom;
|
||||
|
||||
var mc = chartInstance._mc;
|
||||
if (mc) {
|
||||
mc.remove('pinchstart');
|
||||
mc.remove('pinch');
|
||||
mc.remove('pinchend');
|
||||
mc.remove('panstart');
|
||||
mc.remove('pan');
|
||||
mc.remove('panend');
|
||||
mc.destroy();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Chart.register(zoomPlugin);
|
||||
export default zoomPlugin;
|
20
client/externalFiles/chartjs-zoom ticks.js
Normal file
20
client/externalFiles/chartjs-zoom ticks.js
Normal file
File diff suppressed because one or more lines are too long
20
client/externalFiles/chartjs-zoom.js
Normal file
20
client/externalFiles/chartjs-zoom.js
Normal file
File diff suppressed because one or more lines are too long
20
client/externalFiles/chartjs-zoom_orig.js
Normal file
20
client/externalFiles/chartjs-zoom_orig.js
Normal file
File diff suppressed because one or more lines are too long
8
client/externalFiles/d3.min.js
vendored
Normal file
8
client/externalFiles/d3.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
541
client/externalFiles/eventsource.js
Normal file
541
client/externalFiles/eventsource.js
Normal file
@ -0,0 +1,541 @@
|
||||
/** @license
|
||||
* eventsource.js
|
||||
* Available under MIT License (MIT)
|
||||
* https://github.com/Yaffle/EventSource/
|
||||
*/
|
||||
|
||||
/*jslint indent: 2, vars: true, plusplus: true */
|
||||
/*global setTimeout, clearTimeout */
|
||||
|
||||
(function (global) {
|
||||
"use strict";
|
||||
|
||||
var setTimeout = global.setTimeout;
|
||||
var clearTimeout = global.clearTimeout;
|
||||
|
||||
function Map() {
|
||||
this.data = {};
|
||||
}
|
||||
|
||||
Map.prototype.get = function (key) {
|
||||
return this.data[key + "~"];
|
||||
};
|
||||
Map.prototype.set = function (key, value) {
|
||||
this.data[key + "~"] = value;
|
||||
};
|
||||
Map.prototype["delete"] = function (key) {
|
||||
delete this.data[key + "~"];
|
||||
};
|
||||
|
||||
function EventTarget() {
|
||||
this.listeners = new Map();
|
||||
}
|
||||
|
||||
function throwError(e) {
|
||||
setTimeout(function () {
|
||||
throw e;
|
||||
}, 0);
|
||||
}
|
||||
|
||||
EventTarget.prototype.dispatchEvent = function (event) {
|
||||
event.target = this;
|
||||
var type = event.type.toString();
|
||||
var listeners = this.listeners;
|
||||
var typeListeners = listeners.get(type);
|
||||
if (typeListeners == undefined) {
|
||||
return;
|
||||
}
|
||||
var length = typeListeners.length;
|
||||
var i = -1;
|
||||
var listener = undefined;
|
||||
while (++i < length) {
|
||||
listener = typeListeners[i];
|
||||
try {
|
||||
listener.call(this, event);
|
||||
} catch (e) {
|
||||
throwError(e);
|
||||
}
|
||||
}
|
||||
};
|
||||
EventTarget.prototype.addEventListener = function (type, callback) {
|
||||
type = type.toString();
|
||||
var listeners = this.listeners;
|
||||
var typeListeners = listeners.get(type);
|
||||
if (typeListeners == undefined) {
|
||||
typeListeners = [];
|
||||
listeners.set(type, typeListeners);
|
||||
}
|
||||
var i = typeListeners.length;
|
||||
while (--i >= 0) {
|
||||
if (typeListeners[i] === callback) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
typeListeners.push(callback);
|
||||
};
|
||||
EventTarget.prototype.removeEventListener = function (type, callback) {
|
||||
type = type.toString();
|
||||
var listeners = this.listeners;
|
||||
var typeListeners = listeners.get(type);
|
||||
if (typeListeners == undefined) {
|
||||
return;
|
||||
}
|
||||
var length = typeListeners.length;
|
||||
var filtered = [];
|
||||
var i = -1;
|
||||
while (++i < length) {
|
||||
if (typeListeners[i] !== callback) {
|
||||
filtered.push(typeListeners[i]);
|
||||
}
|
||||
}
|
||||
if (filtered.length === 0) {
|
||||
listeners["delete"](type);
|
||||
} else {
|
||||
listeners.set(type, filtered);
|
||||
}
|
||||
};
|
||||
|
||||
function Event(type) {
|
||||
this.type = type;
|
||||
this.target = undefined;
|
||||
}
|
||||
|
||||
function MessageEvent(type, options) {
|
||||
Event.call(this, type);
|
||||
this.data = options.data;
|
||||
this.lastEventId = options.lastEventId;
|
||||
}
|
||||
|
||||
MessageEvent.prototype = Event.prototype;
|
||||
|
||||
var XHR = global.XMLHttpRequest;
|
||||
var XDR = global.XDomainRequest;
|
||||
var isCORSSupported = XHR != undefined && (new XHR()).withCredentials != undefined;
|
||||
var Transport = isCORSSupported || (XHR != undefined && XDR == undefined) ? XHR : XDR;
|
||||
|
||||
var WAITING = -1;
|
||||
var CONNECTING = 0;
|
||||
var OPEN = 1;
|
||||
var CLOSED = 2;
|
||||
var AFTER_CR = 3;
|
||||
var FIELD_START = 4;
|
||||
var FIELD = 5;
|
||||
var VALUE_START = 6;
|
||||
var VALUE = 7;
|
||||
var contentTypeRegExp = /^text\/event\-stream;?(\s*charset\=utf\-8)?$/i;
|
||||
|
||||
var MINIMUM_DURATION = 1000;
|
||||
var MAXIMUM_DURATION = 18000000;
|
||||
|
||||
function getDuration(value, def) {
|
||||
var n = value;
|
||||
if (n !== n) {
|
||||
n = def;
|
||||
}
|
||||
return (n < MINIMUM_DURATION ? MINIMUM_DURATION : (n > MAXIMUM_DURATION ? MAXIMUM_DURATION : n));
|
||||
}
|
||||
|
||||
function fire(that, f, event) {
|
||||
try {
|
||||
if (typeof f === "function") {
|
||||
f.call(that, event);
|
||||
}
|
||||
} catch (e) {
|
||||
throwError(e);
|
||||
}
|
||||
}
|
||||
|
||||
function EventSource(url, options) {
|
||||
url = url.toString();
|
||||
|
||||
var withCredentials = isCORSSupported && options != undefined && Boolean(options.withCredentials);
|
||||
var initialRetry = getDuration(1000, 0);
|
||||
var heartbeatTimeout = getDuration(45000, 0);
|
||||
|
||||
var lastEventId = "";
|
||||
var that = this;
|
||||
var retry = initialRetry;
|
||||
var wasActivity = false;
|
||||
var CurrentTransport = options != undefined && options.Transport != undefined ? options.Transport : Transport;
|
||||
var xhr = new CurrentTransport();
|
||||
var timeout = 0;
|
||||
var timeout0 = 0;
|
||||
var charOffset = 0;
|
||||
var currentState = WAITING;
|
||||
var dataBuffer = [];
|
||||
var lastEventIdBuffer = "";
|
||||
var eventTypeBuffer = "";
|
||||
var onTimeout = undefined;
|
||||
|
||||
var state = FIELD_START;
|
||||
var field = "";
|
||||
var value = "";
|
||||
|
||||
function close() {
|
||||
currentState = CLOSED;
|
||||
if (xhr != undefined) {
|
||||
xhr.abort();
|
||||
xhr = undefined;
|
||||
}
|
||||
if (timeout !== 0) {
|
||||
clearTimeout(timeout);
|
||||
timeout = 0;
|
||||
}
|
||||
if (timeout0 !== 0) {
|
||||
clearTimeout(timeout0);
|
||||
timeout0 = 0;
|
||||
}
|
||||
that.readyState = CLOSED;
|
||||
}
|
||||
|
||||
function onEvent(type) {
|
||||
var responseText = "";
|
||||
if (currentState === OPEN || currentState === CONNECTING) {
|
||||
try {
|
||||
responseText = xhr.responseText;
|
||||
} catch (error) {
|
||||
// IE 8 - 9 with XMLHttpRequest
|
||||
}
|
||||
}
|
||||
var event = undefined;
|
||||
var isWrongStatusCodeOrContentType = false;
|
||||
|
||||
if (currentState === CONNECTING) {
|
||||
var status = 0;
|
||||
var statusText = "";
|
||||
var contentType = undefined;
|
||||
if (!("contentType" in xhr)) {
|
||||
try {
|
||||
status = xhr.status;
|
||||
statusText = xhr.statusText;
|
||||
contentType = xhr.getResponseHeader("Content-Type");
|
||||
} catch (error) {
|
||||
// https://bugs.webkit.org/show_bug.cgi?id=29121
|
||||
status = 0;
|
||||
statusText = "";
|
||||
contentType = undefined;
|
||||
// FF < 14, WebKit
|
||||
// https://bugs.webkit.org/show_bug.cgi?id=29658
|
||||
// https://bugs.webkit.org/show_bug.cgi?id=77854
|
||||
}
|
||||
} else if (type !== "" && type !== "error") {
|
||||
status = 200;
|
||||
statusText = "OK";
|
||||
contentType = xhr.contentType;
|
||||
}
|
||||
if (contentType == undefined) {
|
||||
contentType = "";
|
||||
}
|
||||
if (status === 0 && statusText === "" && type === "load" && responseText !== "") {
|
||||
status = 200;
|
||||
statusText = "OK";
|
||||
if (contentType === "") { // Opera 12
|
||||
var tmp = (/^data\:([^,]*?)(?:;base64)?,[\S]*$/).exec(url);
|
||||
if (tmp != undefined) {
|
||||
contentType = tmp[1];
|
||||
}
|
||||
}
|
||||
}
|
||||
if (status === 200 && contentTypeRegExp.test(contentType)) {
|
||||
currentState = OPEN;
|
||||
wasActivity = true;
|
||||
retry = initialRetry;
|
||||
that.readyState = OPEN;
|
||||
event = new Event("open");
|
||||
that.dispatchEvent(event);
|
||||
fire(that, that.onopen, event);
|
||||
if (currentState === CLOSED) {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
// Opera 12
|
||||
if (status !== 0 && (status !== 200 || contentType !== "")) {
|
||||
var message = "";
|
||||
if (status !== 200) {
|
||||
message = "EventSource's response has a status " + status + " " + statusText.replace(/\s+/g, " ") + " that is not 200. Aborting the connection.";
|
||||
} else {
|
||||
message = "EventSource's response has a Content-Type specifying an unsupported type: " + contentType.replace(/\s+/g, " ") + ". Aborting the connection.";
|
||||
}
|
||||
setTimeout(function () {
|
||||
throw new Error(message);
|
||||
}, 0);
|
||||
isWrongStatusCodeOrContentType = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (currentState === OPEN) {
|
||||
if (responseText.length > charOffset) {
|
||||
wasActivity = true;
|
||||
}
|
||||
var i = charOffset - 1;
|
||||
var length = responseText.length;
|
||||
var c = "\n";
|
||||
while (++i < length) {
|
||||
c = responseText.charAt(i);
|
||||
if (state === AFTER_CR && c === "\n") {
|
||||
state = FIELD_START;
|
||||
} else {
|
||||
if (state === AFTER_CR) {
|
||||
state = FIELD_START;
|
||||
}
|
||||
if (c === "\r" || c === "\n") {
|
||||
if (field === "data") {
|
||||
dataBuffer.push(value);
|
||||
} else if (field === "id") {
|
||||
lastEventIdBuffer = value;
|
||||
} else if (field === "event") {
|
||||
eventTypeBuffer = value;
|
||||
} else if (field === "retry") {
|
||||
initialRetry = getDuration(Number(value), initialRetry);
|
||||
retry = initialRetry;
|
||||
} else if (field === "heartbeatTimeout") {
|
||||
heartbeatTimeout = getDuration(Number(value), heartbeatTimeout);
|
||||
if (timeout !== 0) {
|
||||
clearTimeout(timeout);
|
||||
timeout = setTimeout(onTimeout, heartbeatTimeout);
|
||||
}
|
||||
}
|
||||
value = "";
|
||||
field = "";
|
||||
if (state === FIELD_START) {
|
||||
if (dataBuffer.length !== 0) {
|
||||
lastEventId = lastEventIdBuffer;
|
||||
if (eventTypeBuffer === "") {
|
||||
eventTypeBuffer = "message";
|
||||
}
|
||||
event = new MessageEvent(eventTypeBuffer, {
|
||||
data: dataBuffer.join("\n"),
|
||||
lastEventId: lastEventIdBuffer
|
||||
});
|
||||
that.dispatchEvent(event);
|
||||
if (eventTypeBuffer === "message") {
|
||||
fire(that, that.onmessage, event);
|
||||
}
|
||||
if (currentState === CLOSED) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
dataBuffer.length = 0;
|
||||
eventTypeBuffer = "";
|
||||
}
|
||||
state = c === "\r" ? AFTER_CR : FIELD_START;
|
||||
} else {
|
||||
if (state === FIELD_START) {
|
||||
state = FIELD;
|
||||
}
|
||||
if (state === FIELD) {
|
||||
if (c === ":") {
|
||||
state = VALUE_START;
|
||||
} else {
|
||||
field += c;
|
||||
}
|
||||
} else if (state === VALUE_START) {
|
||||
if (c !== " ") {
|
||||
value += c;
|
||||
}
|
||||
state = VALUE;
|
||||
} else if (state === VALUE) {
|
||||
value += c;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
charOffset = length;
|
||||
}
|
||||
|
||||
if ((currentState === OPEN || currentState === CONNECTING) &&
|
||||
(type === "load" || type === "error" || isWrongStatusCodeOrContentType || (charOffset > 1024 * 1024) || (timeout === 0 && !wasActivity))) {
|
||||
if (isWrongStatusCodeOrContentType) {
|
||||
close();
|
||||
} else {
|
||||
if (type === "" && timeout === 0 && !wasActivity) {
|
||||
setTimeout(function () {
|
||||
throw new Error("No activity within " + heartbeatTimeout + " milliseconds. Reconnecting.");
|
||||
}, 0);
|
||||
}
|
||||
currentState = WAITING;
|
||||
xhr.abort();
|
||||
if (timeout !== 0) {
|
||||
clearTimeout(timeout);
|
||||
timeout = 0;
|
||||
}
|
||||
if (retry > initialRetry * 16) {
|
||||
retry = initialRetry * 16;
|
||||
}
|
||||
if (retry > MAXIMUM_DURATION) {
|
||||
retry = MAXIMUM_DURATION;
|
||||
}
|
||||
timeout = setTimeout(onTimeout, retry);
|
||||
retry = retry * 2 + 1;
|
||||
|
||||
that.readyState = CONNECTING;
|
||||
}
|
||||
event = new Event("error");
|
||||
that.dispatchEvent(event);
|
||||
fire(that, that.onerror, event);
|
||||
} else {
|
||||
if (timeout === 0) {
|
||||
wasActivity = false;
|
||||
timeout = setTimeout(onTimeout, heartbeatTimeout);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function onProgress() {
|
||||
onEvent("progress");
|
||||
}
|
||||
|
||||
function onLoad() {
|
||||
onEvent("load");
|
||||
}
|
||||
|
||||
function onError() {
|
||||
onEvent("error");
|
||||
}
|
||||
|
||||
function onReadyStateChange() {
|
||||
if (xhr.readyState === 4) {
|
||||
if (xhr.status === 0) {
|
||||
onEvent("error");
|
||||
} else {
|
||||
onEvent("load");
|
||||
}
|
||||
} else {
|
||||
onEvent("progress");
|
||||
}
|
||||
}
|
||||
|
||||
if (("readyState" in xhr) && global.opera != undefined) {
|
||||
// workaround for Opera issue with "progress" events
|
||||
timeout0 = setTimeout(function f() {
|
||||
if (xhr.readyState === 3) {
|
||||
onEvent("progress");
|
||||
}
|
||||
timeout0 = setTimeout(f, 500);
|
||||
}, 0);
|
||||
}
|
||||
|
||||
onTimeout = function () {
|
||||
timeout = 0;
|
||||
if (currentState !== WAITING) {
|
||||
onEvent("");
|
||||
return;
|
||||
}
|
||||
|
||||
// loading indicator in Safari, Chrome < 14
|
||||
// loading indicator in Firefox
|
||||
// https://bugzilla.mozilla.org/show_bug.cgi?id=736723
|
||||
if ((!("ontimeout" in xhr) || ("sendAsBinary" in xhr) || ("mozAnon" in xhr)) && global.document != undefined && global.document.readyState != undefined && global.document.readyState !== "complete") {
|
||||
timeout = setTimeout(onTimeout, 4);
|
||||
return;
|
||||
}
|
||||
|
||||
// XDomainRequest#abort removes onprogress, onerror, onload
|
||||
xhr.onload = onLoad;
|
||||
xhr.onerror = onError;
|
||||
|
||||
if ("onabort" in xhr) {
|
||||
// improper fix to match Firefox behaviour, but it is better than just ignore abort
|
||||
// see https://bugzilla.mozilla.org/show_bug.cgi?id=768596
|
||||
// https://bugzilla.mozilla.org/show_bug.cgi?id=880200
|
||||
// https://code.google.com/p/chromium/issues/detail?id=153570
|
||||
xhr.onabort = onError;
|
||||
}
|
||||
|
||||
if ("onprogress" in xhr) {
|
||||
xhr.onprogress = onProgress;
|
||||
}
|
||||
// IE 8-9 (XMLHTTPRequest)
|
||||
// Firefox 3.5 - 3.6 - ? < 9.0
|
||||
// onprogress is not fired sometimes or delayed
|
||||
// see also #64
|
||||
if ("onreadystatechange" in xhr) {
|
||||
xhr.onreadystatechange = onReadyStateChange;
|
||||
}
|
||||
|
||||
wasActivity = false;
|
||||
timeout = setTimeout(onTimeout, heartbeatTimeout);
|
||||
|
||||
charOffset = 0;
|
||||
currentState = CONNECTING;
|
||||
dataBuffer.length = 0;
|
||||
eventTypeBuffer = "";
|
||||
lastEventIdBuffer = lastEventId;
|
||||
value = "";
|
||||
field = "";
|
||||
state = FIELD_START;
|
||||
|
||||
var s = url.slice(0, 5);
|
||||
if (s !== "data:" && s !== "blob:") {
|
||||
s = url + ((url.indexOf("?", 0) === -1 ? "?" : "&") + "lastEventId=" + encodeURIComponent(lastEventId) + "&r=" + (Math.random() + 1).toString().slice(2));
|
||||
} else {
|
||||
s = url;
|
||||
}
|
||||
xhr.open("GET", s, true);
|
||||
|
||||
if ("withCredentials" in xhr) {
|
||||
// withCredentials should be set after "open" for Safari and Chrome (< 19 ?)
|
||||
xhr.withCredentials = withCredentials;
|
||||
}
|
||||
|
||||
if ("responseType" in xhr) {
|
||||
xhr.responseType = "text";
|
||||
}
|
||||
|
||||
if ("setRequestHeader" in xhr) {
|
||||
// Request header field Cache-Control is not allowed by Access-Control-Allow-Headers.
|
||||
// "Cache-control: no-cache" are not honored in Chrome and Firefox
|
||||
// https://bugzilla.mozilla.org/show_bug.cgi?id=428916
|
||||
//xhr.setRequestHeader("Cache-Control", "no-cache");
|
||||
xhr.setRequestHeader("Accept", "text/event-stream");
|
||||
// Request header field Last-Event-ID is not allowed by Access-Control-Allow-Headers.
|
||||
//xhr.setRequestHeader("Last-Event-ID", lastEventId);
|
||||
}
|
||||
|
||||
xhr.send(undefined);
|
||||
};
|
||||
|
||||
EventTarget.call(this);
|
||||
this.close = close;
|
||||
this.url = url;
|
||||
this.readyState = CONNECTING;
|
||||
this.withCredentials = withCredentials;
|
||||
|
||||
this.onopen = undefined;
|
||||
this.onmessage = undefined;
|
||||
this.onerror = undefined;
|
||||
|
||||
onTimeout();
|
||||
}
|
||||
|
||||
function F() {
|
||||
this.CONNECTING = CONNECTING;
|
||||
this.OPEN = OPEN;
|
||||
this.CLOSED = CLOSED;
|
||||
}
|
||||
F.prototype = EventTarget.prototype;
|
||||
|
||||
EventSource.prototype = new F();
|
||||
F.call(EventSource);
|
||||
if (isCORSSupported) {
|
||||
EventSource.prototype.withCredentials = undefined;
|
||||
}
|
||||
|
||||
var isEventSourceSupported = function () {
|
||||
// Opera 12 fails this test, but this is fine.
|
||||
return global.EventSource != undefined && ("withCredentials" in global.EventSource.prototype);
|
||||
};
|
||||
|
||||
if (Transport != undefined && (global.EventSource == undefined || (isCORSSupported && !isEventSourceSupported()))) {
|
||||
// Why replace a native EventSource ?
|
||||
// https://bugzilla.mozilla.org/show_bug.cgi?id=444328
|
||||
// https://bugzilla.mozilla.org/show_bug.cgi?id=831392
|
||||
// https://code.google.com/p/chromium/issues/detail?id=260144
|
||||
// https://code.google.com/p/chromium/issues/detail?id=225654
|
||||
// ...
|
||||
global.NativeEventSource = global.EventSource;
|
||||
global.EventSource = EventSource;
|
||||
}
|
||||
|
||||
}(typeof window !== 'undefined' ? window : this));
|
6
client/externalFiles/hammer.js
Normal file
6
client/externalFiles/hammer.js
Normal file
File diff suppressed because one or more lines are too long
9041
client/externalFiles/mjs_plot_0_3_n.js
Normal file
9041
client/externalFiles/mjs_plot_0_3_n.js
Normal file
File diff suppressed because it is too large
Load Diff
15
client/externalFiles/oldswiper.min.css
vendored
Normal file
15
client/externalFiles/oldswiper.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
18
client/externalFiles/oldswiper.min.js
vendored
Normal file
18
client/externalFiles/oldswiper.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
576
client/externalFiles/swiper.css
Normal file
576
client/externalFiles/swiper.css
Normal file
@ -0,0 +1,576 @@
|
||||
/**
|
||||
* Swiper 3.4.0
|
||||
* Most modern mobile touch slider and framework with hardware accelerated transitions
|
||||
*
|
||||
* http://www.idangero.us/swiper/
|
||||
*
|
||||
* Copyright 2016, Vladimir Kharlampidi
|
||||
* The iDangero.us
|
||||
* http://www.idangero.us/
|
||||
*
|
||||
* Licensed under MIT
|
||||
*
|
||||
* Released on: October 16, 2016
|
||||
*/
|
||||
.swiper-container {
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
/* Fix of Webkit flickering */
|
||||
z-index: 1;
|
||||
}
|
||||
.swiper-container-no-flexbox .swiper-slide {
|
||||
float: left;
|
||||
}
|
||||
.swiper-container-vertical > .swiper-wrapper {
|
||||
-webkit-box-orient: vertical;
|
||||
-moz-box-orient: vertical;
|
||||
-ms-flex-direction: column;
|
||||
-webkit-flex-direction: column;
|
||||
flex-direction: column;
|
||||
}
|
||||
.swiper-wrapper {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
z-index: 1;
|
||||
display: -webkit-box;
|
||||
display: -moz-box;
|
||||
display: -ms-flexbox;
|
||||
display: -webkit-flex;
|
||||
display: flex;
|
||||
-webkit-transition-property: -webkit-transform;
|
||||
-moz-transition-property: -moz-transform;
|
||||
-o-transition-property: -o-transform;
|
||||
-ms-transition-property: -ms-transform;
|
||||
transition-property: transform;
|
||||
-webkit-box-sizing: content-box;
|
||||
-moz-box-sizing: content-box;
|
||||
box-sizing: content-box;
|
||||
}
|
||||
.swiper-container-android .swiper-slide,
|
||||
.swiper-wrapper {
|
||||
-webkit-transform: translate3d(0px, 0, 0);
|
||||
-moz-transform: translate3d(0px, 0, 0);
|
||||
-o-transform: translate(0px, 0px);
|
||||
-ms-transform: translate3d(0px, 0, 0);
|
||||
transform: translate3d(0px, 0, 0);
|
||||
}
|
||||
.swiper-container-multirow > .swiper-wrapper {
|
||||
-webkit-box-lines: multiple;
|
||||
-moz-box-lines: multiple;
|
||||
-ms-flex-wrap: wrap;
|
||||
-webkit-flex-wrap: wrap;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
.swiper-container-free-mode > .swiper-wrapper {
|
||||
-webkit-transition-timing-function: ease-out;
|
||||
-moz-transition-timing-function: ease-out;
|
||||
-ms-transition-timing-function: ease-out;
|
||||
-o-transition-timing-function: ease-out;
|
||||
transition-timing-function: ease-out;
|
||||
margin: 0 auto;
|
||||
}
|
||||
.swiper-slide {
|
||||
-webkit-flex-shrink: 0;
|
||||
-ms-flex: 0 0 auto;
|
||||
flex-shrink: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: relative;
|
||||
}
|
||||
/* Auto Height */
|
||||
.swiper-container-autoheight,
|
||||
.swiper-container-autoheight .swiper-slide {
|
||||
height: auto;
|
||||
}
|
||||
.swiper-container-autoheight .swiper-wrapper {
|
||||
-webkit-box-align: start;
|
||||
-ms-flex-align: start;
|
||||
-webkit-align-items: flex-start;
|
||||
align-items: flex-start;
|
||||
-webkit-transition-property: -webkit-transform, height;
|
||||
-moz-transition-property: -moz-transform;
|
||||
-o-transition-property: -o-transform;
|
||||
-ms-transition-property: -ms-transform;
|
||||
transition-property: transform, height;
|
||||
}
|
||||
/* a11y */
|
||||
.swiper-container .swiper-notification {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
pointer-events: none;
|
||||
opacity: 0;
|
||||
z-index: -1000;
|
||||
}
|
||||
/* IE10 Windows Phone 8 Fixes */
|
||||
.swiper-wp8-horizontal {
|
||||
-ms-touch-action: pan-y;
|
||||
touch-action: pan-y;
|
||||
}
|
||||
.swiper-wp8-vertical {
|
||||
-ms-touch-action: pan-x;
|
||||
touch-action: pan-x;
|
||||
}
|
||||
/* Arrows */
|
||||
.swiper-button-prev,
|
||||
.swiper-button-next {
|
||||
position: absolute;
|
||||
top: 70%;
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
margin-top: -10px;
|
||||
z-index: 10;
|
||||
cursor: pointer;
|
||||
-moz-background-size: 27px 44px;
|
||||
-webkit-background-size: 27px 44px;
|
||||
background-size: 27px 44px;
|
||||
background-position: center;
|
||||
background-repeat: no-repeat;
|
||||
opacity: 0.6;
|
||||
}
|
||||
.swiper-button-prev.swiper-button-disabled,
|
||||
.swiper-button-next.swiper-button-disabled {
|
||||
opacity: 0.2;
|
||||
cursor: auto;
|
||||
pointer-events: none;
|
||||
}
|
||||
.swiper-button-prev,
|
||||
.swiper-container-rtl .swiper-button-next {
|
||||
background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20viewBox%3D'0%200%2027%2044'%3E%3Cpath%20d%3D'M0%2C22L22%2C0l2.1%2C2.1L4.2%2C22l19.9%2C19.9L22%2C44L0%2C22L0%2C22L0%2C22z'%20fill%3D'%23007aff'%2F%3E%3C%2Fsvg%3E");
|
||||
left: 10px;
|
||||
right: auto;
|
||||
}
|
||||
.swiper-button-prev.swiper-button-black,
|
||||
.swiper-container-rtl .swiper-button-next.swiper-button-black {
|
||||
background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20viewBox%3D'0%200%2027%2044'%3E%3Cpath%20d%3D'M0%2C22L22%2C0l2.1%2C2.1L4.2%2C22l19.9%2C19.9L22%2C44L0%2C22L0%2C22L0%2C22z'%20fill%3D'%23000000'%2F%3E%3C%2Fsvg%3E");
|
||||
}
|
||||
.swiper-button-prev.swiper-button-white,
|
||||
.swiper-container-rtl .swiper-button-next.swiper-button-white {
|
||||
background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20viewBox%3D'0%200%2027%2044'%3E%3Cpath%20d%3D'M0%2C22L22%2C0l2.1%2C2.1L4.2%2C22l19.9%2C19.9L22%2C44L0%2C22L0%2C22L0%2C22z'%20fill%3D'%23ffffff'%2F%3E%3C%2Fsvg%3E");
|
||||
}
|
||||
.swiper-button-next,
|
||||
.swiper-container-rtl .swiper-button-prev {
|
||||
background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20viewBox%3D'0%200%2027%2044'%3E%3Cpath%20d%3D'M27%2C22L27%2C22L5%2C44l-2.1-2.1L22.8%2C22L2.9%2C2.1L5%2C0L27%2C22L27%2C22z'%20fill%3D'%23007aff'%2F%3E%3C%2Fsvg%3E");
|
||||
right: 10px;
|
||||
left: auto;
|
||||
}
|
||||
.swiper-button-next.swiper-button-black,
|
||||
.swiper-container-rtl .swiper-button-prev.swiper-button-black {
|
||||
background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20viewBox%3D'0%200%2027%2044'%3E%3Cpath%20d%3D'M27%2C22L27%2C22L5%2C44l-2.1-2.1L22.8%2C22L2.9%2C2.1L5%2C0L27%2C22L27%2C22z'%20fill%3D'%23000000'%2F%3E%3C%2Fsvg%3E");
|
||||
}
|
||||
.swiper-button-next.swiper-button-white,
|
||||
.swiper-container-rtl .swiper-button-prev.swiper-button-white {
|
||||
background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20viewBox%3D'0%200%2027%2044'%3E%3Cpath%20d%3D'M27%2C22L27%2C22L5%2C44l-2.1-2.1L22.8%2C22L2.9%2C2.1L5%2C0L27%2C22L27%2C22z'%20fill%3D'%23ffffff'%2F%3E%3C%2Fsvg%3E");
|
||||
}
|
||||
/* Pagination Styles */
|
||||
.swiper-pagination {
|
||||
position: absolute;
|
||||
text-align: center;
|
||||
-webkit-transition: 300ms;
|
||||
-moz-transition: 300ms;
|
||||
-o-transition: 300ms;
|
||||
transition: 300ms;
|
||||
-webkit-transform: translate3d(0, 0, 0);
|
||||
-ms-transform: translate3d(0, 0, 0);
|
||||
-o-transform: translate3d(0, 0, 0);
|
||||
transform: translate3d(0, 0, 0);
|
||||
z-index: 10;
|
||||
}
|
||||
.swiper-pagination.swiper-pagination-hidden {
|
||||
opacity: 0;
|
||||
}
|
||||
/* Common Styles */
|
||||
.swiper-pagination-fraction,
|
||||
.swiper-pagination-custom,
|
||||
.swiper-container-horizontal > .swiper-pagination-bullets {
|
||||
bottom: 10px;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
}
|
||||
/* Bullets */
|
||||
.swiper-pagination-bullet {
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
display: inline-block;
|
||||
border-radius: 100%;
|
||||
background: #000;
|
||||
opacity: 0.2;
|
||||
}
|
||||
button.swiper-pagination-bullet {
|
||||
border: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-shadow: none;
|
||||
-moz-appearance: none;
|
||||
-ms-appearance: none;
|
||||
-webkit-appearance: none;
|
||||
appearance: none;
|
||||
}
|
||||
.swiper-pagination-clickable .swiper-pagination-bullet {
|
||||
cursor: pointer;
|
||||
}
|
||||
.swiper-pagination-white .swiper-pagination-bullet {
|
||||
background: #fff;
|
||||
}
|
||||
.swiper-pagination-bullet-active {
|
||||
opacity: 1;
|
||||
background: #007aff;
|
||||
}
|
||||
.swiper-pagination-white .swiper-pagination-bullet-active {
|
||||
background: #fff;
|
||||
}
|
||||
.swiper-pagination-black .swiper-pagination-bullet-active {
|
||||
background: #000;
|
||||
}
|
||||
.swiper-container-vertical > .swiper-pagination-bullets {
|
||||
right: 10px;
|
||||
top: 50%;
|
||||
-webkit-transform: translate3d(0px, -50%, 0);
|
||||
-moz-transform: translate3d(0px, -50%, 0);
|
||||
-o-transform: translate(0px, -50%);
|
||||
-ms-transform: translate3d(0px, -50%, 0);
|
||||
transform: translate3d(0px, -50%, 0);
|
||||
}
|
||||
.swiper-container-vertical > .swiper-pagination-bullets .swiper-pagination-bullet {
|
||||
margin: 5px 0;
|
||||
display: block;
|
||||
}
|
||||
.swiper-container-horizontal > .swiper-pagination-bullets .swiper-pagination-bullet {
|
||||
margin: 0 5px;
|
||||
}
|
||||
/* Progress */
|
||||
.swiper-pagination-progress {
|
||||
background: rgba(0, 0, 0, 0.25);
|
||||
position: absolute;
|
||||
}
|
||||
.swiper-pagination-progress .swiper-pagination-progressbar {
|
||||
background: #007aff;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
-webkit-transform: scale(0);
|
||||
-ms-transform: scale(0);
|
||||
-o-transform: scale(0);
|
||||
transform: scale(0);
|
||||
-webkit-transform-origin: left top;
|
||||
-moz-transform-origin: left top;
|
||||
-ms-transform-origin: left top;
|
||||
-o-transform-origin: left top;
|
||||
transform-origin: left top;
|
||||
}
|
||||
.swiper-container-rtl .swiper-pagination-progress .swiper-pagination-progressbar {
|
||||
-webkit-transform-origin: right top;
|
||||
-moz-transform-origin: right top;
|
||||
-ms-transform-origin: right top;
|
||||
-o-transform-origin: right top;
|
||||
transform-origin: right top;
|
||||
}
|
||||
.swiper-container-horizontal > .swiper-pagination-progress {
|
||||
width: 100%;
|
||||
height: 4px;
|
||||
left: 0;
|
||||
top: 0;
|
||||
}
|
||||
.swiper-container-vertical > .swiper-pagination-progress {
|
||||
width: 4px;
|
||||
height: 100%;
|
||||
left: 0;
|
||||
top: 0;
|
||||
}
|
||||
.swiper-pagination-progress.swiper-pagination-white {
|
||||
background: rgba(255, 255, 255, 0.5);
|
||||
}
|
||||
.swiper-pagination-progress.swiper-pagination-white .swiper-pagination-progressbar {
|
||||
background: #fff;
|
||||
}
|
||||
.swiper-pagination-progress.swiper-pagination-black .swiper-pagination-progressbar {
|
||||
background: #000;
|
||||
}
|
||||
/* 3D Container */
|
||||
.swiper-container-3d {
|
||||
-webkit-perspective: 1200px;
|
||||
-moz-perspective: 1200px;
|
||||
-o-perspective: 1200px;
|
||||
perspective: 1200px;
|
||||
}
|
||||
.swiper-container-3d .swiper-wrapper,
|
||||
.swiper-container-3d .swiper-slide,
|
||||
.swiper-container-3d .swiper-slide-shadow-left,
|
||||
.swiper-container-3d .swiper-slide-shadow-right,
|
||||
.swiper-container-3d .swiper-slide-shadow-top,
|
||||
.swiper-container-3d .swiper-slide-shadow-bottom,
|
||||
.swiper-container-3d .swiper-cube-shadow {
|
||||
-webkit-transform-style: preserve-3d;
|
||||
-moz-transform-style: preserve-3d;
|
||||
-ms-transform-style: preserve-3d;
|
||||
transform-style: preserve-3d;
|
||||
}
|
||||
.swiper-container-3d .swiper-slide-shadow-left,
|
||||
.swiper-container-3d .swiper-slide-shadow-right,
|
||||
.swiper-container-3d .swiper-slide-shadow-top,
|
||||
.swiper-container-3d .swiper-slide-shadow-bottom {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
pointer-events: none;
|
||||
z-index: 10;
|
||||
}
|
||||
.swiper-container-3d .swiper-slide-shadow-left {
|
||||
background-image: -webkit-gradient(linear, left top, right top, from(rgba(0, 0, 0, 0.5)), to(rgba(0, 0, 0, 0)));
|
||||
/* Safari 4+, Chrome */
|
||||
background-image: -webkit-linear-gradient(right, rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0));
|
||||
/* Chrome 10+, Safari 5.1+, iOS 5+ */
|
||||
background-image: -moz-linear-gradient(right, rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0));
|
||||
/* Firefox 3.6-15 */
|
||||
background-image: -o-linear-gradient(right, rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0));
|
||||
/* Opera 11.10-12.00 */
|
||||
background-image: linear-gradient(to left, rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0));
|
||||
/* Firefox 16+, IE10, Opera 12.50+ */
|
||||
}
|
||||
.swiper-container-3d .swiper-slide-shadow-right {
|
||||
background-image: -webkit-gradient(linear, right top, left top, from(rgba(0, 0, 0, 0.5)), to(rgba(0, 0, 0, 0)));
|
||||
/* Safari 4+, Chrome */
|
||||
background-image: -webkit-linear-gradient(left, rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0));
|
||||
/* Chrome 10+, Safari 5.1+, iOS 5+ */
|
||||
background-image: -moz-linear-gradient(left, rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0));
|
||||
/* Firefox 3.6-15 */
|
||||
background-image: -o-linear-gradient(left, rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0));
|
||||
/* Opera 11.10-12.00 */
|
||||
background-image: linear-gradient(to right, rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0));
|
||||
/* Firefox 16+, IE10, Opera 12.50+ */
|
||||
}
|
||||
.swiper-container-3d .swiper-slide-shadow-top {
|
||||
background-image: -webkit-gradient(linear, left top, left bottom, from(rgba(0, 0, 0, 0.5)), to(rgba(0, 0, 0, 0)));
|
||||
/* Safari 4+, Chrome */
|
||||
background-image: -webkit-linear-gradient(bottom, rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0));
|
||||
/* Chrome 10+, Safari 5.1+, iOS 5+ */
|
||||
background-image: -moz-linear-gradient(bottom, rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0));
|
||||
/* Firefox 3.6-15 */
|
||||
background-image: -o-linear-gradient(bottom, rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0));
|
||||
/* Opera 11.10-12.00 */
|
||||
background-image: linear-gradient(to top, rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0));
|
||||
/* Firefox 16+, IE10, Opera 12.50+ */
|
||||
}
|
||||
.swiper-container-3d .swiper-slide-shadow-bottom {
|
||||
background-image: -webkit-gradient(linear, left bottom, left top, from(rgba(0, 0, 0, 0.5)), to(rgba(0, 0, 0, 0)));
|
||||
/* Safari 4+, Chrome */
|
||||
background-image: -webkit-linear-gradient(top, rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0));
|
||||
/* Chrome 10+, Safari 5.1+, iOS 5+ */
|
||||
background-image: -moz-linear-gradient(top, rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0));
|
||||
/* Firefox 3.6-15 */
|
||||
background-image: -o-linear-gradient(top, rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0));
|
||||
/* Opera 11.10-12.00 */
|
||||
background-image: linear-gradient(to bottom, rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0));
|
||||
/* Firefox 16+, IE10, Opera 12.50+ */
|
||||
}
|
||||
/* Coverflow */
|
||||
.swiper-container-coverflow .swiper-wrapper,
|
||||
.swiper-container-flip .swiper-wrapper {
|
||||
/* Windows 8 IE 10 fix */
|
||||
-ms-perspective: 1200px;
|
||||
}
|
||||
/* Cube + Flip */
|
||||
.swiper-container-cube,
|
||||
.swiper-container-flip {
|
||||
overflow: visible;
|
||||
}
|
||||
.swiper-container-cube .swiper-slide,
|
||||
.swiper-container-flip .swiper-slide {
|
||||
pointer-events: none;
|
||||
-webkit-backface-visibility: hidden;
|
||||
-moz-backface-visibility: hidden;
|
||||
-ms-backface-visibility: hidden;
|
||||
backface-visibility: hidden;
|
||||
z-index: 1;
|
||||
}
|
||||
.swiper-container-cube .swiper-slide .swiper-slide,
|
||||
.swiper-container-flip .swiper-slide .swiper-slide {
|
||||
pointer-events: none;
|
||||
}
|
||||
.swiper-container-cube .swiper-slide-active,
|
||||
.swiper-container-flip .swiper-slide-active,
|
||||
.swiper-container-cube .swiper-slide-active .swiper-slide-active,
|
||||
.swiper-container-flip .swiper-slide-active .swiper-slide-active {
|
||||
pointer-events: auto;
|
||||
}
|
||||
.swiper-container-cube .swiper-slide-shadow-top,
|
||||
.swiper-container-flip .swiper-slide-shadow-top,
|
||||
.swiper-container-cube .swiper-slide-shadow-bottom,
|
||||
.swiper-container-flip .swiper-slide-shadow-bottom,
|
||||
.swiper-container-cube .swiper-slide-shadow-left,
|
||||
.swiper-container-flip .swiper-slide-shadow-left,
|
||||
.swiper-container-cube .swiper-slide-shadow-right,
|
||||
.swiper-container-flip .swiper-slide-shadow-right {
|
||||
z-index: 0;
|
||||
-webkit-backface-visibility: hidden;
|
||||
-moz-backface-visibility: hidden;
|
||||
-ms-backface-visibility: hidden;
|
||||
backface-visibility: hidden;
|
||||
}
|
||||
/* Cube */
|
||||
.swiper-container-cube .swiper-slide {
|
||||
visibility: hidden;
|
||||
-webkit-transform-origin: 0 0;
|
||||
-moz-transform-origin: 0 0;
|
||||
-ms-transform-origin: 0 0;
|
||||
transform-origin: 0 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
.swiper-container-cube.swiper-container-rtl .swiper-slide {
|
||||
-webkit-transform-origin: 100% 0;
|
||||
-moz-transform-origin: 100% 0;
|
||||
-ms-transform-origin: 100% 0;
|
||||
transform-origin: 100% 0;
|
||||
}
|
||||
.swiper-container-cube .swiper-slide-active,
|
||||
.swiper-container-cube .swiper-slide-next,
|
||||
.swiper-container-cube .swiper-slide-prev,
|
||||
.swiper-container-cube .swiper-slide-next + .swiper-slide {
|
||||
pointer-events: auto;
|
||||
visibility: visible;
|
||||
}
|
||||
.swiper-container-cube .swiper-cube-shadow {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
bottom: 0px;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: #000;
|
||||
opacity: 0.6;
|
||||
-webkit-filter: blur(50px);
|
||||
filter: blur(50px);
|
||||
z-index: 0;
|
||||
}
|
||||
/* Fade */
|
||||
.swiper-container-fade.swiper-container-free-mode .swiper-slide {
|
||||
-webkit-transition-timing-function: ease-out;
|
||||
-moz-transition-timing-function: ease-out;
|
||||
-ms-transition-timing-function: ease-out;
|
||||
-o-transition-timing-function: ease-out;
|
||||
transition-timing-function: ease-out;
|
||||
}
|
||||
.swiper-container-fade .swiper-slide {
|
||||
pointer-events: none;
|
||||
-webkit-transition-property: opacity;
|
||||
-moz-transition-property: opacity;
|
||||
-o-transition-property: opacity;
|
||||
transition-property: opacity;
|
||||
}
|
||||
.swiper-container-fade .swiper-slide .swiper-slide {
|
||||
pointer-events: none;
|
||||
}
|
||||
.swiper-container-fade .swiper-slide-active,
|
||||
.swiper-container-fade .swiper-slide-active .swiper-slide-active {
|
||||
pointer-events: auto;
|
||||
}
|
||||
.swiper-zoom-container {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: -webkit-box;
|
||||
display: -moz-box;
|
||||
display: -ms-flexbox;
|
||||
display: -webkit-flex;
|
||||
display: flex;
|
||||
-webkit-box-pack: center;
|
||||
-moz-box-pack: center;
|
||||
-ms-flex-pack: center;
|
||||
-webkit-justify-content: center;
|
||||
justify-content: center;
|
||||
-webkit-box-align: center;
|
||||
-moz-box-align: center;
|
||||
-ms-flex-align: center;
|
||||
-webkit-align-items: center;
|
||||
align-items: center;
|
||||
text-align: center;
|
||||
}
|
||||
.swiper-zoom-container > img,
|
||||
.swiper-zoom-container > svg,
|
||||
.swiper-zoom-container > canvas {
|
||||
max-width: 100%;
|
||||
max-height: 100%;
|
||||
object-fit: contain;
|
||||
}
|
||||
/* Scrollbar */
|
||||
.swiper-scrollbar {
|
||||
border-radius: 10px;
|
||||
position: relative;
|
||||
-ms-touch-action: none;
|
||||
background: rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
.swiper-container-horizontal > .swiper-scrollbar {
|
||||
position: absolute;
|
||||
left: 1%;
|
||||
bottom: 3px;
|
||||
z-index: 50;
|
||||
height: 5px;
|
||||
width: 98%;
|
||||
}
|
||||
.swiper-container-vertical > .swiper-scrollbar {
|
||||
position: absolute;
|
||||
right: 3px;
|
||||
top: 1%;
|
||||
z-index: 50;
|
||||
width: 5px;
|
||||
height: 98%;
|
||||
}
|
||||
.swiper-scrollbar-drag {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
position: relative;
|
||||
background: rgba(0, 0, 0, 0.5);
|
||||
border-radius: 10px;
|
||||
left: 0;
|
||||
top: 0;
|
||||
}
|
||||
.swiper-scrollbar-cursor-drag {
|
||||
cursor: move;
|
||||
}
|
||||
/* Preloader */
|
||||
.swiper-lazy-preloader {
|
||||
width: 42px;
|
||||
height: 42px;
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
top: 50%;
|
||||
margin-left: -21px;
|
||||
margin-top: -21px;
|
||||
z-index: 10;
|
||||
-webkit-transform-origin: 50%;
|
||||
-moz-transform-origin: 50%;
|
||||
transform-origin: 50%;
|
||||
-webkit-animation: swiper-preloader-spin 1s steps(12, end) infinite;
|
||||
-moz-animation: swiper-preloader-spin 1s steps(12, end) infinite;
|
||||
animation: swiper-preloader-spin 1s steps(12, end) infinite;
|
||||
}
|
||||
.swiper-lazy-preloader:after {
|
||||
display: block;
|
||||
content: "";
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg%20viewBox%3D'0%200%20120%20120'%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20xmlns%3Axlink%3D'http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink'%3E%3Cdefs%3E%3Cline%20id%3D'l'%20x1%3D'60'%20x2%3D'60'%20y1%3D'7'%20y2%3D'27'%20stroke%3D'%236c6c6c'%20stroke-width%3D'11'%20stroke-linecap%3D'round'%2F%3E%3C%2Fdefs%3E%3Cg%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.27'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.27'%20transform%3D'rotate(30%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.27'%20transform%3D'rotate(60%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.27'%20transform%3D'rotate(90%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.27'%20transform%3D'rotate(120%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.27'%20transform%3D'rotate(150%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.37'%20transform%3D'rotate(180%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.46'%20transform%3D'rotate(210%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.56'%20transform%3D'rotate(240%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.66'%20transform%3D'rotate(270%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.75'%20transform%3D'rotate(300%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.85'%20transform%3D'rotate(330%2060%2C60)'%2F%3E%3C%2Fg%3E%3C%2Fsvg%3E");
|
||||
background-position: 50%;
|
||||
-webkit-background-size: 100%;
|
||||
background-size: 100%;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
.swiper-lazy-preloader-white:after {
|
||||
background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg%20viewBox%3D'0%200%20120%20120'%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20xmlns%3Axlink%3D'http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink'%3E%3Cdefs%3E%3Cline%20id%3D'l'%20x1%3D'60'%20x2%3D'60'%20y1%3D'7'%20y2%3D'27'%20stroke%3D'%23fff'%20stroke-width%3D'11'%20stroke-linecap%3D'round'%2F%3E%3C%2Fdefs%3E%3Cg%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.27'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.27'%20transform%3D'rotate(30%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.27'%20transform%3D'rotate(60%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.27'%20transform%3D'rotate(90%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.27'%20transform%3D'rotate(120%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.27'%20transform%3D'rotate(150%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.37'%20transform%3D'rotate(180%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.46'%20transform%3D'rotate(210%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.56'%20transform%3D'rotate(240%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.66'%20transform%3D'rotate(270%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.75'%20transform%3D'rotate(300%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.85'%20transform%3D'rotate(330%2060%2C60)'%2F%3E%3C%2Fg%3E%3C%2Fsvg%3E");
|
||||
}
|
||||
@-webkit-keyframes swiper-preloader-spin {
|
||||
100% {
|
||||
-webkit-transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
@keyframes swiper-preloader-spin {
|
||||
100% {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
5296
client/externalFiles/swiper.js
Normal file
5296
client/externalFiles/swiper.js
Normal file
File diff suppressed because it is too large
Load Diff
12
client/externalFiles/swiper.min.css
vendored
Normal file
12
client/externalFiles/swiper.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
13
client/externalFiles/swiper.min.js
vendored
Normal file
13
client/externalFiles/swiper.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
client/externalFiles/swiper.min.js.map
Normal file
1
client/externalFiles/swiper.min.js.map
Normal file
File diff suppressed because one or more lines are too long
BIN
client/favicon.ico
Normal file
BIN
client/favicon.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 318 B |
BIN
client/favicon192.png
Normal file
BIN
client/favicon192.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 8.6 KiB |
149
client/group.html
Normal file
149
client/group.html
Normal file
@ -0,0 +1,149 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
</head>
|
||||
<body style='width:400px;'>
|
||||
<div id="event"></div>
|
||||
<script type="text/javascript">
|
||||
|
||||
var blockElement = document.getElementById("event");
|
||||
// copy query
|
||||
query = window.location.search;
|
||||
if (query == "") {
|
||||
query = "?path=main";
|
||||
}
|
||||
var evtSrc = new EventSource("http://localhost:5000/update");
|
||||
|
||||
function getJSON(url, successHandler, errorHandler) {
|
||||
var xhr = typeof XMLHttpRequest != 'undefined'
|
||||
? new XMLHttpRequest()
|
||||
: new ActiveXObject('Microsoft.XMLHTTP');
|
||||
console.log("fired JSON request", url)
|
||||
xhr.open('get', url, true);
|
||||
xhr.onreadystatechange = function() {
|
||||
var status;
|
||||
var data;
|
||||
// https://xhr.spec.whatwg.org/#dom-xmlhttprequest-readystate
|
||||
if (xhr.readyState == 4) { // `DONE`
|
||||
status = xhr.status;
|
||||
if (status == 200) {
|
||||
data = JSON.parse(xhr.responseText);
|
||||
successHandler && successHandler(data);
|
||||
} else {
|
||||
errorHandler && errorHandler(status);
|
||||
}
|
||||
}
|
||||
};
|
||||
xhr.send();
|
||||
};
|
||||
|
||||
|
||||
function htmlEscape(str) {
|
||||
return str
|
||||
.replace(/&/g, '&')
|
||||
.replace(/"/g, '"')
|
||||
.replace(/'/g, ''')
|
||||
.replace(/</g, '<')
|
||||
.replace(/>/g, '>');
|
||||
}
|
||||
|
||||
function draw(message) {
|
||||
var blk = "<h3>" + message.title + "</h3><table>\n"
|
||||
for (var i=0; i < message.components.length; i++) {
|
||||
var component = message.components[i]
|
||||
var name = component.name
|
||||
var type = component.type
|
||||
if ("title" in component) {
|
||||
var title = component.title
|
||||
} else {
|
||||
var title = name
|
||||
}
|
||||
if (type == "group") {
|
||||
blk += "<tr><td>link</td><td><a href='?path=" + encodeURI(message.path + "," + name) + "'>"+ title + "</a></td></tr>\n"
|
||||
} else if (type == "rdonly") {
|
||||
blk += "<tr><td >" + title + "</td><td id='"+ name +"' __ctype__=rdonly></td></tr>\n"
|
||||
} else if (type == "input") {
|
||||
blk += "<tr><td>" + title + "</td><td><input type=input id='"+ name +"' __ctype__=input></td></tr>\n"
|
||||
} else if (type == "checkbox") {
|
||||
blk += "<tr><td>" + title + "</td><td><input type=checkbox id='"+ name +"' __ctype__=checkbox></td></tr>\n"
|
||||
} else if (type == "radio") {
|
||||
blk += "<tr><td>" + title + "</td><td id='" + name + "' __ctype__=radio>\n"
|
||||
for (var j = 0; j < component.buttons.length; j++) {
|
||||
button = component.buttons[j]
|
||||
var rbname = name + ":" + button.value
|
||||
if (j != 0) blk+= "<br>"
|
||||
blk += "<input type=radio name='" + name + "' id='"+rbname+"' value='" + button.value + "'>" + button.title + "\n"
|
||||
}
|
||||
blk += "</td></tr>\n"
|
||||
}
|
||||
}
|
||||
blk += "</table>\n"
|
||||
blockElement.innerHTML = blk
|
||||
}
|
||||
|
||||
function updateblock(id) {
|
||||
getJSON("http://localhost:5000/updateblock"+query+"&id="+id,
|
||||
function(message) { console.log(message); },
|
||||
function(status) { console.log('stat', status); }
|
||||
);
|
||||
}
|
||||
|
||||
evtSrc.onmessage = function(e) {
|
||||
var message = JSON.parse(e.data)
|
||||
if (message.type == "id") {
|
||||
var id = message.id
|
||||
getJSON("http://localhost:5000/getblock"+query+"&id="+id,
|
||||
function(message) { draw(message); updateblock(id); },
|
||||
function(status) { console.log('stat', status); }
|
||||
);
|
||||
} else if (message.type == "draw") {
|
||||
draw(message);
|
||||
} else if (message.type == "update") {
|
||||
for (var i=0; i < message.updates.length; i++) {
|
||||
var component = message.updates[i]
|
||||
var name = component.name
|
||||
var value = component.value
|
||||
var elm = document.getElementById(name)
|
||||
if (!elm) continue
|
||||
var type = elm.getAttribute("__ctype__")
|
||||
if (type == "rdonly") {
|
||||
elm.innerHTML = htmlEscape(value)
|
||||
} else if (type == "input") {
|
||||
elm.value = value
|
||||
} else if (type == "checkbox") {
|
||||
elm.checked = (value != 0) && (value != "0")
|
||||
} else if (type == "radio") {
|
||||
var elm = document.getElementById(name + ":" + value)
|
||||
if (elm) {
|
||||
elm.checked = true // this will uncheck all radio buttons with the same name
|
||||
} else { // no element with this value: we have to go through all radio buttons
|
||||
var elms = document.getElementsByName(name)
|
||||
for (var j; j < elms.length; j++) {
|
||||
if (elms[j].checked) {
|
||||
elms[j].checked = false
|
||||
break // we have found the victim, we can leave
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (message.type == "close") {
|
||||
evtSrc.close()
|
||||
}
|
||||
};
|
||||
|
||||
evtSrc.onerror = function(e) {
|
||||
blockElement.innerHTML = "connection lost"
|
||||
evtSrc.close()
|
||||
};
|
||||
|
||||
window.onbeforeunload = closingCode;
|
||||
function closingCode(){
|
||||
console.log("CLOSE")
|
||||
evtSrc.close()
|
||||
return null;
|
||||
}
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
385
client/jsFiles/SEAWebClientCommunication.js
Normal file
385
client/jsFiles/SEAWebClientCommunication.js
Normal file
@ -0,0 +1,385 @@
|
||||
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
// % COMMUNICATION
|
||||
|
||||
var timeoutID; // We need this ID to reset the timer every 30 seconds
|
||||
|
||||
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
// Server Sent Event
|
||||
|
||||
|
||||
function buildUpdateConnection() {
|
||||
// Establishes server-sent-event-connection, which is used for all sorts of
|
||||
// updates and exists as long as the client is running.
|
||||
// Executed at programstart (see also SEAWebClientMain.js).
|
||||
|
||||
var path = "http://" + hostPort + "/update";
|
||||
if (debugCommunication) {
|
||||
console.log("%cto server (SSE): " + path,
|
||||
"color:white;background:lightblue");
|
||||
}
|
||||
|
||||
try {
|
||||
var src = new EventSource(path);
|
||||
} catch (e) {
|
||||
console.log(e)
|
||||
alertify.prompt(
|
||||
"NETWORK ERROR",
|
||||
"Failed to establish connection to data-server at the given address!"
|
||||
+ "Try to enter HOST and PORT of the data-server manually!",
|
||||
hostPort, function(evt, value) {
|
||||
hostPort = value;
|
||||
buildUpdateConnection();
|
||||
}, function() {
|
||||
})
|
||||
}
|
||||
|
||||
src.onmessage = function(e) {
|
||||
var message = JSON.parse(e.data);
|
||||
if (message) {
|
||||
handleUpdateMessage(src, message);
|
||||
}
|
||||
};
|
||||
|
||||
src.onerror = function(e) {
|
||||
console.log(e);
|
||||
console.log('EVTSRC error')
|
||||
alertify
|
||||
.prompt(
|
||||
"NETWORK ERROR",
|
||||
"Failed to establish connection to data-server at the given address!"
|
||||
+ "Try to enter HOST and PORT of the data-server manually!",
|
||||
hostPort, function(evt, value) {
|
||||
hostPort = value;
|
||||
buildUpdateConnection();
|
||||
}, function() {
|
||||
})
|
||||
src.close();
|
||||
};
|
||||
}
|
||||
|
||||
function handleUpdateMessage(src, message) {
|
||||
// Handles incoming SSE-messages depending on type of message.
|
||||
|
||||
if (debugCommunication > 1) {
|
||||
console.log("%cfrom server (SSE): " + message.type,
|
||||
"color:white;background:lightgray", message);
|
||||
}
|
||||
|
||||
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
// <---------------------------------------------------------------------------------BUG!!!
|
||||
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
resetTimer(src);
|
||||
switch (message.type) {
|
||||
// id-message: Confirms establishment of SSE-connection and determines
|
||||
// specific ID of the client
|
||||
case "id":
|
||||
for (var i = 0; i < swiper.length; i++) {
|
||||
swiper[i].removeAllSlides();
|
||||
}
|
||||
clientID = message.id;
|
||||
if ("device" in message) {
|
||||
if (message.device == "_inst_select") {
|
||||
clientTitle = "select instrument";
|
||||
console.log('IDselect')
|
||||
pushInitCommand("getblock?path=_inst_select&", "instrument selection");
|
||||
menuMode = true;
|
||||
sizeChange();
|
||||
} else {
|
||||
clientTitle = message.instrument + " " + message.device;
|
||||
console.log('loadBlocks')
|
||||
loadFirstBlocks();
|
||||
}
|
||||
document.title = "SEA "+clientTitle;
|
||||
} else {
|
||||
document.title = "SEA "+clientTitle + " " + message.title;
|
||||
}
|
||||
var header = document.getElementById("header");
|
||||
header.setAttribute("style", "width: auto;");
|
||||
header.innerHTML = clientTitle;
|
||||
console.log('ID', initCommands);
|
||||
nextInitCommand();
|
||||
break;
|
||||
// console-update-message: Confirms a command.
|
||||
case "command":
|
||||
var histories = document.getElementsByClassName("history");
|
||||
for (var i = 0; i < histories.length; i++) {
|
||||
var line = document.createElement('div');
|
||||
line.innerHTML = htmlEscape(message.line);
|
||||
line.style.color = "cornflowerblue";
|
||||
if (message.origin == "self") {
|
||||
line.style.fontWeight = "bold";
|
||||
}
|
||||
histories[i].appendChild(document.createElement('br'));
|
||||
histories[i].appendChild(line);
|
||||
histories[i].scrollTop = histories[i].scrollHeight;
|
||||
}
|
||||
var cmd = htmlEscape(message.line);
|
||||
if (commandHistory.indexOf(cmd) === -1) {
|
||||
commandHistory.unshift(cmd);
|
||||
}
|
||||
break;
|
||||
// console-update-message: Confirms execution of command.
|
||||
case "reply":
|
||||
var histories = document.getElementsByClassName("history");
|
||||
for (var i = 0; i < histories.length; i++) {
|
||||
var line = document.createElement('div');
|
||||
line.innerHTML = htmlEscape(message.line);
|
||||
line.style.color = "black";
|
||||
if (message.origin == "self") {
|
||||
line.style.fontWeight = "bold";
|
||||
} else if (message.origin == "async") {
|
||||
line.style.color = "green";
|
||||
if (!showAsync) continue;
|
||||
}
|
||||
histories[i].appendChild(line);
|
||||
histories[i].scrollTop = histories[i].scrollHeight;
|
||||
}
|
||||
break;
|
||||
// graph-message: Evokes redraw of graphics.
|
||||
case "graph":
|
||||
console.log("graph");
|
||||
createCharts2(message.graph);
|
||||
break;
|
||||
// redraw.message: Communicates changes requiring reset of a whole group
|
||||
case "redraw": // SHOULD BE TESTED
|
||||
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
// SPECIAL CASE: is message.title = "main possible? It should evoke
|
||||
// redraw of client
|
||||
|
||||
// special meaning: s < 0: replace slides in all swiper instances
|
||||
reqJSON(-1, "http://" + hostPort + "/getblock?path=" + message.path
|
||||
+ "&id=" + clientID, successHandler, errorHandler);
|
||||
|
||||
break;
|
||||
// graph-update-message:
|
||||
case "graph-update":
|
||||
//if (getUpdatesGraphics) {
|
||||
//timeServer = message.time;
|
||||
console.log("graph-update");
|
||||
updateCharts2(message.graph);
|
||||
//}
|
||||
break;
|
||||
// update-message: Communicates change of values.
|
||||
case "update":
|
||||
if (debugCommunication > 1) {
|
||||
console.log(message);
|
||||
}
|
||||
updateValues(message, src);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
function htmlEscape(str) {
|
||||
if (!str) return "";
|
||||
return str.replace(/&/g, '&').replace(/"/g, '"').replace(/'/g,
|
||||
''').replace(/</g, '<').replace(/>/g, '>');
|
||||
}
|
||||
|
||||
function resetTimer(src) {
|
||||
// Executed every time a heartbeat-message is obtained.
|
||||
// If no heartbeat-messages are obtained for a certain amount of time,
|
||||
// an error-message is thrown.
|
||||
|
||||
clearTimeout(timeoutID);
|
||||
timeoutID = setTimeout(function(src) {
|
||||
console.log("timeout");
|
||||
alertify.error("connection lost");
|
||||
if (src) {
|
||||
src.close();
|
||||
}
|
||||
}, 60000);
|
||||
}
|
||||
|
||||
function updateValues(message, src) {
|
||||
// Handles changes of parameter-values
|
||||
|
||||
for (var i = 0; i < message.updates.length; i++) {
|
||||
var component = message.updates[i];
|
||||
var value = component.value;
|
||||
var matches = document.getElementsByName(component.name);
|
||||
for (var j = 0; j < matches.length; j++) {
|
||||
var type = matches[j].getAttribute("__ctype__");
|
||||
if (type == "rdonly") {
|
||||
var text = htmlEscape(value);
|
||||
if (text) {
|
||||
matches[j].innerHTML = text;
|
||||
}
|
||||
} else if (type == "input") {
|
||||
var row = matches[j].parentNode.parentNode.parentNode;
|
||||
row.style.backgroundColor = "white";
|
||||
var oldValue = matches[j].getAttribute("oldValue")
|
||||
|| matches[j].value;
|
||||
if (value != matches[j].value && value != oldValue) {
|
||||
if (matches[j] == document.activeElement
|
||||
|| oldValue != matches[j].value) {
|
||||
row.style.backgroundColor = "orange";
|
||||
} else {
|
||||
matches[j].value = value;
|
||||
}
|
||||
}
|
||||
matches[j].setAttribute("actualValue", value);
|
||||
resizeTextfield(matches[j]);
|
||||
} else if (type == "checkbox") {
|
||||
var row = matches[j].parentNode.parentNode;
|
||||
row.style.backgroundColor = "white";
|
||||
matches[j].checked = value == 1 && value == "1";
|
||||
} else if (type == "enum") {
|
||||
matches[j].style.display = "block";
|
||||
var row = matches[j].parentNode.parentNode;
|
||||
row.style.backgroundColor = "white";
|
||||
matches[j].value = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
// XMLHttpRequest
|
||||
|
||||
function reqJSON(s, url, successHandler, errorHandler) {
|
||||
var xhr = typeof XMLHttpRequest != 'undefined' ? new XMLHttpRequest()
|
||||
: new ActiveXObject('Microsoft.XMLHTTP');
|
||||
if (debugCommunication) {
|
||||
console.log("%cto server (reqJSON): " + url,
|
||||
"color:white;background:lightgreen");
|
||||
}
|
||||
xhr.open('get', url, true);
|
||||
xhr.onreadystatechange = function() {
|
||||
// console.log(xhr)
|
||||
var status;
|
||||
var data;
|
||||
// https://xhr.spec.whatwg.org/#dom-xmlhttprequest-readystate
|
||||
if (xhr.readyState == 4) { // `DONE`
|
||||
status = xhr.status;
|
||||
if (status == 200) {
|
||||
data = JSON.parse(xhr.responseText);
|
||||
successHandler && successHandler(s, data);
|
||||
} else {
|
||||
errorHandler && errorHandler(status);
|
||||
}
|
||||
}
|
||||
};
|
||||
xhr.send();
|
||||
}
|
||||
|
||||
function successHandler(s, message) {
|
||||
// Handles incoming XMLHttp-messages depending on type of message.
|
||||
// s: slide number or -1 for replacing slide in all slider instances
|
||||
if (debugCommunication) {
|
||||
console.log("%cfrom server (reqJSON): " + message.type,
|
||||
"color:white;background:dimgray", message);
|
||||
}
|
||||
switch (message.type) {
|
||||
// Response to a "getblock"-server-request.
|
||||
case "draw":
|
||||
if (debugCommunication) {
|
||||
console.log(message);
|
||||
}
|
||||
if (message.path == "main") {
|
||||
// Happens only initially or at device change.
|
||||
for (var sLocal = 0; sLocal < MAXBLOCK; sLocal++) {
|
||||
insertSlide(sLocal, message.title, "main", createContent(
|
||||
sLocal, message));
|
||||
}
|
||||
} else {
|
||||
if (s < 0) { // redraw: check for slides in all swiper instances
|
||||
for (var isw = 0; isw < MAXBLOCK; isw ++) {
|
||||
var slide = findSlide(isw, message.path);
|
||||
if (slide) {
|
||||
console.log("redraw", isw);
|
||||
replaceSlideContent(slide, message.title,
|
||||
createContent(isw, message));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
insertSlide(s, message.title, message.path, createContent(s,
|
||||
message));
|
||||
}
|
||||
}
|
||||
nextInitCommand();
|
||||
// Request for updates.
|
||||
if (getUpdates) {
|
||||
reqJSON(s, "http://" + hostPort + "/updateblock?path="
|
||||
+ message.path + "&id=" + clientID, successHandler,
|
||||
errorHandler);
|
||||
}
|
||||
break;
|
||||
// Response to a "update-block"-server-request.
|
||||
case "accept-block":
|
||||
break;
|
||||
// Response to a "console"-server-request.
|
||||
case "accept-console":
|
||||
// draw console, only on the first and the last swiper
|
||||
insertSlide(0, "console", "console",
|
||||
createContentConsole(sLocal));
|
||||
insertSlide(3, "console", "console",
|
||||
createContentConsole(sLocal));
|
||||
nextInitCommand();
|
||||
// send empty command in order to trigger getting history
|
||||
reqJSON(0, "http://" + hostPort + "/sendcommand?command=&id=" + clientID, successHandler,
|
||||
errorHandler);
|
||||
break;
|
||||
// Response to a "gettime"-server-request.
|
||||
case "time":
|
||||
timeRange = message.time;
|
||||
/*createGraphics();
|
||||
// By default mostleft swiper-instance shows graphics.
|
||||
swiper[0].slideTo(0);
|
||||
|
||||
// Update time-selection. (see also SEAWebClientGraphics.js)
|
||||
var select = document.getElementsByClassName("select-time")[0];
|
||||
begin = timeRange[0] - timeRange[1];
|
||||
select.value = begin;
|
||||
// Server-request for variable-list.*/
|
||||
reqJSON(0, "http://" + hostPort + "/getvars?time=" + timeRange + "&id="
|
||||
+ clientID, successHandler, errorHandler);
|
||||
break;
|
||||
// Response to a "getvars"-server-request.
|
||||
case "var_list":
|
||||
//blocks = message.blocks;
|
||||
/*var varlist = [];
|
||||
for (var i = 0; i < blocks.length; i++) {
|
||||
for (var j = 0; j < blocks[i].curves.length; j++) {
|
||||
varlist.push(blocks[i].curves[j].name);
|
||||
}
|
||||
}
|
||||
// Update graphics
|
||||
if (varlist.length > 0) {
|
||||
reqJSON(0, "http://" + hostPort + "/graph?time=" + timeRange
|
||||
+ "&variables=" + varlist + "&id=" + clientID,
|
||||
successHandler, errorHandler);
|
||||
} else {
|
||||
nextInitCommand();
|
||||
}*/
|
||||
graphs.receivedVars(message.blocks);
|
||||
nextInitCommand();
|
||||
break;
|
||||
// Response to a "graph"-server-request.
|
||||
case "graph-draw":
|
||||
// obsolete?
|
||||
if (debugCommunication) {
|
||||
console.log("graph-draw", message);
|
||||
}
|
||||
createCharts2(message.graph);
|
||||
nextInitCommand();
|
||||
// Request for updates.
|
||||
reqJSON(s, "http://" + hostPort + "/updategraph?id=" + clientID,
|
||||
successHandler, errorHandler);
|
||||
break;
|
||||
// Response to a "updategraph"-server-request.
|
||||
case "accept-graph":
|
||||
break;
|
||||
case "error":
|
||||
console.log("%cError-Message received!", "color:white;background:red");
|
||||
console.log(message);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
function errorHandler(status) {
|
||||
if (debugCommunication) {
|
||||
console.log("error", status);
|
||||
}
|
||||
}
|
67
client/jsFiles/SEAWebClientConsole.js
Normal file
67
client/jsFiles/SEAWebClientConsole.js
Normal file
@ -0,0 +1,67 @@
|
||||
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
// % CONSOLE
|
||||
|
||||
var commandHistory = []; // Stores commands executed by console.
|
||||
|
||||
var histIndex = -1; // Selected element of 'commandHistory'. (-1 = "")
|
||||
|
||||
function createContentConsole(s) {
|
||||
// Creates input-textfield and texarea showing console-history.
|
||||
|
||||
var commandline = document.createElement('input');
|
||||
commandline.setAttribute("type", "text");
|
||||
commandline.setAttribute("class", "row commandline");
|
||||
|
||||
commandline.onkeydown = function (e) {
|
||||
//console.log(histIndex);
|
||||
if (e.which === 38 || e.key == "ArrowUp") {
|
||||
if (histIndex + 1 < commandHistory.length) {
|
||||
histIndex++;
|
||||
this.value = commandHistory[histIndex];
|
||||
}
|
||||
var input = this;
|
||||
window.setTimeout(
|
||||
function () {
|
||||
input.setSelectionRange(input.value.length,
|
||||
input.value.length);
|
||||
}, 0, input);
|
||||
}
|
||||
if (e.which === 40 || e.key == "ArrowDown") {
|
||||
if (histIndex >= 0) {
|
||||
histIndex--;
|
||||
if (histIndex > -1) {
|
||||
this.value = commandHistory[histIndex];
|
||||
} else {
|
||||
this.value = "";
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
commandline.setAttribute("autocomplete", "on");
|
||||
|
||||
var wrapper = document.createElement('form');
|
||||
wrapper.setAttribute("class", "commandline-wrapper");
|
||||
|
||||
wrapper.onsubmit = function (e) {
|
||||
e.preventDefault();
|
||||
histIndex = -1;
|
||||
// Request for command.
|
||||
reqJSON(s, "http://" + hostPort + "/sendcommand?command="
|
||||
+ commandline.value + "&id=" + clientID, successHandler,
|
||||
errorHandler);
|
||||
commandline.value = "";
|
||||
};
|
||||
|
||||
wrapper.setAttribute("method", 'GET');
|
||||
wrapper.appendChild(commandline);
|
||||
|
||||
var history = document.createElement('div');
|
||||
history.setAttribute("class", "history");
|
||||
|
||||
var content = document.createElement('div');
|
||||
content.setAttribute("class", "content-console");
|
||||
content.appendChild(wrapper);
|
||||
content.appendChild(history);
|
||||
return content;
|
||||
}
|
1108
client/jsFiles/SEAWebClientGraph.js
Normal file
1108
client/jsFiles/SEAWebClientGraph.js
Normal file
File diff suppressed because it is too large
Load Diff
31
client/jsFiles/SEAWebClientGraphics.js
Normal file
31
client/jsFiles/SEAWebClientGraphics.js
Normal file
@ -0,0 +1,31 @@
|
||||
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
// % GRAPHICS
|
||||
/*
|
||||
var swiperGraphics = []; // This array contains graphics-swiper-Instances.
|
||||
var begin = -10; // Time to look back (in seconds).
|
||||
var timeServer; // Every time a graph-update-mesage is received the
|
||||
// server-timestamp is stored.
|
||||
var timeRange; // Range of time to regard (unix-time in seconds).
|
||||
var blocks; // array of graphic-blocks sorted by units. (as from var_list, but values added)
|
||||
|
||||
var MARGIN_TOP = 10;
|
||||
var MARGIN_RIGHT = 10;
|
||||
var MARGIN_BOTTOM = 20;
|
||||
var MARGIN_LEFT = 60;
|
||||
|
||||
var width;
|
||||
var height;
|
||||
var margin;
|
||||
|
||||
var scaleX;
|
||||
|
||||
zoomSelection = false;
|
||||
|
||||
|
||||
function createCharts(graph) {
|
||||
createCharts2(graph);
|
||||
return
|
||||
}
|
||||
function updateCharts(graph){
|
||||
updateCharts2(graph)
|
||||
}
|
565
client/jsFiles/SEAWebClientGroup.js
Normal file
565
client/jsFiles/SEAWebClientGroup.js
Normal file
@ -0,0 +1,565 @@
|
||||
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
// % GROUP
|
||||
|
||||
var writePermissionTimeout; // Sets writePermission to 'false, restarts by
|
||||
// user-interaction.
|
||||
|
||||
var prompt = false // True while a prompt is opened.
|
||||
|
||||
function getGroup(s, name) {
|
||||
var found = false;
|
||||
if (name == "") {
|
||||
swiper[s].slideTo(defaultSlidePos(s));
|
||||
return;
|
||||
}
|
||||
for (var i = 0; i < swiper[s].slides.length; i++) {
|
||||
var slideType = swiper[s].slides[i].getAttribute("slide-type");
|
||||
if (slideType == name) {
|
||||
found = true;
|
||||
swiper[s].slideTo(i);
|
||||
}
|
||||
}
|
||||
if (!found && name != "console" && name != "graphics") {
|
||||
// Server-request for group.
|
||||
reqJSON(s, "http://" + hostPort + "/getblock?path=" + name
|
||||
+ "&id=" + clientID, successHandler, errorHandler);
|
||||
}
|
||||
}
|
||||
|
||||
function sendCommand(s, command) {
|
||||
reqJSON(s, "http://" + hostPort + "/sendcommand?command=" + command
|
||||
+ "&id=" + clientID, successHandler, errorHandler);
|
||||
}
|
||||
|
||||
function createContent(s, message) {
|
||||
// Depending on the message received from the server the content of the
|
||||
// group
|
||||
// is created dynamically. Handles draw-message.
|
||||
|
||||
var content = document.createElement('div');
|
||||
content.setAttribute("class", "content");
|
||||
// Process components of the message
|
||||
for (var i = 0; i < message.components.length; i++) {
|
||||
var component = message.components[i];
|
||||
var name = component.name;
|
||||
var type = component.type;
|
||||
var title = name;
|
||||
if ("title" in component)
|
||||
title = component.title;
|
||||
var info = component.info;
|
||||
switch (type) {
|
||||
case "group":
|
||||
content.appendChild(createLink(s, name, title));
|
||||
break;
|
||||
case "rdonly":
|
||||
if ("link" in component) {
|
||||
content.appendChild(createReadOnlyInstrLink(s, name, title,
|
||||
component.link, info));
|
||||
} else {
|
||||
content.appendChild(createReadOnly(s, name, title, info));
|
||||
}
|
||||
break;
|
||||
case "rdlink":
|
||||
content.appendChild(createReadOnlyGroupLink(s, name, title, info));
|
||||
break;
|
||||
case "input":
|
||||
content.appendChild(createInput(s, name, title,
|
||||
info));
|
||||
break;
|
||||
case "checkbox":
|
||||
content.appendChild(createCheckbox(s, name, title,
|
||||
info));
|
||||
break;
|
||||
case "enum":
|
||||
content.appendChild(createSelection(s, name, title,
|
||||
component.enum_names, info));
|
||||
break;
|
||||
case "pushbutton":
|
||||
console.log(component);
|
||||
console.log(component.info);
|
||||
content.appendChild(createPushButton(s, name, title,
|
||||
info));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return content;
|
||||
}
|
||||
|
||||
function gotoGroups(slideNames) {
|
||||
slideNames = slideNames.split("%20");
|
||||
var l = Math.min(MAXBLOCK,slideNames.length);
|
||||
document.title = "SEA "+ clientTitle + " " + slideNames.join(" ");
|
||||
for (var s=0; s<l; s++) {
|
||||
getGroup(s, slideNames[s]);
|
||||
}
|
||||
}
|
||||
|
||||
function createLink(s, name, title) {
|
||||
// Creates row-element containing link.
|
||||
|
||||
var row = document.createElement('row');
|
||||
row.setAttribute("id", name);
|
||||
row.setAttribute("name", title);
|
||||
row.setAttribute("class", "interactive row link");
|
||||
row.setAttribute("tabindex", 0);
|
||||
|
||||
row.onclick = function () {
|
||||
var slideNames = getSlideNames();
|
||||
slideNames[s] = name;
|
||||
document.title = "SEA "+ clientTitle + " " + slideNames.join(" ");
|
||||
history.pushState({func: "gotoGroups", funarg: slideNames.join("%20")}, document.title, "#" + slideNames.join("%20"));
|
||||
getGroup(s, name);
|
||||
}
|
||||
|
||||
if (title === "console" || title === "device config") {
|
||||
row.setAttribute("class", "interactive row link link-static");
|
||||
row.innerHTML = "console";
|
||||
}
|
||||
row.innerHTML = title;
|
||||
return row;
|
||||
}
|
||||
|
||||
function createReadOnly(s, name, title, info) {
|
||||
// Creates row-element containing read-only-item.
|
||||
|
||||
var left = createTitle(title, info);
|
||||
|
||||
var right = document.createElement('span');
|
||||
right.setAttribute("class", "col-right");
|
||||
right.setAttribute("name", name);
|
||||
right.setAttribute("__ctype__", "rdonly");
|
||||
|
||||
return appendToContent(info, left, right);
|
||||
}
|
||||
|
||||
function createReadOnlyGroupLink(s, name, title, info) {
|
||||
// Creates row-element containing link AND read-only-item.
|
||||
// for secop
|
||||
|
||||
var left = createTitle(title, info);
|
||||
|
||||
left.setAttribute("id", name);
|
||||
left.setAttribute("name", title);
|
||||
left.setAttribute("class", "interactive link");
|
||||
|
||||
left.onclick = function () {
|
||||
getGroup(s, title);
|
||||
}
|
||||
|
||||
var right = document.createElement('span');
|
||||
right.setAttribute("class", "col-right");
|
||||
right.setAttribute("name", name);
|
||||
right.setAttribute("__ctype__", "rdonly");
|
||||
|
||||
return appendToContent(info, left, right);
|
||||
}
|
||||
|
||||
function createReadOnlyInstrLink(s, name, title, link, info) {
|
||||
// Creates row-element containing link AND read-only-item.
|
||||
|
||||
// var left = createTitle(title, info);
|
||||
var left = document.createElement('a');
|
||||
left.setAttribute("class", "col-left");
|
||||
left.innerHTML = title;
|
||||
|
||||
left.setAttribute("id", name);
|
||||
left.setAttribute("name", title);
|
||||
left.setAttribute("class", "interactive link");
|
||||
|
||||
var right = document.createElement('span');
|
||||
right.setAttribute("class", "col-right");
|
||||
right.setAttribute("name", name);
|
||||
right.setAttribute("__ctype__", "rdonly");
|
||||
|
||||
row = appendToContent(info, left, right);
|
||||
row.onclick = function () {
|
||||
this.style.backgroundColor = "orangered";
|
||||
left.click();
|
||||
}
|
||||
if (link.charAt(0) == ':') {
|
||||
left.href = "http://" + location.hostname + link + "/";
|
||||
} else {
|
||||
left.href = link;
|
||||
}
|
||||
|
||||
row.setAttribute("class", "row clickable");
|
||||
return row;
|
||||
}
|
||||
|
||||
function createPushButton(s, name, title, info) {
|
||||
// Creates row-element containing a push button
|
||||
|
||||
var left = createTitle(title, info);
|
||||
console.log(info);
|
||||
|
||||
left.setAttribute("id", name);
|
||||
left.setAttribute("name", title);
|
||||
|
||||
var right = document.createElement('span');
|
||||
right.setAttribute("class", "col-right clickable push-button");
|
||||
right.setAttribute("name", name);
|
||||
right.setAttribute("__ctype__", "rdonly");
|
||||
|
||||
row = appendToContent(info, left, right);
|
||||
right.onclick = function () {
|
||||
if (writePermission) {
|
||||
var row = left.parentNode;
|
||||
right.style.backgroundColor = "orangered";
|
||||
// Request for command
|
||||
sendCommand(s, name);
|
||||
} else {
|
||||
prompt = true;
|
||||
alertify.confirm("", "You are connected with <b>" + clientTitle
|
||||
+ "</b>. <br>"
|
||||
+ "Are you sure you want to modify things here?",
|
||||
function () {
|
||||
// User decided to proceed.
|
||||
writePermission = true;
|
||||
writePermissionTimeout = setTimeout(function () {
|
||||
writePermission = false;
|
||||
}, 3600000);
|
||||
var row = left.parentNode;
|
||||
row.style.backgroundColor = "orangered";
|
||||
// Request for command
|
||||
sendCommand(s, name);
|
||||
prompt = false;
|
||||
}, function () {
|
||||
// User decided to cancel
|
||||
prompt = false;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
row.setAttribute("class", "row");
|
||||
return row;
|
||||
}
|
||||
|
||||
function createInput(s, name, title, info) {
|
||||
// Creates row-element containing input-item.
|
||||
|
||||
if (info) {
|
||||
var infoBox = createInfo(title, info);
|
||||
}
|
||||
var left = createTitle(title, info);
|
||||
|
||||
var input = document.createElement('input');
|
||||
input.setAttribute("type", "text");
|
||||
input.setAttribute("class", "input-text");
|
||||
input.setAttribute("name", name);
|
||||
input.setAttribute("__ctype__", "input");
|
||||
input.style.width = "100px";
|
||||
|
||||
input.onkeydown = function (e) {
|
||||
if (e.which === 27 || e.key == "Escape") {
|
||||
// User decided to cancel
|
||||
input.value = input.getAttribute("oldValue");
|
||||
resizeTextfield(input);
|
||||
var row = left.parentNode;
|
||||
row.style.backgroundColor = "white";
|
||||
}
|
||||
}
|
||||
|
||||
input.onfocus = function () {
|
||||
input.setAttribute("oldValue", input.value);
|
||||
|
||||
if (isTouchDevice())
|
||||
setTimeout(function () {
|
||||
posTextfield(s, left);
|
||||
}, 1);
|
||||
}
|
||||
|
||||
input.onblur = function () {
|
||||
if (prompt) {
|
||||
return false;
|
||||
}
|
||||
var row = left.parentNode;
|
||||
var value = input.value;
|
||||
var oldValue = input.getAttribute("oldValue") || value;
|
||||
if (!input.hasAttribute("actualValue")) {
|
||||
input.setAttribute("actualValue", oldValue);
|
||||
}
|
||||
var actualValue = input.getAttribute("actualValue");
|
||||
if (value === actualValue || value === oldValue) {
|
||||
input.value = actualValue;
|
||||
// nothing to do.
|
||||
row.style.backgroundColor = "white";
|
||||
return false;
|
||||
}
|
||||
// User changed value and moved focus to other object.
|
||||
alertify.confirm("", "You changed a field without pressing the return key.<br>"
|
||||
+ "Hint: press ESC for leaving a field unchanged.<b>"
|
||||
+ "You are connected with <b>" + clientTitle + "</b>.<br>"
|
||||
+ "Are you sure you want to change the value of<br><b>"
|
||||
+ name + "</b> from <b>" + actualValue
|
||||
+ "</b> to <b>" + value + "</b>?", function () {
|
||||
// User decided to proceed.
|
||||
writePermission = true;
|
||||
writePermissionTimeout = setTimeout(function () {
|
||||
writePermission = false;
|
||||
}, 3600000);
|
||||
row.style.backgroundColor = "orangered";
|
||||
// Request for command
|
||||
sendCommand(s, name + " " + value);
|
||||
resizeTextfield(input);
|
||||
prompt = false;
|
||||
}, function () {
|
||||
// User decided to cancel
|
||||
input.value = input.getAttribute("actualValue");
|
||||
resizeTextfield(input);
|
||||
row.style.backgroundColor = "white";
|
||||
prompt = false;
|
||||
});
|
||||
}
|
||||
|
||||
var form = document.createElement('form');
|
||||
form.onsubmit = function (e) {
|
||||
e.preventDefault();
|
||||
// remove following check: sometimes we want to send a command even with an unchanged value
|
||||
//if (input.value === input.getAttribute("oldValue")) {
|
||||
// // nothing to do.
|
||||
// return false;
|
||||
//}
|
||||
if (writePermission) {
|
||||
var row = left.parentNode;
|
||||
row.style.backgroundColor = "orangered";
|
||||
// Request for command
|
||||
sendCommand(s, name + " " + input.value);
|
||||
} else {
|
||||
var value = input.value
|
||||
prompt = true;
|
||||
alertify.confirm("", "You are connected with <b>" + clientTitle
|
||||
+ "</b>. <br>"
|
||||
+ "Are you sure you want to modify things here?",
|
||||
function () {
|
||||
// User decided to proceed.
|
||||
writePermission = true;
|
||||
writePermissionTimeout = setTimeout(function () {
|
||||
writePermission = false;
|
||||
}, 3600000);
|
||||
var row = left.parentNode;
|
||||
row.style.backgroundColor = "orangered";
|
||||
// Request for command
|
||||
sendCommand(s, name + " " + value);
|
||||
resizeTextfield(input);
|
||||
prompt = false;
|
||||
}, function () {
|
||||
// User decided to cancel
|
||||
input.value = input.getAttribute("oldValue");
|
||||
resizeTextfield(input);
|
||||
prompt = false;
|
||||
});
|
||||
}
|
||||
};
|
||||
form.appendChild(input);
|
||||
|
||||
var right = document.createElement('span');
|
||||
right.setAttribute("class", "col-right");
|
||||
right.appendChild(form);
|
||||
return appendToContent(info, left, right);
|
||||
}
|
||||
|
||||
function posTextfield(s, left) {
|
||||
var content = swiper[s].slides[swiper[s].activeIndex].childNodes[1];
|
||||
var row = left.parentNode;
|
||||
content.scrollTop = row.offsetTop - 30;
|
||||
}
|
||||
|
||||
function resizeTextfield(input) {
|
||||
if (input.value.length > input.size * 12 / 20) {
|
||||
var str0 = window.getComputedStyle(input).fontSize;
|
||||
var str1 = str0.substring(0, str0.length - 2);
|
||||
if (input.value.length < 43) {
|
||||
input.style.width = input.value.length * str1 * 12 / 20 + "px";
|
||||
}
|
||||
} else {
|
||||
input.style.width = "100px";
|
||||
}
|
||||
}
|
||||
|
||||
function createCheckbox(s, name, title, info) {
|
||||
// Creates row-element containing checkbox-item
|
||||
|
||||
var left = createTitle(title, info);
|
||||
|
||||
var input = document.createElement('input');
|
||||
input.setAttribute("type", "checkbox");
|
||||
input.setAttribute("name", name);
|
||||
input.setAttribute("__ctype__", "checkbox");
|
||||
input.setAttribute("class", "parameter-checkbox");
|
||||
|
||||
input.onkeyup = function (e) {
|
||||
if (e.keyCode === 32) {
|
||||
handleCheckbox();
|
||||
}
|
||||
}
|
||||
|
||||
var label = document.createElement('label');
|
||||
label.setAttribute("for", input);
|
||||
label.setAttribute("class", "parameter-label");
|
||||
|
||||
label.onclick = function () {
|
||||
handleCheckbox();
|
||||
}
|
||||
|
||||
function handleCheckbox() {
|
||||
if (writePermission) {
|
||||
var row = left.parentNode;
|
||||
row.style.backgroundColor = "orangered";
|
||||
if (input.checked) {
|
||||
var value = "0";
|
||||
input.checked = false;
|
||||
} else {
|
||||
var value = "1";
|
||||
input.checked = true;
|
||||
}
|
||||
// Request for command
|
||||
sendCommand(s, name + " " + value);
|
||||
} else {
|
||||
alertify.confirm("", "You are connected with <b>" + clientTitle
|
||||
+ "</b>. <br>"
|
||||
+ "Are you sure you want to modify things here?",
|
||||
function () {
|
||||
// User decided to proceed.
|
||||
writePermission = true;
|
||||
writePermissionTimeout = setTimeout(function () {
|
||||
writePermission = false;
|
||||
}, 3600000);
|
||||
var row = left.parentNode;
|
||||
row.style.backgroundColor = "orangered";
|
||||
if (input.checked) {
|
||||
var value = "0";
|
||||
input.checked = false;
|
||||
} else {
|
||||
var value = "1";
|
||||
input.checked = true;
|
||||
}
|
||||
// Request for command
|
||||
sendCommand(s, name + " " + value);
|
||||
}, function () {
|
||||
// User decided to cancel
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
var right = document.createElement('span');
|
||||
right.setAttribute("class", "col-right");
|
||||
right.appendChild(input);
|
||||
right.appendChild(label);
|
||||
return appendToContent(info, left, right);
|
||||
}
|
||||
|
||||
function createSelection(s, name, title, buttons, info) {
|
||||
// Creates row-element containing dropdown-selection.
|
||||
|
||||
var left = createTitle(title, info);
|
||||
|
||||
var select = document.createElement('select');
|
||||
select.setAttribute("name", name);
|
||||
select.setAttribute("__ctype__", "enum");
|
||||
select.setAttribute("class", "select-params");
|
||||
|
||||
select.onfocus = function () {
|
||||
select.setAttribute("oldIndex", select.selectedIndex);
|
||||
}
|
||||
|
||||
select.oninput = function () {
|
||||
if (writePermission && title != "device config") {
|
||||
var row = left.parentNode;
|
||||
row.style.backgroundColor = "orangered";
|
||||
// Request for command
|
||||
sendCommand(s, name + " " + this.value);
|
||||
} else {
|
||||
alertify.confirm("", "You are connected with <b>" + clientTitle
|
||||
+ "</b>. <br>"
|
||||
+ "Are you sure you want to modify things here?",
|
||||
function () {
|
||||
// User decided to proceed.
|
||||
writePermission = true;
|
||||
writePermissionTimeout = setTimeout(function () {
|
||||
writePermission = false;
|
||||
}, 3600000);
|
||||
var row = left.parentNode;
|
||||
row.style.backgroundColor = "orangered";
|
||||
// Request for command
|
||||
sendCommand(s, name + " " + select.value);
|
||||
}, function () {
|
||||
// User decided to cancel
|
||||
select.value = select.options[select
|
||||
.getAttribute("oldIndex")].value;
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
for (var i = 0; i < buttons.length; i++) {
|
||||
var option = document.createElement('option');
|
||||
option.setAttribute("type", "enum");
|
||||
option.setAttribute("class", "option-params");
|
||||
option.setAttribute("value", buttons[i].value);
|
||||
option.appendChild(document.createTextNode(buttons[i].title));
|
||||
select.add(option);
|
||||
}
|
||||
select.style.display = "none";
|
||||
|
||||
var right = document.createElement('span');
|
||||
right.setAttribute("class", "col-right");
|
||||
right.appendChild(select);
|
||||
return appendToContent(info, left, right);
|
||||
}
|
||||
|
||||
function createTitle(title, info) {
|
||||
// Creates left side of row-tag containing title. Title may hold additional
|
||||
// information, which is shown, when title-tag is clicked.
|
||||
|
||||
var left = document.createElement('span');
|
||||
if (info) {
|
||||
left.setAttribute("class", "col-left event-toggle-info");
|
||||
|
||||
left.onclick = function () {
|
||||
var infoBox = left.parentNode.childNodes[0];
|
||||
if (infoBox.style.display == "none") {
|
||||
infoBox.style.display = "block";
|
||||
} else {
|
||||
infoBox.style.display = "none";
|
||||
}
|
||||
}
|
||||
|
||||
left.innerHTML = title + "<sup><b>(i)</b></sup>";
|
||||
} else {
|
||||
left.setAttribute("class", "col-left");
|
||||
left.innerHTML = title;
|
||||
}
|
||||
return left;
|
||||
}
|
||||
|
||||
function createInfo(info) {
|
||||
// Creates info-box, which isn't visible by default but can be displayed.
|
||||
|
||||
var infoBox = document.createElement('div');
|
||||
infoBox.setAttribute("class", "info-box");
|
||||
|
||||
infoBox.onclick = function () {
|
||||
infoBox.style.display = "none";
|
||||
}
|
||||
|
||||
infoBox.innerHTML = info;
|
||||
return infoBox;
|
||||
}
|
||||
|
||||
function appendToContent(info, left, right) {
|
||||
// Cretees row-tag containing infoBox (not visible by default), left side
|
||||
// (span)
|
||||
// and right side (span).
|
||||
|
||||
var row = document.createElement('div');
|
||||
row.setAttribute("class", "row");
|
||||
if (info) {
|
||||
row.appendChild(createInfo(info));
|
||||
}
|
||||
for (var i = 1; i < arguments.length; i++)
|
||||
if (arguments[i]) {
|
||||
row.appendChild(arguments[i]);
|
||||
}
|
||||
return row;
|
||||
}
|
198
client/jsFiles/SEAWebClientMain.js
Normal file
198
client/jsFiles/SEAWebClientMain.js
Normal file
@ -0,0 +1,198 @@
|
||||
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
// % INIT
|
||||
|
||||
var MAXBLOCK = 4; // max number of blocks
|
||||
|
||||
var elements = []; // grid elements
|
||||
|
||||
var swiper = []; // This array contains main-swiper-Instances.
|
||||
|
||||
var hostPort = ""; // Address and port of static html-file.
|
||||
|
||||
var clientID = ""; // ID given by server when SSE-connection is established.
|
||||
|
||||
var clientTitle = ""; // Contains name of instrument and device.
|
||||
|
||||
var getUpdates = true;
|
||||
|
||||
var getUpdatesGraphics = true;
|
||||
|
||||
var initCommands = [];
|
||||
|
||||
var loadingShown = true;
|
||||
|
||||
var writePermission = false;
|
||||
|
||||
var menuMode = false;
|
||||
|
||||
var panelOn = true;
|
||||
|
||||
var firstState = 0;
|
||||
|
||||
function Settings() {
|
||||
// get key/value pairs from search part of the URL and fill into query
|
||||
var qstr = location.search;
|
||||
console.log(qstr);
|
||||
if (qstr) {
|
||||
var a = (qstr[0] === '?' ? qstr.substr(1) : qstr).split('&');
|
||||
for (var i = 0; i < a.length; i++) {
|
||||
var b = a[i].split('=');
|
||||
key = decodeURIComponent(b[0]);
|
||||
value = decodeURIComponent(b.slice(1).join("=").replace(/\+/g, '%20'));
|
||||
this[key] = value;
|
||||
}
|
||||
}
|
||||
this.treat = function (variable, shortcut, convert, defaultValue) {
|
||||
// the third argument should be:
|
||||
// None or omitted for a string
|
||||
// to_bool for converting to boolean
|
||||
// Number for converting to a number
|
||||
if (shortcut in this) {
|
||||
value = this[shortcut];
|
||||
if (convert) {
|
||||
value = convert(value);
|
||||
}
|
||||
} else {
|
||||
value = defaultValue;
|
||||
}
|
||||
//console.log(variable, value);
|
||||
window[variable] = value;
|
||||
return this;
|
||||
}
|
||||
this.add_init = function (shortcut, command, defaultValue) {
|
||||
if (shortcut in this) {
|
||||
value = to_bool(this[shortcut]);
|
||||
console.log(shortcut, value);
|
||||
} else {
|
||||
value = defaultValue;
|
||||
console.log(shortcut, value);
|
||||
}
|
||||
if (value) {
|
||||
initCommands.push(command);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
function to_bool(string) {
|
||||
// everything else than false, 0 or an empty string is considered as true
|
||||
return !/^(false|FALSE|False|0|)$/.test(string);
|
||||
}
|
||||
|
||||
// example: localhost:5000/SEAWebClient.html?hp=ldmzolliker:5000&dc=1
|
||||
// hostPort given and debugCommunication switched on
|
||||
new Settings()
|
||||
.treat("debugCommunication", "dc", 0, 0) // 1: debug synchronous comm. 2: debug syn and asyn comm
|
||||
.treat("debugGraphics", "dg", to_bool, false)
|
||||
.treat("hostPort", "hp", 0, location.hostname + ":" + location.port)
|
||||
.treat("showMain", "sm", to_bool, true)
|
||||
.treat("showConsole", "sc", to_bool, true)
|
||||
.treat("showOverview", "so", to_bool, true)
|
||||
.treat("showGraphics", "sg", to_bool, true)
|
||||
.treat("showAsync", "sa", to_bool, false)
|
||||
|
||||
function loadFirstBlocks() {
|
||||
|
||||
if (showMain) pushInitCommand("getblock?path=main&", "main")
|
||||
if (showConsole) pushInitCommand("console?", "console")
|
||||
if (nColumns == 1) { // probably mobile phone}
|
||||
if (showGraphics) pushInitCommand("gettime?time=-1800,0&", "graphics")
|
||||
if (showOverview) pushInitCommand("getblock?path=_overview&", "overview")
|
||||
} else {
|
||||
if (showOverview) pushInitCommand("getblock?path=_overview&", "overview")
|
||||
if (showGraphics) pushInitCommand("gettime?time=-1800,0&", "graphics")
|
||||
// last is shown first
|
||||
}
|
||||
}
|
||||
|
||||
function nextInitCommand() {
|
||||
// do the next init request
|
||||
if (initCommands.length > 0) {
|
||||
next = initCommands.shift();
|
||||
cmd = next[0]
|
||||
text = next[1]
|
||||
var loadingSpan = document.getElementsByClassName("loading-span")[0];
|
||||
loadingSpan.innerHTML = loadingSpan.innerHTML + "<br>loading " + htmlEscape(text) + " ...";
|
||||
reqJSON(0, "http://" + hostPort + "/" + cmd + "id=" + clientID, successHandler, errorHandler);
|
||||
} else if (loadingShown) {
|
||||
var loadingScreen = document.getElementsByClassName("loading-div")[0];
|
||||
loadingScreen.style.display = "none";
|
||||
loadingShown = false;
|
||||
if (location.hash) { // there was a #hash part
|
||||
var slideNames = location.hash.substr(1);
|
||||
gotoGroups(slideNames);
|
||||
}
|
||||
console.log("loading finished");
|
||||
}
|
||||
}
|
||||
|
||||
function pushInitCommand(cmd, text) {
|
||||
initCommands.push([cmd, text]);
|
||||
}
|
||||
|
||||
window.onload = function() {
|
||||
// Executed when loading of page is completed.
|
||||
|
||||
// Create grid-elements. (see also at
|
||||
// 'SEAWebClientResponsivity.js')
|
||||
elements = createGrid();
|
||||
// Number of shown columns 'm' and rows 'n' is determined depending on
|
||||
// available viewport-size.
|
||||
determineViewportSize();
|
||||
// Determine size of grid-elements depending on number of columns 'm' and
|
||||
// rows 'n'
|
||||
adjustGrid();
|
||||
// Create swiper-instances.
|
||||
for (var s = 0; s < MAXBLOCK; s++) {
|
||||
swiper[s] = insertSwiper(s);
|
||||
}
|
||||
var homeButton = document.getElementById("home-icon");
|
||||
homeButton.onclick = function () {
|
||||
window.location = "http://" + location.hostname + ":8800/";
|
||||
};
|
||||
buildUpdateConnection();
|
||||
if (location.hash) {
|
||||
console.log("hash in url", location.hash);
|
||||
initSlides = location.hash.substring(1);
|
||||
} else {
|
||||
initSlides = "";
|
||||
}
|
||||
// Initialisation will be continued, when SSE-connection is established
|
||||
// and id-message is obtained.
|
||||
// (see also at SEAWebClientCommunication.js)
|
||||
addEventListener("popstate", function (e) {
|
||||
if (e.state) {
|
||||
if (loadingShown) {
|
||||
if (initSlides != e.state.funarg) {
|
||||
console.log("hash mismatch", initSlides, e.state.funarg);
|
||||
initSlides = e.state.funarg;
|
||||
}
|
||||
} else {
|
||||
console.log("popstate", e.state.func, e.state.funarg);
|
||||
window[e.state.func](e.state.funarg);
|
||||
}
|
||||
} else {
|
||||
document.title = "SEA "+ clientTitle;
|
||||
for (var s=0; s<MAXBLOCK; s++) {
|
||||
swiper[s].slideTo(defaultSlidePos(s));
|
||||
}
|
||||
}
|
||||
})
|
||||
};
|
||||
|
||||
function toggleHeader() {
|
||||
// Show and hide box showing name of the current device ('see also
|
||||
// SEAWebClient.html')
|
||||
|
||||
var main_panel = document.getElementById("main-panel");
|
||||
panelOn = !panelOn;
|
||||
if (panelOn) {
|
||||
header.innerHTML = clientTitle
|
||||
/* header.setAttribute("style", "width: auto;"); */
|
||||
main_panel.setAttribute("style", "display: block;");
|
||||
} else {
|
||||
/* header.setAttribute("style", "width: 30px;"); */
|
||||
main_panel.setAttribute("style", "display: none;");
|
||||
}
|
||||
return true;
|
||||
}
|
151
client/jsFiles/SEAWebClientResponsivity.js
Normal file
151
client/jsFiles/SEAWebClientResponsivity.js
Normal file
@ -0,0 +1,151 @@
|
||||
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
// % RESPONSIVITY
|
||||
|
||||
var nColumns = 1; // Viewport is subdivided in nColumns columns.
|
||||
|
||||
var nRows = 1; // Viewport is subdivided in nRows rows.
|
||||
|
||||
var gridCountGraphics = 2; // Number of displayed graphics-swipers.
|
||||
|
||||
var MINWIDTH = 400; // Minimal width of block.
|
||||
|
||||
var MINHEIGHT = 700; // Minimal height of block.
|
||||
|
||||
function createGrid() {
|
||||
// Creates grid-elements. By default only the first one is shown
|
||||
// and
|
||||
// takes the whole viewport.
|
||||
var elements = [];
|
||||
for (var i = 0; i < 4; i++) {
|
||||
var element = document.createElement('div');
|
||||
element.setAttribute("class", "grid-element");
|
||||
document.getElementById("center").appendChild(element);
|
||||
elements.push(element);
|
||||
}
|
||||
return elements;
|
||||
}
|
||||
|
||||
function determineViewportSize() {
|
||||
// Number of columns 'nColumns' and rows 'nRows' is determined depending on available
|
||||
// viewport-size.
|
||||
|
||||
var width = window.innerWidth || document.documentElement.clientWidth
|
||||
|| document.body.clientWidth;
|
||||
var height = window.innerHeight || document.documentElement.clientHeight
|
||||
|| document.body.clientHeight;
|
||||
nColumns = 1;
|
||||
if (width > MINWIDTH * 1.8) {
|
||||
nColumns = 2;
|
||||
}
|
||||
if (width > MINWIDTH * 2.5) {
|
||||
nColumns = 3;
|
||||
}
|
||||
if (width > MINWIDTH * 3.5) {
|
||||
nColumns = 4;
|
||||
}
|
||||
nRows = 1;
|
||||
if (height > MINHEIGHT) {
|
||||
nRows = 2;
|
||||
}
|
||||
if (menuMode) {
|
||||
nRows = 1;
|
||||
nColumns = 1;
|
||||
}
|
||||
}
|
||||
|
||||
function sizeChange() {
|
||||
determineViewportSize();
|
||||
adjustGrid();
|
||||
}
|
||||
|
||||
function adjustGrid() {
|
||||
// Determines size of grid-elements depending on number of columns 'nColumns' and
|
||||
// rows 'nRows'
|
||||
|
||||
var width = window.innerWidth || document.documentElement.clientWidth
|
||||
|| document.body.clientWidth;
|
||||
var height = window.innerHeight || document.documentElement.clientHeight
|
||||
|| document.body.clientHeight;
|
||||
|
||||
switch (nColumns) {
|
||||
case 1:
|
||||
if (menuMode) {
|
||||
leftWidth = Math.min(100, MINWIDTH / width * 100);
|
||||
style(0,leftWidth + "vw","100vh");
|
||||
style(1); // hide
|
||||
style(2); // hide
|
||||
style(3); // hide
|
||||
} else {
|
||||
style(0,"100vw","100vh");
|
||||
style(1); // hide
|
||||
style(2); // hide
|
||||
style(3); // hide
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
rightWidth = Math.min(50, MINWIDTH / width * 100);
|
||||
leftWidth = 100 - rightWidth;
|
||||
if (nRows == 1) {
|
||||
style(0,leftWidth + "vw","100vh");
|
||||
style(1,rightWidth + "vw","100vh");
|
||||
style(2); // hide
|
||||
style(3); // hide
|
||||
} else {
|
||||
style(0,leftWidth + "vw","100vh");
|
||||
style(1,rightWidth + "vw","50vh");
|
||||
style(2); // hide
|
||||
style(3,rightWidth + "vw","50vh");
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
rightWidth = MINWIDTH / width * 100;
|
||||
leftWidth = 100 - rightWidth;
|
||||
if (nRows == 1) {
|
||||
style(0,leftWidth + "vw","100vh");
|
||||
style(1,rightWidth + "vw","100vh");
|
||||
style(2); // hide
|
||||
style(3); // hide
|
||||
} else {
|
||||
style(0,leftWidth + "vw","100vh");
|
||||
style(1,rightWidth + "vw","50vh");
|
||||
style(2); // hide
|
||||
style(3,rightWidth + "vw","50vh");
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
rightWidth = MINWIDTH / width * 100;
|
||||
leftWidth = 100 - 2 * rightWidth;
|
||||
if (nRows == 1) {
|
||||
style(0,leftWidth + "vw","100vh");
|
||||
style(1,rightWidth + "vw","100vh");
|
||||
style(2); // hide
|
||||
style(3,rightWidth + "vw","100vh");
|
||||
} else {
|
||||
style(0,leftWidth + "vw","100vh");
|
||||
style(1,rightWidth + "vw","50vh");
|
||||
style(2,rightWidth + "vw","50vh");
|
||||
style(3,(2 * rightWidth) + "vw","50vh");
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
function style(s, width, height) {
|
||||
if (width) {
|
||||
elements[s].style.display = "inline-block";
|
||||
elements[s].style.width = width;
|
||||
} else {
|
||||
elements[s].style.display = "none";
|
||||
}
|
||||
if (height) {
|
||||
elements[s].style.height = height;
|
||||
}
|
||||
elements[s].style.float = "left";
|
||||
}
|
||||
|
||||
function isTouchDevice() {
|
||||
return !!('ontouchstart' in window)
|
||||
|| !!('msmaxtouchpoints' in window.navigator);
|
||||
};
|
42
client/jsFiles/SEAWebClientStart.js
Normal file
42
client/jsFiles/SEAWebClientStart.js
Normal file
@ -0,0 +1,42 @@
|
||||
var showSettings = false;
|
||||
|
||||
function toggleSettings() {
|
||||
// Shows and hides settings.
|
||||
|
||||
console.log("toggle settings");
|
||||
if (showSettings) {
|
||||
document.getElementsByClassName("start-settings-checkboxes")[0].style.display = "none";
|
||||
document.getElementsByClassName("start-settings-show-hide")[0].innerHTML = "show";
|
||||
showSettings = false;
|
||||
} else {
|
||||
document.getElementsByClassName("start-settings-checkboxes")[0].style.display = "inline";
|
||||
document.getElementsByClassName("start-settings-show-hide")[0].innerHTML = "hide";
|
||||
showSettings = true;
|
||||
}
|
||||
}
|
||||
|
||||
function followLink(destination) {
|
||||
// Build query string and load new page.
|
||||
|
||||
var checkboxes = document.getElementsByClassName("start-checkbox");
|
||||
var query = "";
|
||||
// Loop through settings-checkboxes.
|
||||
for (var i = 0; i < checkboxes.length; i++) {
|
||||
if (checkboxes[i].checked != checkboxes[i].defaultChecked) {
|
||||
if (query === "") {
|
||||
query = "?";
|
||||
} else {
|
||||
query += "&";
|
||||
}
|
||||
query += checkboxes[i].name + "=";
|
||||
if (checkboxes[i].checked) {
|
||||
query += "1";
|
||||
} else {
|
||||
query += "0";
|
||||
}
|
||||
}
|
||||
}
|
||||
destination += query;
|
||||
console.log(destination);
|
||||
window.location = destination;
|
||||
}
|
174
client/jsFiles/SEAWebClientSwiper.js
Normal file
174
client/jsFiles/SEAWebClientSwiper.js
Normal file
@ -0,0 +1,174 @@
|
||||
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
// % SWIPER
|
||||
|
||||
function insertSwiper(s) {
|
||||
// Create an empty swiper-instance and append the swiper-container to
|
||||
// 'grid-element' s.
|
||||
|
||||
var container = document.createElement('div');
|
||||
container.setAttribute("class", "swiper-container swiper-container-main");
|
||||
elements[s].appendChild(container);
|
||||
|
||||
var swiperwrapper = document.createElement('div');
|
||||
swiperwrapper.setAttribute("class", "swiper-wrapper swiper-wrapper-main");
|
||||
swiperwrapper.setAttribute("s", s);
|
||||
container.appendChild(swiperwrapper);
|
||||
|
||||
var paginationWrapper = document.createElement('div');
|
||||
paginationWrapper.setAttribute("class", "swiper-pagination");
|
||||
container.appendChild(paginationWrapper);
|
||||
|
||||
var buttonPrev = document.createElement("div");
|
||||
buttonPrev.setAttribute("class", "swiper-button-prev swiper-button-black");
|
||||
|
||||
var buttonNext = document.createElement("div");
|
||||
buttonNext.setAttribute("class", "swiper-button-next swiper-button-black");
|
||||
|
||||
var swiper = new Swiper(container, {
|
||||
direction : 'horizontal',
|
||||
pagination: {
|
||||
el: paginationWrapper,
|
||||
clickable: true
|
||||
},
|
||||
spaceBetween : 0,
|
||||
navigation:{
|
||||
prevEl: buttonPrev,
|
||||
nextEl: buttonNext
|
||||
}
|
||||
});
|
||||
//console.log(swiper);
|
||||
|
||||
|
||||
if (!isTouchDevice()) {
|
||||
// Add swiper-button.
|
||||
swiper.params.noSwipingClass = "swiper-slide-main";
|
||||
container.appendChild(buttonPrev);
|
||||
container.appendChild(buttonNext);
|
||||
}
|
||||
|
||||
return swiper;
|
||||
}
|
||||
|
||||
function findSlide(s, type) {
|
||||
var i;
|
||||
for (i = 0; i < swiper[s].slides.length; i++) {
|
||||
if (swiper[s].slides[i].getAttribute("slide-type") === type) {
|
||||
return swiper[s].slides[i];
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function replaceSlideContent(slide, title, content) {
|
||||
titlewrapper = slide.childNodes[0].childNodes[0];
|
||||
titlewrapper.innerHTML = title;
|
||||
slide.replaceChild(content, slide.childNodes[1])
|
||||
}
|
||||
|
||||
function insertSlide(s, title, type, content) {
|
||||
// Inserts new group to instance s of Swiper.
|
||||
|
||||
var slide = findSlide(s, type);
|
||||
if (slide) { // slide already exists
|
||||
replaceSlideContent(slide, title, content);
|
||||
return
|
||||
}
|
||||
var panel = document.createElement('div');
|
||||
panel.setAttribute("class", "panel");
|
||||
|
||||
titlewrapper = document.createElement('span');
|
||||
titlewrapper.innerHTML = title;
|
||||
panel.appendChild(titlewrapper);
|
||||
if (type == "_overview" || type == "main") {
|
||||
//panel.appendChild(createHomeButton(s));
|
||||
} else if (type != "graphics" && type != "_inst_select" && type != "console") {
|
||||
panel.appendChild(createCloseButton(s));
|
||||
}
|
||||
|
||||
/*if (type === "graphics") {
|
||||
panel.appendChild(createUpdateButton(s));
|
||||
}*/
|
||||
|
||||
slide = document.createElement('div');
|
||||
slide.setAttribute("class", "swiper-slide swiper-slide-main");
|
||||
// Store type so it can be found easiely later.
|
||||
slide.setAttribute("slide-type", type);
|
||||
slide.appendChild(panel);
|
||||
slide.appendChild(content);
|
||||
// Graphics-slide is put at mostleft position.
|
||||
if (type == "graphics" || type == "_overview") {
|
||||
// Remove old graphics-slide.
|
||||
/* see above
|
||||
if(swiper[0].slides[0].getAttribute("slide-type") === "graphics"){
|
||||
swiper[0].removeSlide(0);
|
||||
}
|
||||
*/
|
||||
swiper[s].prependSlide(slide);
|
||||
swiper[s].slideTo(0);
|
||||
} else if (type == "console") {
|
||||
swiper[s].appendSlide(slide);
|
||||
if (s === 3) {
|
||||
// Slide mostright swiper-instance to last position (console)
|
||||
swiper[3].slideNext();
|
||||
}
|
||||
} else {
|
||||
swiper[s].appendSlide(slide);
|
||||
if (swiper[s].slides.length > 1) {
|
||||
var consoleslide = swiper[s].slides[swiper[s].slides.length - 2];
|
||||
if (consoleslide.getAttribute["slide-type"] == "console") {
|
||||
// shift Console-slide to mostright position.
|
||||
swiper[s].removeSlide(swiper[s].slides.length - 2);
|
||||
swiper[s].appendSlide(consoleslide);
|
||||
// Slide to position of new slide
|
||||
swiper[s].slideTo(swiper[s].slides.length - 2);
|
||||
} else {
|
||||
swiper[s].slideTo(swiper[s].slides.length - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function createCloseButton(s) {
|
||||
// Creates 'span'-element containing close-button.
|
||||
var wrapper = document.createElement('span');
|
||||
wrapper.onclick = function () {
|
||||
swiper[s].removeSlide(swiper[s].activeIndex);
|
||||
swiper[s].slidePrev();
|
||||
};
|
||||
var closeButton = '<svg class="interactive icon slide-close-icon" fill="#000000" height="24" viewBox="0 0 24 24" width="24"><path d="M19 6.41L17.6 5 12 10.6 6.4 5 5 6.4 10.6 12 5 17.6 6.4 19 12 13.4 17.6 19 19 17.6 13.4 12z"/><path d="M0 0h24v24H0z" fill="none"/></svg>';
|
||||
wrapper.innerHTML = closeButton;
|
||||
return wrapper;
|
||||
}
|
||||
|
||||
function createUpdateButton(s){
|
||||
// Creates 'span'-element containing update-button (Should be removed later!)
|
||||
var button = document.createElement('span');
|
||||
button.setAttribute("class","interactive toggle-updates-graphics")
|
||||
button.onclick = function () {
|
||||
getUpdatesGraphics = ! getUpdatesGraphics;
|
||||
button.innerHTML = "updates = "+getUpdatesGraphics;
|
||||
};
|
||||
button.innerHTML = "updates: "+getUpdatesGraphics;
|
||||
return button;
|
||||
}
|
||||
|
||||
function defaultSlidePos(s) {
|
||||
return s < 3 ? 0 : swiper[s].slides.length-1;
|
||||
}
|
||||
|
||||
function getSlideNames() {
|
||||
var names = []
|
||||
for (var s=0; s<MAXBLOCK; s++) {
|
||||
var sw = swiper[s];
|
||||
var name = "";
|
||||
if (sw.activeIndex != defaultSlidePos(s)) {
|
||||
name = sw.slides[sw.activeIndex].getAttribute("slide-type");
|
||||
}
|
||||
names.push();
|
||||
}
|
||||
for (var s=MAXBLOCK-1; s>=0; s--) {
|
||||
if (names[s] != "") break;
|
||||
names.pop();
|
||||
}
|
||||
return names;
|
||||
}
|
68
client/main.html
Normal file
68
client/main.html
Normal file
@ -0,0 +1,68 @@
|
||||
<html>
|
||||
<body>
|
||||
<a href="http://localhost:5000/console.html" target=console>console</a>
|
||||
<a href="http://localhost:5000/group.html?path=/nv" target=group>group</a>
|
||||
<button onclick="action.value='getblock?path=/nv&id=*';">?getblock</button>
|
||||
<button onclick="action.value='updateblock?path=/nv&id=*';">?updateblock</button>
|
||||
<button onclick="action.value='console?id=*';">?console</button>
|
||||
<button onclick="action.value='gettime?time=-1800,0&id=*';">?gettime</button>
|
||||
<button onclick="action.value='getvars?time=-1800,0&id=*';">?getvars</button>
|
||||
<button onclick="action.value='graph?time=-1800,0&variables=tt.tm,lev&id=*';">?graph</button><br>
|
||||
<input type=text value="console?id=*" size=120 id=action>
|
||||
<button onclick='act();'>Send</button>
|
||||
<div id=result>
|
||||
</div><p>
|
||||
<textarea rows=50 cols=132 id=t>
|
||||
</textarea>
|
||||
<script type="text/javascript">
|
||||
|
||||
var myid = 0
|
||||
var result = document.getElementById("result")
|
||||
var action = document.getElementById("action")
|
||||
|
||||
function getJSON(url, successHandler, errorHandler) {
|
||||
var xhr = typeof XMLHttpRequest != 'undefined'
|
||||
? new XMLHttpRequest()
|
||||
: new ActiveXObject('Microsoft.XMLHTTP');
|
||||
console.log("fired JSON request", url)
|
||||
xhr.open('get', url, true);
|
||||
xhr.onreadystatechange = function() {
|
||||
var status;
|
||||
var data;
|
||||
// https://xhr.spec.whatwg.org/#dom-xmlhttprequest-readystate
|
||||
if (xhr.readyState == 4) { // `DONE`
|
||||
status = xhr.status;
|
||||
if (status == 200) {
|
||||
data = JSON.parse(xhr.responseText);
|
||||
successHandler && successHandler(data);
|
||||
} else {
|
||||
errorHandler && errorHandler(status);
|
||||
}
|
||||
}
|
||||
};
|
||||
xhr.send();
|
||||
};
|
||||
|
||||
function insert(link) {
|
||||
action.value = link
|
||||
}
|
||||
|
||||
function act() {
|
||||
getJSON("http://localhost:5000/" + action.value.split("*").join(myid),
|
||||
function(message) { result.innerHTML = JSON.stringify(message); },
|
||||
function(status) { console.log(status); }
|
||||
)
|
||||
}
|
||||
|
||||
var evtSrc = new EventSource("http://localhost:5000/update");
|
||||
|
||||
evtSrc.onmessage = function(e) {
|
||||
var message = JSON.parse(e.data);
|
||||
if (message.type == "id") {
|
||||
myid = message.id
|
||||
}
|
||||
t.value = t.value + e.data + "\n";
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
70
client/plotex.html
Normal file
70
client/plotex.html
Normal file
@ -0,0 +1,70 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<script src="externalFiles/mjs_plot_0_3_n.js"></script>
|
||||
</head>
|
||||
<!body>
|
||||
<body onresize="draw_graphs()" onload="draw_graphs()">
|
||||
<canvas id="democanvas" width="600" height="400"></canvas>
|
||||
<script>
|
||||
//make a graph object
|
||||
time = [0,1,2,3,4,5];
|
||||
pot = [2,4,3,4,null,1];
|
||||
still = [9,8,7,6,5,4];
|
||||
var pressure_graph = mjs_plot.new_graph("pressure_graph","democanvas");
|
||||
//give it data
|
||||
pressure_graph.set_data([[time,pot],[time,still]]);
|
||||
pressure_graph.set_captions(['pot','still']);
|
||||
//set up some graphics styling (optional)
|
||||
pressure_graph.default_graphics_style.title = "Pressures";
|
||||
pressure_graph.default_graphics_style.x_axis_title = "Hours";
|
||||
pressure_graph.default_graphics_style.y_axis_title = "pressure mbar";
|
||||
pressure_graph.default_graphics_style.color_bg = '#fff';
|
||||
//plot the graph
|
||||
pressure_graph.reset();
|
||||
pressure_graph.mjs_plot();
|
||||
tim = 5;
|
||||
saved_time = 5;
|
||||
live = true;
|
||||
function addPoint() {
|
||||
pot.push(pot[tim]+0.1);
|
||||
still.push(still[tim]+0.1);
|
||||
tim += 1;
|
||||
time.push(tim);
|
||||
if (pressure_graph.busy()) {
|
||||
return;
|
||||
}
|
||||
if (live) {
|
||||
if (saved_time > pressure_graph.graphics_style.x_auto_max) {
|
||||
live = false;
|
||||
console.log("live", live);
|
||||
return;
|
||||
}
|
||||
if (tim > pressure_graph.graphics_style.x_auto_max) {
|
||||
pressure_graph.graphics_style.x_scale_auto_max = false;
|
||||
pressure_graph.graphics_style.x_manual_max = tim;
|
||||
}
|
||||
} else if (tim < pressure_graph.graphics_style.x_auto_max) {
|
||||
live = true;
|
||||
console.log("live", live);
|
||||
}
|
||||
saved_time = tim;
|
||||
pressure_graph.set_data([[time,pot],[time,still]]);
|
||||
pressure_graph.mjs_plot();
|
||||
}
|
||||
|
||||
setInterval(addPoint, 1000);
|
||||
|
||||
|
||||
function draw_graphs(){
|
||||
pressure_graph.canvas.width = window.innerWidth - 20;
|
||||
pressure_graph.canvas.height = window.innerHeight - 20;
|
||||
//tell the graph to plot
|
||||
pressure_graph.mjs_plot();
|
||||
}
|
||||
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
61
client/select.html
Normal file
61
client/select.html
Normal file
@ -0,0 +1,61 @@
|
||||
<html>
|
||||
<body>
|
||||
<table>
|
||||
<tr><td>
|
||||
<a href='http://samenv.psi.ch:8850/'>DMC</a>
|
||||
</td><td>
|
||||
<a href='http://samenv.psi.ch:8851/'>HRPT</a>
|
||||
</td><td>
|
||||
<a href='http://samenv.psi.ch:8852/'>ZEBRA</a>
|
||||
</td><td>
|
||||
<a href='http://samenv.psi.ch:8853/'>POLDI</a>
|
||||
</td></tr><tr><td>
|
||||
<a href='http://samenv.psi.ch:8854/'>FOCUS</a>
|
||||
</td><td>
|
||||
<a href='http://samenv.psi.ch:8855/'>TASP</a>
|
||||
</td><td>
|
||||
<a href='http://samenv.psi.ch:8856/'>RITA2</a>
|
||||
</td><td>
|
||||
<a href='http://samenv.psi.ch:8857/'>EIGER</a>
|
||||
</td></tr><tr><td>
|
||||
<a href='http://samenv.psi.ch:8854/'>SANS 1</a>
|
||||
</td><td>
|
||||
<a href='http://samenv.psi.ch:8855/'>SANS 2</a>
|
||||
</td><td>
|
||||
<a href='http://samenv.psi.ch:8856/'>AMOR</a>
|
||||
</td><td>
|
||||
<a href='http://samenv.psi.ch:8857/'>BOA</a>
|
||||
</td></tr><tr><td>
|
||||
<a href='http://samenv.psi.ch:8801/'>PREP1</a>
|
||||
</td><td>
|
||||
<a href='http://samenv.psi.ch:8802/'>PREP2</a>
|
||||
</td><td>
|
||||
<a href='http://samenv.psi.ch:8803/'>PREP3</a>
|
||||
</td><td>
|
||||
<a href='http://samenv.psi.ch:8804/'>PREP4</a>
|
||||
</td></tr><tr><td>
|
||||
<a href='http://samenv.psi.ch:8805/'>PREP5</a>
|
||||
</td><td>
|
||||
<a href='http://samenv.psi.ch:8806/'>PREP6</a>
|
||||
</td><td>
|
||||
<a href='http://samenv.psi.ch:8807/'>PREP7</a>
|
||||
</td><td>
|
||||
<a href='http://samenv.psi.ch:8808/'>PREP8</a>
|
||||
</td></tr><tr><td>
|
||||
<a href='http://samenv.psi.ch:8809/'>PREP9</a>
|
||||
</td><td>
|
||||
<a href='http://samenv.psi.ch:8800/'>PREP0</a>
|
||||
</td></tr><tr><td>
|
||||
<a href='http://samenv.psi.ch:8810/'>LAB0</a>
|
||||
</td><td>
|
||||
<a href='http://samenv.psi.ch:8811/'>LAB1</a>
|
||||
</td><td>
|
||||
<a href='http://samenv.psi.ch:8812/'>LAB2</a>
|
||||
</td><td>
|
||||
<a href='http://samenv.psi.ch:8813/'>LAB3</a>
|
||||
</td></tr><tr><td>
|
||||
<a href='http://samenv.psi.ch:8814/'>LAB4</a>
|
||||
</td></tr>
|
||||
</table>
|
||||
</body>
|
||||
</html>
|
84
client/touchtest.html
Normal file
84
client/touchtest.html
Normal file
@ -0,0 +1,84 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta name="viewport"
|
||||
content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no" />
|
||||
<meta name="apple-mobile-web-app-capable" content="yes" />
|
||||
<meta name="apple-mobile-web-app-status-bar-style"
|
||||
content="black-translucent" />
|
||||
</head>
|
||||
<body>
|
||||
<canvas id=inp width='300' height='500' style="border:1px solid #000000;"></canvas>
|
||||
<div id=out style="width: 300px;"></div>
|
||||
<script>
|
||||
var canvas=document.getElementById("inp");
|
||||
var rect = canvas.getBoundingClientRect();
|
||||
console.log(rect);
|
||||
// Setup canvas and expose context via ctx variable
|
||||
ctx=canvas.getContext("2d");
|
||||
function strt(touch) {
|
||||
return {i:touch.identifier,x:touch.pageX,y:touch.pageY}
|
||||
}
|
||||
function stre(event) {
|
||||
if (event.touches) {
|
||||
t = {};
|
||||
for (var i=0; i<event.touches.length;i++) {
|
||||
id=event.touches[i].identifier.toString();
|
||||
t[id] = strt(event.touches[i]);
|
||||
}
|
||||
tc = [];
|
||||
for (var i=0; i<event.changedTouches.length;i++) {
|
||||
id=event.touches[i].identifier.toString();
|
||||
t[id]['changed'] = 1;
|
||||
}
|
||||
for (var i=0; i<event.targetTouches.length;i++) {
|
||||
id=event.touches[i].identifier.toString();
|
||||
t[id]['target'] = 1;
|
||||
}
|
||||
}
|
||||
return {type:event.type,x:event.pageX,y:event.pageY,t:t};
|
||||
}
|
||||
|
||||
var styles=["rgba(0, 0, 200, 1)", "rgba(0, 255, 0, 1)", "rgba(255, 0, 0, 1)"]
|
||||
canvas.addEventListener('touchstart', function(event) {
|
||||
for (var i = 0; i < event.touches.length; i++) {
|
||||
var touch = event.touches[i];
|
||||
ctx.beginPath();
|
||||
ctx.arc(touch.pageX-rect.left, touch.pageY-rect.top, 5, 0, 2*Math.PI, true);
|
||||
ctx.lineWidth = 2.0;
|
||||
ctx.strokeStyle = styles[i];
|
||||
ctx.stroke();
|
||||
}
|
||||
}, false);
|
||||
canvas.addEventListener('touchmove', function(event) {
|
||||
document.getElementById("out").innerHTML = JSON.stringify(stre(event));
|
||||
event.preventDefault();
|
||||
for (var i = 0; i < event.touches.length; i++) {
|
||||
var touch = event.touches[i];
|
||||
ctx.beginPath();
|
||||
ctx.arc(touch.pageX-rect.left, touch.pageY-rect.top, 1, 0, 2*Math.PI, true);
|
||||
ctx.lineWidth = 2.0;
|
||||
ctx.strokeStyle = styles[i];
|
||||
ctx.stroke();
|
||||
}
|
||||
}, false);
|
||||
canvas.addEventListener('touchend', function(event) {
|
||||
for (var i = 0; i < event.changedTouches.length; i++) {
|
||||
var touch = event.changedTouches[i];
|
||||
ctx.beginPath();
|
||||
ctx.arc(touch.pageX-rect.left, touch.pageY-rect.top, 50, 0, 2*Math.PI, true);
|
||||
ctx.lineWidth = 2.0;
|
||||
ctx.strokeStyle = styles[i];
|
||||
ctx.stroke();
|
||||
}
|
||||
}, false);
|
||||
canvas.addEventListener('click', function(event) {
|
||||
console.log(event);
|
||||
ctx.beginPath();
|
||||
ctx.arc(event.clientX-rect.left, event.clientY - rect.top, 2, 0, 2*Math.PI, true);
|
||||
ctx.lineWidth = 2.0;
|
||||
ctx.strokeStyle = "rgba(0, 0, 200, 0.8)";
|
||||
ctx.stroke();
|
||||
}, false);
|
||||
|
||||
</script>
|
||||
</body></html>
|
BIN
doc/Screen Shot sea.png
Normal file
BIN
doc/Screen Shot sea.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 146 KiB |
1
doc/blocks.tsv
Normal file
1
doc/blocks.tsv
Normal file
@ -0,0 +1 @@
|
||||
1 2 3 4
|
Can't render this file because it contains an unexpected character in line 1 and column 36.
|
35
doc/graphics_todo.txt
Normal file
35
doc/graphics_todo.txt
Normal file
@ -0,0 +1,35 @@
|
||||
Grafik:
|
||||
|
||||
- Einbindung in slider
|
||||
|
||||
ok, aber Responsivity fehlt noch
|
||||
|
||||
- updates funktionieren manchmal nicht (könnte auch am Server liegen)
|
||||
|
||||
- marker linie nicht genau synchronisiert
|
||||
|
||||
- Zoom-Rechteck funktioniert teilweise
|
||||
|
||||
- Zoom selbst muss noch implementiert werden
|
||||
|
||||
- Im Moment wird die Zeitachse erst gezeichnet, wenn der erste Update kommt
|
||||
dies muss noch überdacht werden.
|
||||
Zeitachse muss an zwei stellen im Code erzeugt werden (in Funktion auslagern).
|
||||
|
||||
- die Variable begin bedeutet aktuell:
|
||||
|
||||
a) die erste Zeitspanne (zurück)
|
||||
b) der freie Platz (Zukunft)
|
||||
|
||||
dies muss in 2 Variablen aufgeteilt werden
|
||||
(b eher als absolute Zeit)
|
||||
|
||||
- MAXBLOCKGRAPHICS (sowie auch MAXBLOCK) wieder einführen
|
||||
höhen müssen noch berechnet werden (aktuell fix im css)
|
||||
|
||||
- im Moment sind Grafikslider auf (MAXBLOCKGRAPHICS = 1) gesetzt,
|
||||
sollte aber mit mehreren funktionieren.
|
||||
|
||||
- y-domain: statt min/max quantile(?) verwenden
|
||||
|
||||
- D3: müssen kurven neu gezeichnet werden, oder kann man auch ansetzen?
|
41
doc/message_chain.txt
Normal file
41
doc/message_chain.txt
Normal file
@ -0,0 +1,41 @@
|
||||
U id : if showMain : CHAIN getblock/main (accept-block, draw, redraw)
|
||||
|
||||
R draw: if main: if showConsole: CHAIN console (accept-console)
|
||||
else: update slides in all swiper instances
|
||||
|
||||
R accept-console: if showGraphics: CHAIN gettime (time)
|
||||
elif showOverviews: CHAIN getblock FINI
|
||||
else FINI
|
||||
|
||||
R time: CHAIN getvars (var_list)
|
||||
|
||||
R var_list: CHAIN graph (graph-draw)
|
||||
|
||||
R graph-draw: FINI CHAIN updategraph
|
||||
|
||||
R accept-graph: pass
|
||||
|
||||
U redraw: CHAIN getblock (accept-block)
|
||||
|
||||
U update: updateValues
|
||||
|
||||
U graph: createCharts
|
||||
U graph-update: updateCharts
|
||||
|
||||
U command: add to history / add to console
|
||||
U reply: add to console
|
||||
|
||||
|
||||
R accept-block: pass
|
||||
|
||||
|
||||
R error: ERROR
|
||||
|
||||
|
||||
1. getblock/main
|
||||
2. console
|
||||
3. gettime
|
||||
|
||||
console "/console?"
|
||||
graph "/gettime?time=-10,0&"
|
||||
overview "/getblock?path=_overview&"
|
201
doc/protocol.txt
Normal file
201
doc/protocol.txt
Normal file
@ -0,0 +1,201 @@
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
***** ServerSentEvents *****
|
||||
|
||||
The only constantly open connection:
|
||||
|
||||
/updates
|
||||
|
||||
response: <id-message> <update-message> <redraw-message> <console-update-message> <graph-update-message>
|
||||
|
||||
the id-message is got immediately, later a mix of all other types of messages may be received
|
||||
|
||||
*********************************************************************************************************************************
|
||||
|
||||
<id-message> = {
|
||||
"type": "id",
|
||||
"id":<id>,
|
||||
"title": <title>
|
||||
}
|
||||
|
||||
<update-message> = {
|
||||
"type": "update",
|
||||
"updates": [{"name": <name0>, "value": <value0>}, ...]
|
||||
}
|
||||
|
||||
<redraw-message> = {
|
||||
"type": "redraw",
|
||||
"path": <path>
|
||||
}
|
||||
|
||||
<console-update-message> = {
|
||||
"type": "command" | "reply",
|
||||
"origin": "self" | "other",
|
||||
"lines": <line>
|
||||
}
|
||||
|
||||
<graph-update-message> = {
|
||||
"type": "graph-update",
|
||||
"reduced": true/false,
|
||||
"time": <server-time>,
|
||||
"graph": {
|
||||
"<name1>": [[<time>,<value>],[<time>,<value>]...
|
||||
"<name2>": [[<time>,<value>],[<time>,<value>]...
|
||||
...
|
||||
}
|
||||
}
|
||||
|
||||
<graph-redraw-message> = {
|
||||
"type": "graph-redraw"
|
||||
}
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
***** XMLHttp *****
|
||||
|
||||
All other connections are to be closed (getJSON):
|
||||
|
||||
*********************************************************************************************************************************
|
||||
/getblock?path=<path>&id=<id>
|
||||
|
||||
response: <draw-message>
|
||||
|
||||
<draw-message> = {
|
||||
"type": "draw",
|
||||
"path": <path>,
|
||||
"components": [<component0>, <component1>, ...]
|
||||
}
|
||||
|
||||
*********************************************************************************************************************************
|
||||
|
||||
<component> = <input> | <rdonly> | <checkbox> | <radio-group>
|
||||
|
||||
<input> = {
|
||||
"type": "input",
|
||||
"name": <variable name>,
|
||||
"title": <title>
|
||||
<optional-attributes>
|
||||
}
|
||||
|
||||
<rdonly> = {
|
||||
"type": "rdonly",
|
||||
"name": <variable name>,
|
||||
"title": <title>
|
||||
<optional-attributes>
|
||||
}
|
||||
|
||||
<checkbox> = {
|
||||
"type": "checkbox",
|
||||
"name": <variable name>,
|
||||
"title": <title>
|
||||
<optional-attributes>
|
||||
}
|
||||
|
||||
<radio-group> = {
|
||||
"type": "radio",
|
||||
"name": <variable name>,
|
||||
"title": <title>,
|
||||
"buttons": [{"value": <value0>, "title": <title0>} , ...],
|
||||
<optional-attributes>
|
||||
}
|
||||
|
||||
<optional-attributes> =
|
||||
["info": <tool-tip-text> ,]
|
||||
|
||||
|
||||
*********************************************************************************************************************************
|
||||
|
||||
/updateblock?path=<path>&id=<id>
|
||||
|
||||
response: <accept-block-message> (and from now on, update-messages (incl. initial updates) are sent)
|
||||
|
||||
<accept-block-message> = {
|
||||
"type": "accept-block",
|
||||
}
|
||||
|
||||
*********************************************************************************************************************************
|
||||
|
||||
/sendcommand?command=<command>&id=<id>
|
||||
|
||||
response: <accept-command-message>
|
||||
|
||||
<accept-command-message> = {
|
||||
"type": "accept-command",
|
||||
}
|
||||
|
||||
*********************************************************************************************************************************
|
||||
/gettime?time=<start>,<end>&id=<id>
|
||||
|
||||
response: <time-message>
|
||||
|
||||
<time-message> = {
|
||||
"type":"time",
|
||||
"time": [<start>, <end>]
|
||||
}
|
||||
|
||||
*********************************************************************************************************************************
|
||||
|
||||
/getvars?time=<time>&id=<id>
|
||||
|
||||
response: <varlist-message>
|
||||
|
||||
<varlist-message> = {
|
||||
"type":"var_list",
|
||||
"blocks": [
|
||||
{
|
||||
"tag":"K_2",
|
||||
"unit": "K",
|
||||
"curves": [
|
||||
{
|
||||
"name":<name1>,
|
||||
"label":<label1>,
|
||||
"color":<color1>
|
||||
},
|
||||
{
|
||||
"name":<name2>,
|
||||
...
|
||||
} ...
|
||||
]
|
||||
},
|
||||
{
|
||||
"tag":"mbar",
|
||||
"unit": "mbar",
|
||||
"curves": ...
|
||||
},
|
||||
...
|
||||
]
|
||||
}
|
||||
|
||||
*********************************************************************************************************************************
|
||||
|
||||
/updategraph?id=<id>
|
||||
|
||||
response: <accept-graph-message>
|
||||
|
||||
<accept-graph-message> = = {
|
||||
"type": "accept-graph"
|
||||
}
|
||||
|
||||
*********************************************************************************************************************************
|
||||
|
||||
/graph?time=<start>,<end>&variables=<variable list>&id=<id>
|
||||
|
||||
response: <graph-draw-message>
|
||||
|
||||
<graph-draw-message> = = {
|
||||
"type": "graph-draw",
|
||||
"reduced": true/false,
|
||||
"graph": {
|
||||
"<name1>": [[<time>,<value>],[<time>,<value>]...
|
||||
"<name2>": [[<time>,<value>],[<time>,<value>]...
|
||||
...
|
||||
}
|
||||
|
||||
*********************************************************************************************************************************
|
||||
|
||||
/console?id=<id>
|
||||
|
||||
response: <accept-console-message> (and from now on, console-updates-messages (incl. history) are sent)
|
||||
|
||||
<accept-console-message> = {
|
||||
"type": "accept-console",
|
||||
}
|
||||
|
17
doc/urls for graphics.txt
Normal file
17
doc/urls for graphics.txt
Normal file
@ -0,0 +1,17 @@
|
||||
user serverside events for all updates, from the first message
|
||||
the client id can be retrieved
|
||||
|
||||
localhost:8000/update
|
||||
|
||||
get the actual data for the chart:
|
||||
|
||||
localhost:8000/graph?variables=tt,treg.set.reg&time=-1800,0&id=<client-id>
|
||||
|
||||
activate updates for chart:
|
||||
|
||||
localhost:8000/graphupdate?id=<client-id>
|
||||
|
||||
|
||||
Start without main and blocks:
|
||||
|
||||
localhost:8000/?sg=1&sm=0&sc=0
|
Reference in New Issue
Block a user